diff --git a/buidler.config.js b/buidler.config.js index 545f7c0..de2ae04 100644 --- a/buidler.config.js +++ b/buidler.config.js @@ -11,17 +11,21 @@ const GelatoCoreLib = require("@gelatonetwork/core"); require("dotenv").config(); const INFURA_ID = process.env.INFURA_ID; assert.ok(INFURA_ID, "no Infura ID in process.env"); +const INSTA_MASTER = "0xb1DC62EC38E6E3857a887210C38418E4A17Da5B2"; // ================================= CONFIG ========================================= module.exports = { defaultNetwork: "ganache", networks: { ganache: { + timeout: 150000, // Standard config url: "http://localhost:8545", fork: `https://mainnet.infura.io/v3/${INFURA_ID}`, + unlocked_accounts: [INSTA_MASTER], // Custom GelatoCore: "0x1d681d76ce96E4d70a88A00EBbcfc1E47808d0b8", + InstaMaster: INSTA_MASTER, InstaIndex: "0x2971AdFa57b20E5a416aE5a708A8655A9c74f723", InstaList: "0x4c8a1BEb8a87765788946D6B19C6C6355194AbEb", InstaConnectors: "0xD6A602C01a023B98Ecfb29Df02FBA380d3B21E0c", @@ -31,9 +35,13 @@ module.exports = { ConnectGelato: "0x37A7009d424951dd5D5F155fA588D9a03C455163", ConnectMaker: "0xac02030d8a8F49eD04b2f52C394D3F901A10F8A9", ConnectCompound: "0x07F81230d73a78f63F0c2A3403AD281b067d28F8", + ConnectInstaPool: "0xCeF5f3c402d4fef76A038e89a4357176963e1464", + MakerResolver: "0x0A7008B38E7015F8C36A49eEbc32513ECA8801E5", DAI: "0x6b175474e89094c44da98b954eedeac495271d0f", DAI_UNISWAP: "0x2a1530C4C41db0B0b2bB646CB5Eb1A67b7158667", CDAI: "0x5d3a536E4D6DbD6114cc1Ead35777bAB948E3643", + DssCdpManager: "0x5ef30b9986345249bc32d8928B7ee64DE9435E39", + GetCdps: "0x36a724Bd100c39f0Ea4D3A20F7097eE01A8Ff573", ProviderModuleDSA: "0x0C25452d20cdFeEd2983fa9b9b9Cf4E81D6f2fE2", }, }, diff --git a/contracts/ConditionMakerVaultIsSafe.sol b/contracts/ConditionMakerVaultIsSafe.sol new file mode 100644 index 0000000..987d9c3 --- /dev/null +++ b/contracts/ConditionMakerVaultIsSafe.sol @@ -0,0 +1,106 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import { + GelatoConditionsStandard +} from "@gelatonetwork/core/contracts/conditions/GelatoConditionsStandard.sol"; +import {GelatoBytes} from "./GelatoBytes.sol"; +import "./DSMath.sol"; + +interface IOracleAggregator { + function getMakerTokenPrice(string memory _pair) + external + view + returns (uint256); +} + +interface IVaultResolver { + struct VaultData { + uint256 id; + address owner; + string colType; + uint256 collateral; + uint256 art; + uint256 debt; + uint256 liquidatedCol; + uint256 borrowRate; + uint256 colPrice; + uint256 liquidationRatio; + address vaultAddress; + } + + function getVaultById(uint256 id) external view returns (VaultData memory); +} + +contract ConditionMakerVaultIsSafe is GelatoConditionsStandard, DSMath { + using GelatoBytes for bytes; + + address public oracleAggregator; + + constructor(address _oracleAggregator) public { + oracleAggregator = _oracleAggregator; + } + + function getConditionData( + uint256 _vaultID, + string memory _pair, + uint256 _unSafeLimit + ) public pure virtual returns (bytes memory) { + return abi.encode(_vaultID, _pair, _unSafeLimit); + } + + function ok( + uint256, + bytes calldata _conditionData, + uint256 + ) public view virtual override returns (string memory) { + (uint256 vaultID, string memory pair, uint256 unSafeLimit) = abi.decode( + _conditionData, + (uint256, string, uint256) + ); + + return _isVaultUnSafe(vaultID, pair, unSafeLimit); + } + + function _isVaultUnSafe( + uint256 _vaultID, + string memory _pair, + uint256 _unSafeLimit + ) internal view returns (string memory) { + uint256 latestPriceInRay = _getLatestPrice(_pair); + + IVaultResolver.VaultData memory vault = IVaultResolver( + _getVaultResolverAddress() + ) + .getVaultById(_vaultID); + uint256 colRatio = _vaultCollaterizationRatio( + _wmul(vault.collateral, latestPriceInRay), + vault.debt + ); + if (_unSafeLimit > colRatio) { + return OK; + } + return "NotOKMakerVaultIsSafe"; + } + + function _getVaultResolverAddress() internal pure returns (address) { + return 0x0A7008B38E7015F8C36A49eEbc32513ECA8801E5; + } + + function _vaultCollaterizationRatio(uint256 _col, uint256 _debt) + internal + pure + returns (uint256) + { + return _wdiv(_col, _debt); + } + + function _getLatestPrice(string memory _pair) + internal + view + returns (uint256) + { + return IOracleAggregator(oracleAggregator).getMakerTokenPrice(_pair); + } +} diff --git a/contracts/ConnectGelatoDebtBridge.sol b/contracts/ConnectGelatoDebtBridge.sol new file mode 100644 index 0000000..4cfb7e5 --- /dev/null +++ b/contracts/ConnectGelatoDebtBridge.sol @@ -0,0 +1,506 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import "./IMemoryInterface.sol"; +import "./DSMath.sol"; + +interface ConnectorInterface { + function connectorID() external view returns (uint256 _type, uint256 _id); + + function name() external view returns (string memory); +} + +interface OracleAggregator { + function getMakerTokenPrice(string memory _pair) + external + view + returns (uint256); +} + +interface GelatoGasPriceOracle { + function latestAnswer() external view returns (int256); +} + +interface IMakerResolver { + struct VaultData { + uint256 id; + address owner; + string colType; + uint256 collateral; + uint256 art; + uint256 debt; + uint256 liquidatedCol; + uint256 borrowRate; + uint256 colPrice; + uint256 liquidationRatio; + address vaultAddress; + } + + function getVaultById(uint256 id) external view returns (VaultData memory); +} + +interface ICompoundResolver { + struct CompData { + uint256 tokenPriceInEth; + uint256 tokenPriceInUsd; + uint256 exchangeRateStored; + uint256 balanceOfUser; + uint256 borrowBalanceStoredUser; + uint256 supplyRatePerBlock; + uint256 borrowRatePerBlock; + } + + function getCompoundData(address owner, address[] memory cAddress) + external + view + returns (CompData[] memory); +} + +interface IAaveResolver { + struct AaveTokenData { + uint256 ltv; + uint256 threshold; + bool usageAsCollEnabled; + bool borrowEnabled; + bool stableBorrowEnabled; + bool isActive; + } + + struct AaveUserTokenData { + uint256 tokenPriceInEth; + uint256 tokenPriceInUsd; + uint256 supplyBalance; + uint256 borrowBalance; + uint256 borrowFee; + uint256 supplyRate; + uint256 borrowRate; + uint256 borrowModal; + AaveTokenData aaveTokenData; + } + + struct AaveUserData { + uint256 totalSupplyETH; + uint256 totalCollateralETH; + uint256 totalBorrowsETH; + uint256 totalFeesETH; + uint256 availableBorrowsETH; + uint256 currentLiquidationThreshold; + uint256 ltv; + uint256 healthFactor; + uint256 ethPriceInUsd; + } + + function getPosition(address user, address[] memory tokens) + external + view + returns (AaveUserTokenData[] memory, AaveUserData memory); +} + +abstract contract Helpers is ConnectorInterface, DSMath { + uint256 internal _id; + + /** + * @dev Return ethereum address + */ + function _getAddressETH() internal pure returns (address) { + return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // ETH Address + } + + /** + * @dev Return Memory Variable Address + */ + function _getMemoryAddr() internal pure returns (address) { + return 0x8a5419CfC711B2343c17a6ABf4B2bAFaBb06957F; // InstaMemory Address + } + + /** + * @dev Set Uint value in InstaMemory Contract. + */ + function _setUint(uint256 setId, uint256 val) internal { + if (setId != 0) IMemoryInterface(_getMemoryAddr()).setUint(setId, val); + } + + /** + * @dev Get Uint value from InstaMemory Contract. + */ + function _getUint(uint256 getId, uint256 val) + internal + returns (uint256 returnVal) + { + returnVal = getId == 0 + ? val + : IMemoryInterface(_getMemoryAddr()).getUint(getId); + } + + /** + * @dev Connector Details + */ + function connectorID() + public + view + override + returns (uint256 _type, uint256 _iD) + { + (_type, _iD) = (1, _id); // Should put specific value. + } + + function _stringToBytes32(string memory str) + internal + pure + returns (bytes32 result) + { + require(bytes(str).length != 0, "String-Empty"); + // solium-disable-next-line security/no-inline-assembly + assembly { + result := mload(add(str, 32)) + } + } +} + +abstract contract ConnectGelatoDebtBridgeHelpers is Helpers { + function _getMakerResolver() internal pure returns (address) { + return 0x0A7008B38E7015F8C36A49eEbc32513ECA8801E5; + } + + function _getCompoundResolver() internal pure returns (address) { + return 0x1f22D77365d8BFE3b901C33C83C01B584F946617; + } + + function _getAaveResolver() internal pure returns (address) { + return 0xe04Cd009fF68628BC663058dDAA7E5Bf7979BEaF; + } + + function _getGelatoGasPriceOracle() internal pure returns (address) { + return 0x169E633A2D1E6c10dD91238Ba11c4A708dfEF37C; + } + + function _getGasPrice() internal view returns (uint256) { + return + uint256( + GelatoGasPriceOracle(_getGelatoGasPriceOracle()).latestAnswer() + ); + } +} + +abstract contract ConnectGelatoDebtBridgeResolver is + ConnectGelatoDebtBridgeHelpers +{ + mapping(address => address) internal _priceFeeds; + + function getMakerVault(uint256 _vaultID) + public + view + returns (IMakerResolver.VaultData memory) + { + // call maker resolver. + return IMakerResolver(_getMakerResolver()).getVaultById(_vaultID); + } + + function getMakerVaultDebt(uint256 _vaultID) public view returns (uint256) { + return getMakerVault(_vaultID).debt; + } + + function getMakerVaultCollateralBalance(uint256 _vaultID) + public + view + returns (uint256) + { + return getMakerVault(_vaultID).collateral; + } + + function getMakerVaultCollateralType(uint256 _vaultID) + public + view + returns (string memory) + { + return getMakerVault(_vaultID).colType; + } + + function getCompoundData(address _owner, address _cAddress) + public + view + returns (ICompoundResolver.CompData memory) + { + address[] memory cAddressArray; + cAddressArray[0] = _cAddress; + return + ICompoundResolver(_getCompoundResolver()).getCompoundData( + _owner, + cAddressArray + )[0]; + } + + function getCompoundDebt(address _owner, address _cAddress) + public + view + returns (uint256) + { + return getCompoundData(_owner, _cAddress).borrowBalanceStoredUser; + } + + function getCompoundCollateralBalance(address _owner, address _cAddress) + public + view + returns (uint256) + { + return getCompoundData(_owner, _cAddress).balanceOfUser; + } + + function getAaveTokenData(address _owner, address _atoken) + public + view + returns ( + IAaveResolver.AaveUserTokenData memory, + IAaveResolver.AaveUserData memory + ) + { + address[] memory aTokenArray; + aTokenArray[0] = _atoken; + ( + IAaveResolver.AaveUserTokenData[] memory tokensData, + IAaveResolver.AaveUserData memory etherUserData + ) = IAaveResolver(_getAaveResolver()).getPosition(_owner, aTokenArray); + return (tokensData[0], etherUserData); + } + + function getAaveTokenDebt(address _owner, address _atoken) + public + view + returns (uint256) + { + (IAaveResolver.AaveUserTokenData memory tokenData, ) = getAaveTokenData( + _owner, + _atoken + ); + return tokenData.supplyBalance; + } + + function getAaveTokenCollateralBalance(address _owner, address _atoken) + public + view + returns (uint256) + { + (IAaveResolver.AaveUserTokenData memory tokenData, ) = getAaveTokenData( + _owner, + _atoken + ); + return tokenData.borrowBalance; + } +} + +contract ConnectGelatoDebtBridge is ConnectGelatoDebtBridgeResolver { + // Constant name must be in capitalized SNAKE_CASE + // solhint-disable-next-line + string public constant override name = "GelatoDebtBridge-v1.0"; + uint256 public constant GASLIMIT = 2000000; // To Define + address public immutable oracleAggregator; + + constructor(uint256 _iD, address _oracleAggregator) public { + _id = _iD; + oracleAggregator = _oracleAggregator; + } + + /// @notice Write in instaMemory the needed values for doing the refinancing between makerDAO and Compound. + /// @param _vaultID is the id of the makerDAO vault. + /// @param _vaultCollateralizationRatio is the collateralization ratio wanted by the client. + /// @param _compPosCollateralizationRatio is the collateralization ratio wanted by the client. + /// @param _pair crypto currency pair used (collateral token/ borrowed token). + /// @param _getID Id for writting in instaMemory. + /// @param _setID Id for loading from instaMemory. + function debtBridgeMakerToCompound( + uint256 _vaultID, + uint256 _vaultCollateralizationRatio, // should be in ray because maker use ray standard + uint256 _compPosCollateralizationRatio, // should be in wad because compound use wad standard + string memory _pair, + uint256 _getID, + uint256 _setID + ) external { + ( + uint256 paybackAmount, + uint256 collateralToWithdraw, + uint256 fees + ) = debtBridgeCompute( + _vaultID, + _vaultCollateralizationRatio, + _compPosCollateralizationRatio, + _pair + ); + + _setUint(100, paybackAmount); + _setUint(101, paybackAmount); // payback maker + _setUint(102, _add(collateralToWithdraw, fees)); // withdraw maker + _setUint(103, collateralToWithdraw); // deposit compound + _setUint(104, paybackAmount); // borrow compound + _setUint(105, fees); // pay the provider + } + + // Price Oracle + + function debtBridgeCompute( + uint256 _vaultID, + uint256 _vaultLiquidationRatio, // should be in ray because maker use ray standard + uint256 _compPosLiquidationRatio, // should be in wad because compound use wad standard + string memory _pair + ) + public + view + returns ( + uint256 paybackAmount, + uint256 collateralToWithdraw, + uint256 fees + ) + { + uint256 latestPrice = _getLatestPrice(_pair); + // uint256 fees = mul(GASLIMIT, wmul(_getGasPrice(), latestPrice)); + fees = _mul(GASLIMIT, _getGasPrice()); + + uint256 debt = getMakerVaultDebt(_vaultID); + uint256 collateral = _sub( + _wmul(getMakerVaultCollateralBalance(_vaultID), latestPrice), + fees + ); + + collateralToWithdraw = _wcollateralToWithdraw( + _vaultLiquidationRatio, + _compPosLiquidationRatio, + collateral, + debt, + latestPrice + ); + paybackAmount = _wborrowedTokenToPayback( + _vaultLiquidationRatio, + _compPosLiquidationRatio, + collateral, + debt + ); + } + + function _getLatestPrice(string memory _pair) + internal + view + returns (uint256) + { + return OracleAggregator(oracleAggregator).getMakerTokenPrice(_pair); + } + + /// Computation in ray + /// @notice return the amount of collateral we need to withdraw during the debt refinancing in ray standard. + /// @param _p1LiqRatio the liquidation ratio of protocol 1. + /// @param _p2LiqRatio the liquidation ratio of protocol 2. + /// @param _col token1 collateral to put on protocol 1. + /// @param _bor amount of borrowed token2 on protocol 1. + /// @param _colPrice price of the collateral. + /// @return collateral to withdraw in ray standard + function _rcollateralToWithdraw( + uint256 _p1LiqRatio, + uint256 _p2LiqRatio, + uint256 _col, + uint256 _bor, + uint256 _colPrice + ) internal pure returns (uint256) { + return + _rdiv( + _sub( + _col, + _rdiv( + _sub( + _rmul(_p1LiqRatio, _col), + _rmul(_p1LiqRatio, _rmul(_p2LiqRatio, _bor)) + ), + _sub(_p1LiqRatio, _p2LiqRatio) + ) + ), + _colPrice + ); + } + + /// Computation in ray + /// @notice return the amount of borrowed token we need to payback during the debt refinancing in ray standard. + /// @param _p1LiqRatio the liquidation ratio of protocol 1. + /// @param _p2LiqRatio the liquidation ratio of protocol 2. + /// @param _col token1 collateral to put on protocol 1. + /// @param _bor amount of borrowed token2 on protocol 1. + /// @return amount of borrowed token to pay back in ray standard + function _rborrowedTokenToPayback( + uint256 _p1LiqRatio, + uint256 _p2LiqRatio, + uint256 _col, + uint256 _bor + ) internal pure returns (uint256) { + return + _sub( + _bor, + _rmul( + _rdiv(1e18, _p1LiqRatio), + _rdiv( + _sub( + _rmul(_p1LiqRatio, _col), + _rmul(_p1LiqRatio, _rmul(_p2LiqRatio, _bor)) + ), + _sub(_p1LiqRatio, _p2LiqRatio) + ) + ) + ); + } + + /// Computation in wad + /// @notice return the amount of collateral we need to withdraw during the debt refinancing in wad standard. + /// @param _p1LiqRatio the liquidation ratio of protocol 1. + /// @param _p2LiqRatio the liquidation ratio of protocol 2. + /// @param _col token1 collateral to put on protocol 1. + /// @param _bor amount of borrowed token2 on protocol 1. + /// @param _colPrice price of the collateral. + /// @return collateral to withdraw in wad standard + function _wcollateralToWithdraw( + uint256 _p1LiqRatio, + uint256 _p2LiqRatio, + uint256 _col, + uint256 _bor, + uint256 _colPrice + ) internal pure returns (uint256) { + return + _wdiv( + _sub( + _col, + _wdiv( + _sub( + _wmul(_p1LiqRatio, _col), + _wmul(_p1LiqRatio, _wmul(_p2LiqRatio, _bor)) + ), + _sub(_p1LiqRatio, _p2LiqRatio) + ) + ), + _colPrice + ); + } + + /// Computation in wad + /// @notice return the amount of borrowed token we need to payback during the debt refinancing in wad standard. + /// @param _p1LiqRatio the liquidation ratio of protocol 1. + /// @param _p2LiqRatio the liquidation ratio of protocol 2. + /// @param _col token1 collateral to put on protocol 1. + /// @param _bor amount of borrowed token2 on protocol 1. + /// @return amount of borrowed token to pay back in wad standard + function _wborrowedTokenToPayback( + uint256 _p1LiqRatio, + uint256 _p2LiqRatio, + uint256 _col, + uint256 _bor + ) internal pure returns (uint256) { + return + _sub( + _bor, + _wmul( + _wdiv(1e18, _p1LiqRatio), + _wdiv( + _sub( + _wmul(_p1LiqRatio, _col), + _wmul(_p1LiqRatio, _wmul(_p2LiqRatio, _bor)) + ), + _sub(_p1LiqRatio, _p2LiqRatio) + ) + ) + ); + } +} diff --git a/contracts/ConnectGelatoProviderPayment.sol b/contracts/ConnectGelatoProviderPayment.sol new file mode 100644 index 0000000..b487386 --- /dev/null +++ b/contracts/ConnectGelatoProviderPayment.sol @@ -0,0 +1,76 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; + +import "./IMemoryInterface.sol"; +import {IERC20} from "@gelatonetwork/core/contracts/external/IERC20.sol"; + +interface ConnectorInterface { + function connectorID() external view returns (uint256 _type, uint256 _id); + + function name() external view returns (string memory); +} + +abstract contract ConnectGelatoProviderPaymentHelper is ConnectorInterface { + uint256 internal _id; + + function connectorID() + public + view + override + returns (uint256 _type, uint256 _iD) + { + (_type, _iD) = (1, _id); // Should put specific value. + } + + function _getMemoryAddr() internal pure returns (address) { + return 0x8a5419CfC711B2343c17a6ABf4B2bAFaBb06957F; // InstaMemory Address + } + + function _getUint(uint256 _getId, uint256 _val) + internal + returns (uint256 returnVal) + { + returnVal = _getId == 0 + ? _val + : IMemoryInterface(_getMemoryAddr()).getUint(_getId); + } + + function _setUint(uint256 setId, uint256 val) internal { + if (setId != 0) IMemoryInterface(_getMemoryAddr()).setUint(setId, val); + } + + function _getAddressETH() internal pure returns (address) { + return 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE; // ETH Address + } +} + +contract ConnectGelatoProviderPayment is ConnectGelatoProviderPaymentHelper { + // Constant name must be in capitalized SNAKE_CASE + // solhint-disable-next-line + string public constant override name = "GelatoProviderPayement-v1.0"; + + constructor(uint256 _iD) public { + _id = _iD; + } + + function payProvider( + address _provider, + address _token, + uint256 _amt, + uint256 _getID, + uint256 _setID + ) public { + // Desable linter for too long require statement + // solhint-disable-next-line + require( + _provider != address(0x0), + "ConnectGelatoProviderPayment.payProvider:INVALIDADDESS." + ); + uint256 amt = _getUint(_getID, _amt); + if (_token == _getAddressETH()) { + payable(_provider).transfer(amt); + return; + } + IERC20(_token).transfer(_provider, amt); + } +} diff --git a/contracts/DSMath.sol b/contracts/DSMath.sol new file mode 100644 index 0000000..8aac369 --- /dev/null +++ b/contracts/DSMath.sol @@ -0,0 +1,82 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; + +contract DSMath { + function _add(uint256 x, uint256 y) internal pure returns (uint256 z) { + require((z = x + y) >= x, "ds-math-_add-overflow"); + } + + function _sub(uint256 x, uint256 y) internal pure returns (uint256 z) { + require((z = x - y) <= x, "ds-math-_sub-underflow"); + } + + function _mul(uint256 x, uint256 y) internal pure returns (uint256 z) { + require(y == 0 || (z = x * y) / y == x, "ds-math-_mul-overflow"); + } + + function _min(uint256 x, uint256 y) internal pure returns (uint256 z) { + return x <= y ? x : y; + } + + function _max(uint256 x, uint256 y) internal pure returns (uint256 z) { + return x >= y ? x : y; + } + + function _imin(int256 x, int256 y) internal pure returns (int256 z) { + return x <= y ? x : y; + } + + function _imax(int256 x, int256 y) internal pure returns (int256 z) { + return x >= y ? x : y; + } + + uint256 internal constant _WAD = 10**18; + uint256 internal constant _RAY = 10**27; + + //rounds to zero if x*y < _WAD / 2 + function _wmul(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = _add(_mul(x, y), _WAD / 2) / _WAD; + } + + //rounds to zero if x*y < _WAD / 2 + function _rmul(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = _add(_mul(x, y), _RAY / 2) / _RAY; + } + + //rounds to zero if x*y < _WAD / 2 + function _wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = _add(_mul(x, _WAD), y / 2) / y; + } + + //rounds to zero if x*y < _RAY / 2 + function _rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) { + z = _add(_mul(x, _RAY), y / 2) / y; + } + + // This famous algorithm is called "exponentiation by squaring" + // and calculates x^n with x as fixed-point and n as regular unsigned. + // + // It's O(log n), instead of O(n) for naive repeated _multiplication. + // + // These facts are why it works: + // + // If n is even, then x^n = (x^2)^(n/2). + // If n is odd, then x^n = x * x^(n-1), + // and applying the equation for even x gives + // x^n = x * (x^2)^((n-1) / 2). + // + // Also, EVM division is flooring and + // floor[(n-1) / 2] = floor[n / 2]. + // + function _rpow(uint256 x, uint256 n) internal pure returns (uint256 z) { + z = n % 2 != 0 ? x : _RAY; + + for (n /= 2; n != 0; n /= 2) { + x = _rmul(x, x); + + if (n % 2 != 0) { + z = _rmul(z, x); + } + } + } +} diff --git a/contracts/IMemoryInterface.sol b/contracts/IMemoryInterface.sol new file mode 100644 index 0000000..38549f8 --- /dev/null +++ b/contracts/IMemoryInterface.sol @@ -0,0 +1,8 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; + +interface IMemoryInterface { + function setUint(uint256 _id, uint256 _val) external; + + function getUint(uint256 _id) external returns (uint256); +} diff --git a/contracts/OracleAggregator.sol b/contracts/OracleAggregator.sol new file mode 100644 index 0000000..d7d827f --- /dev/null +++ b/contracts/OracleAggregator.sol @@ -0,0 +1,56 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import {Ownable} from "@gelatonetwork/core/contracts/external/Ownable.sol"; +import "./DSMath.sol"; + +interface IMakerPriceFeed { + function read() external view returns (bytes32); +} + +contract OracleAggregatorStorage { + mapping(string => address) internal _makerOracle; + mapping(string => address) internal _compoundOracle; + mapping(string => address) internal _chainlinkOracle; +} + +// 0x729D19f657BD0614b4985Cf1D82531c67569197B for ETH/USD medianizer it return value in wad standard. +contract OracleAggregator is OracleAggregatorStorage, Ownable, DSMath { + bool public mockMode; + uint256 public mockValue; + + constructor() public Ownable() { + mockMode = false; + mockValue = 0; + } + + function mock(bool _mockMode, uint256 _mockValue) public onlyOwner { + mockMode = _mockMode; + mockValue = _mockValue; + } + + function addOracle(string memory _pair, address _oracleAddress) + external + onlyOwner + { + // Desable linter for too long require statement + // solhint-disable-next-line + require( + _makerOracle[_pair] == address(0x0), + "OracleAggregator.Maker: Oracle already set." + ); + _makerOracle[_pair] = _oracleAddress; + } + + function getMakerTokenPrice(string memory _pair) + external + view + returns (uint256) + { + if (mockMode) { + return mockValue; + } + return uint256(IMakerPriceFeed(_makerOracle[_pair]).read()); + } +} diff --git a/contracts/ProviderModuleDSA.sol b/contracts/ProviderModuleDSA.sol new file mode 100644 index 0000000..2855a1c --- /dev/null +++ b/contracts/ProviderModuleDSA.sol @@ -0,0 +1,121 @@ +// "SPDX-License-Identifier: UNLICENSED" +pragma solidity 0.6.12; +pragma experimental ABIEncoderV2; + +import { + GelatoProviderModuleStandard +} from "@gelatonetwork/core/contracts/provider_modules/GelatoProviderModuleStandard.sol"; +import { + Task +} from "@gelatonetwork/core/contracts/gelato_core/interfaces/IGelatoCore.sol"; +import "./ConnectGelatoProviderPayment.sol"; + +/// @dev InstaDapp Index +interface IndexInterface { + function connectors(uint256 version) external view returns (address); + + function list() external view returns (address); +} + +/// @dev InstaDapp List +interface ListInterface { + function accountID(address _account) external view returns (uint64); +} + +/// @dev InstaDapp Defi Smart Account wallet +interface AccountInterface { + function version() external view returns (uint256); + + function isAuth(address user) external view returns (bool); + + function shield() external view returns (bool); + + function cast( + address[] calldata _targets, + bytes[] calldata _datas, + address _origin + ) external payable returns (bytes32[] memory responses); +} + +contract ProviderModuleDSA is GelatoProviderModuleStandard { + IndexInterface public immutable index; + address public immutable gelatoCore; + address public immutable connectGelatoProviderPayment; + + constructor( + IndexInterface _index, + address _gelatoCore, + address _connectGelatoProviderPayment + ) public { + index = _index; + gelatoCore = _gelatoCore; + connectGelatoProviderPayment = _connectGelatoProviderPayment; + } + + // ================= GELATO PROVIDER MODULE STANDARD ================ + function isProvided( + address _userProxy, + address, + Task calldata _task + ) external view override returns (string memory) { + // Verify InstaDapp account identity + if (ListInterface(index.list()).accountID(_userProxy) == 0) + return "ProviderModuleDSA.isProvided:InvalidUserProxy"; + + // Is GelatoCore authorized + if (!AccountInterface(_userProxy).isAuth(gelatoCore)) + return "ProviderModuleDSA.isProvided:GelatoCoreNotAuth"; + + return OK; + } + + /// @dev DS PROXY ONLY ALLOWS DELEGATE CALL for single actions, that's why we also use multisend + function execPayload( + uint256, + address, + address _provider, + Task calldata _task, + uint256 + ) external view override returns (bytes memory payload, bool) { + address[] memory targets = new address[](_task.actions.length); + for (uint256 i = 0; i < _task.actions.length; i++) + targets[i] = _task.actions[i].addr; + + bytes[] memory datas = new bytes[](_task.actions.length); + for (uint256 i = 0; i < _task.actions.length; i++) { + if (_task.actions[i].addr == connectGelatoProviderPayment) { + // input the exact address of the provider + datas[i] = _getDelegateCallDataForProviderPaymentConnector( + _provider, + _task.actions[i].data + ); + } else { + datas[i] = _task.actions[i].data; + } + } + + payload = abi.encodeWithSelector( + AccountInterface.cast.selector, + targets, + datas, + gelatoCore + ); + } + + function _getDelegateCallDataForProviderPaymentConnector( + address _provider, + bytes calldata _data + ) internal pure returns (bytes memory) { + (, address token, uint256 amt, uint256 getID, uint256 setID) = abi + .decode(_data[4:], (address, address, uint256, uint256, uint256)); + return + abi.encodeWithSelector( + ConnectGelatoProviderPayment.payProvider.selector, + _provider, + token, + amt, + getID, + setID + ); + } +} diff --git a/pre-compiles/CTokenInterface.json b/pre-compiles/CTokenInterface.json new file mode 100644 index 0000000..a573f29 --- /dev/null +++ b/pre-compiles/CTokenInterface.json @@ -0,0 +1,359 @@ +{ + "contractName": "CTokenInterface", + "abi": [ + { + "inputs": [], + "name": "_acceptAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "newPendingAdmin", + "type": "address" + } + ], + "name": "_setPendingAdmin", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "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": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "balanceOfUnderlying", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "borrowBalanceStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "borrowRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "exchangeRateStored", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "getAccountSnapshot", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCash", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "liquidator", + "type": "address" + }, + { + "internalType": "address", + "name": "borrower", + "type": "address" + }, + { + "internalType": "uint256", + "name": "seizeTokens", + "type": "uint256" + } + ], + "name": "seize", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "supplyRatePerBlock", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "totalBorrowsCurrent", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "src", + "type": "address" + }, + { + "internalType": "address", + "name": "dst", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/pre-compiles/ConnectGelato.json b/pre-compiles/ConnectGelato.json new file mode 100644 index 0000000..7eb2fef --- /dev/null +++ b/pre-compiles/ConnectGelato.json @@ -0,0 +1,1323 @@ +{ + "contractName": "ConnectGelato", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "userProxy", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "internalType": "struct Provider", + "name": "provider", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct Task[]", + "name": "tasks", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "expiryDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cycleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "submissionsLeft", + "type": "uint256" + } + ], + "indexed": true, + "internalType": "struct TaskReceipt[]", + "name": "taskReceipt", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogMultiCancelTasks", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "executor", + "type": "address" + }, + { + "components": [ + { + "internalType": "address[]", + "name": "conditions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "gasPriceCeil", + "type": "uint256" + } + ], + "indexed": true, + "internalType": "struct TaskSpec[]", + "name": "taskspecs", + "type": "tuple[]" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "modules", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethToDeposit", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogMultiProvide", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address[]", + "name": "conditions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "gasPriceCeil", + "type": "uint256" + } + ], + "indexed": true, + "internalType": "struct TaskSpec[]", + "name": "taskspecs", + "type": "tuple[]" + }, + { + "indexed": true, + "internalType": "address[]", + "name": "modules", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "ethToWithdraw", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogMultiUnprovide", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "indexed": true, + "internalType": "struct Provider", + "name": "provider", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "indexed": true, + "internalType": "struct Task", + "name": "task", + "type": "tuple" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "expiryDate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogSubmitTask", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "indexed": true, + "internalType": "struct Provider", + "name": "provider", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "indexed": true, + "internalType": "struct Task[]", + "name": "tasks", + "type": "tuple[]" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "expiryDate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogSubmitTaskChain", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "indexed": true, + "internalType": "struct Provider", + "name": "provider", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "indexed": true, + "internalType": "struct Task[]", + "name": "tasks", + "type": "tuple[]" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "expiryDate", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogSubmitTaskCycle", + "type": "event" + }, + { + "inputs": [], + "name": "connectorID", + "outputs": [ + { + "internalType": "uint256", + "name": "_type", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_id", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "uint256", + "name": "id", + "type": "uint256" + }, + { + "internalType": "address", + "name": "userProxy", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "internalType": "struct Provider", + "name": "provider", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct Task[]", + "name": "tasks", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "expiryDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "cycleId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "submissionsLeft", + "type": "uint256" + } + ], + "internalType": "struct TaskReceipt[]", + "name": "_taskReceipts", + "type": "tuple[]" + } + ], + "name": "multiCancelTasks", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_executor", + "type": "address" + }, + { + "components": [ + { + "internalType": "address[]", + "name": "conditions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "gasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct TaskSpec[]", + "name": "_taskSpecs", + "type": "tuple[]" + }, + { + "internalType": "address[]", + "name": "_modules", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "_ethToDeposit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_setId", + "type": "uint256" + } + ], + "name": "multiProvide", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_withdrawAmount", + "type": "uint256" + }, + { + "components": [ + { + "internalType": "address[]", + "name": "conditions", + "type": "address[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "gasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct TaskSpec[]", + "name": "_taskSpecs", + "type": "tuple[]" + }, + { + "internalType": "address[]", + "name": "_modules", + "type": "address[]" + }, + { + "internalType": "uint256", + "name": "_getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_setId", + "type": "uint256" + } + ], + "name": "multiUnprovide", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "internalType": "struct Provider", + "name": "_provider", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct Task", + "name": "_task", + "type": "tuple" + }, + { + "internalType": "uint256", + "name": "_expiryDate", + "type": "uint256" + } + ], + "name": "submitTask", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "internalType": "struct Provider", + "name": "_provider", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct Task[]", + "name": "_tasks", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "_expiryDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_sumOfRequestedTaskSubmits", + "type": "uint256" + } + ], + "name": "submitTaskChain", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "address", + "name": "module", + "type": "address" + } + ], + "internalType": "struct Provider", + "name": "_provider", + "type": "tuple" + }, + { + "components": [ + { + "components": [ + { + "internalType": "address", + "name": "inst", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "internalType": "struct Condition[]", + "name": "conditions", + "type": "tuple[]" + }, + { + "components": [ + { + "internalType": "address", + "name": "addr", + "type": "address" + }, + { + "internalType": "bytes", + "name": "data", + "type": "bytes" + }, + { + "internalType": "enum Operation", + "name": "operation", + "type": "uint8" + }, + { + "internalType": "enum DataFlow", + "name": "dataFlow", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + }, + { + "internalType": "bool", + "name": "termsOkCheck", + "type": "bool" + } + ], + "internalType": "struct Action[]", + "name": "actions", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "selfProviderGasLimit", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "selfProviderGasPriceCeil", + "type": "uint256" + } + ], + "internalType": "struct Task[]", + "name": "_tasks", + "type": "tuple[]" + }, + { + "internalType": "uint256", + "name": "_expiryDate", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_cycles", + "type": "uint256" + } + ], + "name": "submitTaskCycle", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x60806040526040518060400160405280600b81526020017f47656c61746f2d76312e30000000000000000000000000000000000000000000815250600090805190602001906200005192919062000066565b503480156200005f57600080fd5b5062000115565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620000a957805160ff1916838001178555620000da565b82800160010185558215620000da579182015b82811115620000d9578251825591602001919060010190620000bc565b5b509050620000e99190620000ed565b5090565b6200011291905b808211156200010e576000816000905550600101620000f4565b5090565b90565b61298780620001256000396000f3fe60806040526004361061007b5760003560e01c80636cd3d8981161004e5780636cd3d898146100ff578063b348e2681461011b578063eb15f78114610137578063ff92b1a8146101635761007b565b8063025264901461008057806306fdde031461009c5780632738a788146100c75780633e75a9a8146100e3575b600080fd5b61009a60048036036100959190810190610d23565b61017f565b005b3480156100a857600080fd5b506100b1610269565b6040516100be9190612186565b60405180910390f35b6100e160048036036100dc9190810190610e33565b610307565b005b6100fd60048036036100f89190810190610cde565b610423565b005b61011960048036036101149190810190610c1b565b6104ed565b005b61013560048036036101309190810190610d23565b61063e565b005b34801561014357600080fd5b5061014c610728565b60405161015a9291906122ba565b60405180910390f35b61017d60048036036101789190810190610da3565b610741565b005b610187610823565b73ffffffffffffffffffffffffffffffffffffffff16630252649086868686866040518663ffffffff1660e01b81526004016101c79594939291906121ca565b600060405180830381600087803b1580156101e157600080fd5b505af11580156101f5573d6000803e3d6000fd5b5050505081848460405161020a9291906120a5565b60405180910390208660405161022091906120be565b60405180910390207f6e618ca93d8007a3bb048d87cc0e7bf12bddc6ca3e336c153890bc0b6f66e9f660008060405161025a92919061215d565b60405180910390a45050505050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102ff5780601f106102d4576101008083540402835291602001916102ff565b820191906000526020600020905b8154815290600101906020018083116102e257829003601f168201915b505050505081565b6000610313838961083f565b90506000479050610322610823565b73ffffffffffffffffffffffffffffffffffffffff1663b300f752838a8a8a8a6040518663ffffffff1660e01b8152600401610362959493929190612271565b600060405180830381600087803b15801561037c57600080fd5b505af1158015610390573d6000803e3d6000fd5b5050505060006103a047836108e9565b90506103ac84826108fd565b86866040516103bc92919061205a565b604051809103902089896040516103d492919061208c565b60405180910390207fc44585ae385fe053d798d56dc20dc0f0beade803098d105d289637d878fa9c7b83888860405161040f939291906122e3565b60405180910390a350505050505050505050565b61042b610823565b73ffffffffffffffffffffffffffffffffffffffff16633e75a9a883836040518363ffffffff1660e01b8152600401610465929190612139565b600060405180830381600087803b15801561047f57600080fd5b505af1158015610493573d6000803e3d6000fd5b5050505081816040516104a7929190612073565b60405180910390207fb42519a7cf5f104a27b62b10dc1e67721be4b68791899606dd15e1b017bd96316000806040516104e192919061215d565b60405180910390a25050565b60006104f9838561083f565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610528578061052a565b475b9050610534610823565b73ffffffffffffffffffffffffffffffffffffffff16639aad3798828b8b8b8b8b6040518763ffffffff1660e01b81526004016105759594939291906120f0565b6000604051808303818588803b15801561058e57600080fd5b505af11580156105a2573d6000803e3d6000fd5b50505050506105b182826108fd565b85856040516105c192919061205a565b604051809103902088886040516105d992919061208c565b60405180910390208a73ffffffffffffffffffffffffffffffffffffffff167f1e9ff70996f352b5b70751209e03ae367633703bfc74ccc966b87e70ab57136184878760405161062b939291906122e3565b60405180910390a4505050505050505050565b610646610823565b73ffffffffffffffffffffffffffffffffffffffff1663b348e26886868686866040518663ffffffff1660e01b81526004016106869594939291906121ca565b600060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050508184846040516106c99291906120a5565b6040518091039020866040516106df91906120be565b60405180910390207f9e2ce841f586026d01f4cdb7bcd28c46154ba65e6766033fee248e3690c35a0d60008060405161071992919061215d565b60405180910390a45050505050565b6000806001602a81915080905080925081935050509091565b610749610823565b73ffffffffffffffffffffffffffffffffffffffff1663ff92b1a88484846040518463ffffffff1660e01b815260040161078593929190612218565b600060405180830381600087803b15801561079f57600080fd5b505af11580156107b3573d6000803e3d6000fd5b5050505080826040516107c691906120d9565b6040518091039020846040516107dc91906120be565b60405180910390207f054a2512b2e1ba381f3ca2abbf5515644385116f44cf8d635382f6df3f41055760008060405161081692919061215d565b60405180910390a4505050565b6000731d681d76ce96e4d70a88a00ebbcfc1e47808d0b8905090565b60008083146108df5761085061097e565b73ffffffffffffffffffffffffffffffffffffffff1663a9c70eaa846040518263ffffffff1660e01b81526004016108889190612256565b602060405180830381600087803b1580156108a257600080fd5b505af11580156108b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108da9190810190610e0a565b6108e1565b815b905092915050565b60006108f5838361099a565b905092915050565b6000821461097a5761090d61097e565b73ffffffffffffffffffffffffffffffffffffffff166361e3c94483836040518363ffffffff1660e01b81526004016109479291906122ba565b600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b505050505b5050565b6000738a5419cfc711b2343c17a6abf4b2bafabb06957f905090565b60006109dc83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506109e4565b905092915050565b6000838311158290610a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2391906121a8565b60405180910390fd5b5060008385039050809150509392505050565b600081359050610a4e816128ec565b92915050565b60008083601f840112610a6657600080fd5b8235905067ffffffffffffffff811115610a7f57600080fd5b602083019150836020820283011115610a9757600080fd5b9250929050565b60008083601f840112610ab057600080fd5b8235905067ffffffffffffffff811115610ac957600080fd5b602083019150836020820283011115610ae157600080fd5b9250929050565b60008083601f840112610afa57600080fd5b8235905067ffffffffffffffff811115610b1357600080fd5b602083019150836020820283011115610b2b57600080fd5b9250929050565b60008083601f840112610b4457600080fd5b8235905067ffffffffffffffff811115610b5d57600080fd5b602083019150836020820283011115610b7557600080fd5b9250929050565b600081359050610b8b81612903565b92915050565b600081359050610ba08161291a565b92915050565b600081359050610bb58161292a565b92915050565b600060408284031215610bcd57600080fd5b81905092915050565b600060808284031215610be857600080fd5b81905092915050565b600081359050610c008161293a565b92915050565b600081519050610c158161293a565b92915050565b60008060008060008060008060c0898b031215610c3757600080fd5b6000610c458b828c01610a3f565b985050602089013567ffffffffffffffff811115610c6257600080fd5b610c6e8b828c01610ae8565b9750975050604089013567ffffffffffffffff811115610c8d57600080fd5b610c998b828c01610a54565b95509550506060610cac8b828c01610bf1565b9350506080610cbd8b828c01610bf1565b92505060a0610cce8b828c01610bf1565b9150509295985092959890939650565b60008060208385031215610cf157600080fd5b600083013567ffffffffffffffff811115610d0b57600080fd5b610d1785828601610a9e565b92509250509250929050565b600080600080600060a08688031215610d3b57600080fd5b6000610d4988828901610bbb565b955050604086013567ffffffffffffffff811115610d6657600080fd5b610d7288828901610b32565b94509450506060610d8588828901610bf1565b9250506080610d9688828901610bf1565b9150509295509295909350565b600080600060808486031215610db857600080fd5b6000610dc686828701610bbb565b935050604084013567ffffffffffffffff811115610de357600080fd5b610def86828701610bd6565b9250506060610e0086828701610bf1565b9150509250925092565b600060208284031215610e1c57600080fd5b6000610e2a84828501610c06565b91505092915050565b600080600080600080600060a0888a031215610e4e57600080fd5b6000610e5c8a828b01610bf1565b975050602088013567ffffffffffffffff811115610e7957600080fd5b610e858a828b01610ae8565b9650965050604088013567ffffffffffffffff811115610ea457600080fd5b610eb08a828b01610a54565b94509450506060610ec38a828b01610bf1565b9250506080610ed48a828b01610bf1565b91505092959891949750929550565b6000610eef83836110c1565b60208301905092915050565b6000610f0783836110df565b60208301905092915050565b6000610f20848484611205565b90509392505050565b6000610f368484846112d6565b90509392505050565b6000610f4c8484846113a7565b90509392505050565b6000610f628484846116eb565b90509392505050565b6000610f778383611757565b60208301905092915050565b6000610f90848484611793565b90509392505050565b6000610fa583836117cf565b60208301905092915050565b6000610fbd83836117ed565b60208301905092915050565b6000610fd5838361187d565b905092915050565b6000610fe98383611938565b905092915050565b6000610ffd83836119e5565b905092915050565b60006110118383611a34565b905092915050565b60006110258383611b34565b60408301905092915050565b600061103d8383611b71565b905092915050565b60006110518383611c65565b905092915050565b60006110658383611d47565b905092915050565b60006110798383611dba565b905092915050565b600061108d8383611f24565b905092915050565b60006110a18383611fb2565b905092915050565b60006110b5838361204b565b60208301905092915050565b6110ca816127db565b82525050565b6110d9816127db565b82525050565b6110e8816127db565b82525050565b60006110fa83856123f9565b935061110582612324565b8060005b8581101561113e5761111b82846124f5565b6111258882610ee3565b97506111308361238d565b925050600181019050611109565b5085925050509392505050565b60006111578385612415565b935061116282612324565b8060005b8581101561119b5761117882846124f5565b6111828882610efb565b975061118d8361238d565b925050600181019050611166565b5085925050509392505050565b60006111b483856123e8565b93506111bf8261231a565b8060005b858110156111f8576111d582846124f5565b6111df8882610ee3565b97506111ea83612380565b9250506001810190506111c3565b5085925050509392505050565b6000611211838561240a565b935061121c8261231a565b8060005b858110156112555761123282846124f5565b61123c8882610efb565b975061124783612380565b925050600181019050611220565b5085925050509392505050565b600061126e8385612420565b9350836020840285016112808461232e565b8060005b878110156112c457848403895261129b8284612704565b6112a58582610fc9565b94506112b08361239a565b925060208a01995050600181019050611284565b50829750879450505050509392505050565b60006112e28385612431565b93506112ed8261232e565b8060005b85811015611326576113038284612704565b61130d8882610fdd565b97506113188361239a565b9250506001810190506112f1565b5085925050509392505050565b600061133f838561243c565b93508360208402850161135184612338565b8060005b8781101561139557848403895261136c8284612728565b6113768582610ff1565b9450611381836123a7565b925060208a01995050600181019050611355565b50829750879450505050509392505050565b60006113b3838561244d565b93506113be82612338565b8060005b858110156113f7576113d48284612728565b6113de8882611005565b97506113e9836123a7565b9250506001810190506113c2565b5085925050509392505050565b60006114108385612458565b93508360208402850161142284612342565b8060005b8781101561146657848403895261143d8284612757565b6114478582611031565b9450611452836123b4565b925060208a01995050600181019050611426565b50829750879450505050509392505050565b60006114848385612469565b935061148f82612342565b8060005b858110156114c8576114a58284612757565b6114af8882611045565b97506114ba836123b4565b925050600181019050611493565b5085925050509392505050565b60006114e18385612474565b9350836020840285016114f38461234c565b8060005b8781101561153757848403895261150e828461277c565b6115188582611059565b9450611523836123c1565b925060208a019950506001810190506114f7565b50829750879450505050509392505050565b60006115558385612485565b93506115608261234c565b8060005b8581101561159957611576828461277c565b611580888261106d565b975061158b836123c1565b925050600181019050611564565b5085925050509392505050565b60006115b283856124a1565b9350836020840285016115c484612360565b8060005b878110156116085784840389526115df82846127a0565b6115e98582611081565b94506115f4836123db565b925060208a019950506001810190506115c8565b50829750879450505050509392505050565b600061162683856124bd565b935061163182612360565b8060005b8581101561166a5761164782846127a0565b6116518882611095565b975061165c836123db565b925050600181019050611635565b5085925050509392505050565b60006116838385612490565b93508360208402850161169584612356565b8060005b878110156116d95784840389526116b082846127a0565b6116ba8582611081565b94506116c5836123ce565b925060208a01995050600181019050611699565b50829750879450505050509392505050565b60006116f783856124b2565b935061170282612356565b8060005b8581101561173b5761171882846127a0565b6117228882611095565b975061172d836123ce565b925050600181019050611706565b5085925050509392505050565b611751816127ed565b82525050565b611760816127ed565b82525050565b600061177283856124c8565b935061177f83858461287f565b611788836128c1565b840190509392505050565b600061179f83856124d9565b93506117ac83858461287f565b6117b5836128c1565b840190509392505050565b6117c981612849565b82525050565b6117d881612849565b82525050565b6117e78161285b565b82525050565b6117f68161285b565b82525050565b6118058161286d565b82525050565b600061181682612375565b61182081856124e4565b935061183081856020860161288e565b611839816128c1565b840191505092915050565b600061184f8261236a565b61185981856124e4565b935061186981856020860161288e565b611872816128c1565b840191505092915050565b600060c0830161189060008401846124f5565b61189d60008601826110c1565b506118ab602084018461267f565b85830360208701526118be838284611766565b925050506118cf60408401846126ed565b6118dc60408601826117de565b506118ea60608401846126d6565b6118f760608601826117c0565b5061190560808401846127c4565b611912608086018261202d565b5061192060a0840184612668565b61192d60a0860182611748565b508091505092915050565b600080830161194a60008401846124f5565b6119548582610efb565b945050611964602084018461267f565b61196f868284610f83565b9550505061198060408401846126ed565b61198a8582610fb1565b94505061199a60608401846126d6565b6119a48582610f99565b9450506119b460808401846127c4565b6119be85826110a9565b9450506119ce60a0840184612668565b6119d88582610f6b565b9450508391505092915050565b6000604083016119f860008401846124f5565b611a0560008601826110c1565b50611a13602084018461267f565b8583036020870152611a26838284611766565b925050508091505092915050565b6000808301611a4660008401846124f5565b611a508582610efb565b945050611a60602084018461267f565b611a6b868284610f83565b955050508391505092915050565b60408201611a8a60008301836124f5565b611a9760008501826110c1565b50611aa560208301836124f5565b611ab260208501826110c1565b50505050565b60008201611ac960008301836124f5565b611ad38482610efb565b935050611ae360208301836124f5565b611aed8482610efb565b935050505050565b60408201611b0660008301836124f5565b611b1360008501826110c1565b50611b2160208301836124f5565b611b2e60208501826110c1565b50505050565b60008201611b4560008301836124f5565b611b4f8482610efb565b935050611b5f60208301836124f5565b611b698482610efb565b935050505050565b60006101208301611b8560008401846127c4565b611b92600086018261202d565b50611ba060208401846124f5565b611bad60208601826110c1565b50611bbb604084018461274c565b611bc86040860182611af5565b50611bd660808401846127c4565b611be3608086018261202d565b50611bf160a0840184612611565b85830360a0870152611c04838284611677565b92505050611c1560c08401846127c4565b611c2260c086018261202d565b50611c3060e08401846127c4565b611c3d60e086018261202d565b50611c4c6101008401846127c4565b611c5a61010086018261202d565b508091505092915050565b6000808301611c7760008401846127c4565b611c8185826110a9565b945050611c9160208401846124f5565b611c9b8582610efb565b945050611cab604084018461274c565b611cb58582611019565b945050611cc560808401846127c4565b611ccf85826110a9565b945050611cdf60a0840184612611565b611cea868284610f55565b95505050611cfb60c08401846127c4565b611d0585826110a9565b945050611d1560e08401846127c4565b611d1f85826110a9565b945050611d306101008401846127c4565b611d3a85826110a9565b9450508391505092915050565b600060608301611d5a600084018461250c565b8583036000870152611d6d8382846111a8565b92505050611d7e6020840184612563565b8583036020870152611d91838284611262565b92505050611da260408401846127c4565b611daf604086018261202d565b508091505092915050565b6000808301611dcc600084018461250c565b611dd7868284610f13565b95505050611de86020840184612563565b611df3868284610f29565b95505050611e0460408401846127c4565b611e0e85826110a9565b9450508391505092915050565b600060808301611e2e60008401846125ba565b8583036000870152611e41838284611333565b92505050611e526020840184612563565b8583036020870152611e65838284611262565b92505050611e7660408401846127c4565b611e83604086018261202d565b50611e9160608401846127c4565b611e9e606086018261202d565b508091505092915050565b6000808301611ebb60008401846125ba565b611ec6868284610f3f565b95505050611ed76020840184612563565b611ee2868284610f29565b95505050611ef360408401846127c4565b611efd85826110a9565b945050611f0d60608401846127c4565b611f1785826110a9565b9450508391505092915050565b600060808301611f3760008401846125ba565b8583036000870152611f4a838284611333565b92505050611f5b6020840184612563565b8583036020870152611f6e838284611262565b92505050611f7f60408401846127c4565b611f8c604086018261202d565b50611f9a60608401846127c4565b611fa7606086018261202d565b508091505092915050565b6000808301611fc460008401846125ba565b611fcf868284610f3f565b95505050611fe06020840184612563565b611feb868284610f29565b95505050611ffc60408401846127c4565b61200685826110a9565b94505061201660608401846127c4565b61202085826110a9565b9450508391505092915050565b6120368161283f565b82525050565b6120458161283f565b82525050565b6120548161283f565b82525050565b600061206782848661114b565b91508190509392505050565b6000612080828486611478565b91508190509392505050565b6000612099828486611549565b91508190509392505050565b60006120b282848661161a565b91508190509392505050565b60006120ca8284611ab8565b60408201915081905092915050565b60006120e58284611ea9565b915081905092915050565b600060608201905061210560008301886110d0565b81810360208301526121188186886114d5565b9050818103604083015261212d8184866110ee565b90509695505050505050565b60006020820190508181036000830152612154818486611404565b90509392505050565b600060408201905061217260008301856117fc565b61217f60208301846117fc565b9392505050565b600060208201905081810360008301526121a08184611844565b905092915050565b600060208201905081810360008301526121c2818461180b565b905092915050565b600060a0820190506121df6000830188611a79565b81810360408301526121f28186886115a6565b9050612201606083018561203c565b61220e608083018461203c565b9695505050505050565b600060808201905061222d6000830186611a79565b818103604083015261223f8185611e1b565b905061224e606083018461203c565b949350505050565b600060208201905061226b600083018461203c565b92915050565b6000606082019050612286600083018861203c565b81810360208301526122998186886114d5565b905081810360408301526122ae8184866110ee565b90509695505050505050565b60006040820190506122cf600083018561203c565b6122dc602083018461203c565b9392505050565b60006060820190506122f8600083018661203c565b612305602083018561203c565b612312604083018461203c565b949350505050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b60006125046020840184610a3f565b905092915050565b6000808335600160200384360303811261252557600080fd5b83810192508235915060208301925067ffffffffffffffff82111561254957600080fd5b60208202360384131561255b57600080fd5b509250929050565b6000808335600160200384360303811261257c57600080fd5b83810192508235915060208301925067ffffffffffffffff8211156125a057600080fd5b6020820236038413156125b257600080fd5b509250929050565b600080833560016020038436030381126125d357600080fd5b83810192508235915060208301925067ffffffffffffffff8211156125f757600080fd5b60208202360384131561260957600080fd5b509250929050565b6000808335600160200384360303811261262a57600080fd5b83810192508235915060208301925067ffffffffffffffff82111561264e57600080fd5b60208202360384131561266057600080fd5b509250929050565b60006126776020840184610b7c565b905092915050565b6000808335600160200384360303811261269857600080fd5b83810192508235915060208301925067ffffffffffffffff8211156126bc57600080fd5b6001820236038413156126ce57600080fd5b509250929050565b60006126e56020840184610b91565b905092915050565b60006126fc6020840184610ba6565b905092915050565b60008235600160c00383360303811261271c57600080fd5b82810191505092915050565b60008235600160400383360303811261274057600080fd5b82810191505092915050565b600082905092915050565b6000823560016101200383360303811261277057600080fd5b82810191505092915050565b60008235600160600383360303811261279457600080fd5b82810191505092915050565b6000823560016080038336030381126127b857600080fd5b82810191505092915050565b60006127d36020840184610bf1565b905092915050565b60006127e68261281f565b9050919050565b60008115159050919050565b6000819050612807826128d2565b919050565b600081905061281a826128df565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612854826127f9565b9050919050565b60006128668261280c565b9050919050565b60006128788261283f565b9050919050565b82818337600083830152505050565b60005b838110156128ac578082015181840152602081019050612891565b838111156128bb576000848401525b50505050565b6000601f19601f8301169050919050565b600481106128dc57fe5b50565b600281106128e957fe5b50565b6128f5816127db565b811461290057600080fd5b50565b61290c816127ed565b811461291757600080fd5b50565b6004811061292757600080fd5b50565b6002811061293757600080fd5b50565b6129438161283f565b811461294e57600080fd5b5056fea264697066735822122088280a6b796c8b831d87a8e867c7a16ddf6e9d066a788dbb3b6423cf352f357864736f6c63430006020033", + "deployedBytecode": "0x60806040526004361061007b5760003560e01c80636cd3d8981161004e5780636cd3d898146100ff578063b348e2681461011b578063eb15f78114610137578063ff92b1a8146101635761007b565b8063025264901461008057806306fdde031461009c5780632738a788146100c75780633e75a9a8146100e3575b600080fd5b61009a60048036036100959190810190610d23565b61017f565b005b3480156100a857600080fd5b506100b1610269565b6040516100be9190612186565b60405180910390f35b6100e160048036036100dc9190810190610e33565b610307565b005b6100fd60048036036100f89190810190610cde565b610423565b005b61011960048036036101149190810190610c1b565b6104ed565b005b61013560048036036101309190810190610d23565b61063e565b005b34801561014357600080fd5b5061014c610728565b60405161015a9291906122ba565b60405180910390f35b61017d60048036036101789190810190610da3565b610741565b005b610187610823565b73ffffffffffffffffffffffffffffffffffffffff16630252649086868686866040518663ffffffff1660e01b81526004016101c79594939291906121ca565b600060405180830381600087803b1580156101e157600080fd5b505af11580156101f5573d6000803e3d6000fd5b5050505081848460405161020a9291906120a5565b60405180910390208660405161022091906120be565b60405180910390207f6e618ca93d8007a3bb048d87cc0e7bf12bddc6ca3e336c153890bc0b6f66e9f660008060405161025a92919061215d565b60405180910390a45050505050565b60008054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156102ff5780601f106102d4576101008083540402835291602001916102ff565b820191906000526020600020905b8154815290600101906020018083116102e257829003601f168201915b505050505081565b6000610313838961083f565b90506000479050610322610823565b73ffffffffffffffffffffffffffffffffffffffff1663b300f752838a8a8a8a6040518663ffffffff1660e01b8152600401610362959493929190612271565b600060405180830381600087803b15801561037c57600080fd5b505af1158015610390573d6000803e3d6000fd5b5050505060006103a047836108e9565b90506103ac84826108fd565b86866040516103bc92919061205a565b604051809103902089896040516103d492919061208c565b60405180910390207fc44585ae385fe053d798d56dc20dc0f0beade803098d105d289637d878fa9c7b83888860405161040f939291906122e3565b60405180910390a350505050505050505050565b61042b610823565b73ffffffffffffffffffffffffffffffffffffffff16633e75a9a883836040518363ffffffff1660e01b8152600401610465929190612139565b600060405180830381600087803b15801561047f57600080fd5b505af1158015610493573d6000803e3d6000fd5b5050505081816040516104a7929190612073565b60405180910390207fb42519a7cf5f104a27b62b10dc1e67721be4b68791899606dd15e1b017bd96316000806040516104e192919061215d565b60405180910390a25050565b60006104f9838561083f565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8114610528578061052a565b475b9050610534610823565b73ffffffffffffffffffffffffffffffffffffffff16639aad3798828b8b8b8b8b6040518763ffffffff1660e01b81526004016105759594939291906120f0565b6000604051808303818588803b15801561058e57600080fd5b505af11580156105a2573d6000803e3d6000fd5b50505050506105b182826108fd565b85856040516105c192919061205a565b604051809103902088886040516105d992919061208c565b60405180910390208a73ffffffffffffffffffffffffffffffffffffffff167f1e9ff70996f352b5b70751209e03ae367633703bfc74ccc966b87e70ab57136184878760405161062b939291906122e3565b60405180910390a4505050505050505050565b610646610823565b73ffffffffffffffffffffffffffffffffffffffff1663b348e26886868686866040518663ffffffff1660e01b81526004016106869594939291906121ca565b600060405180830381600087803b1580156106a057600080fd5b505af11580156106b4573d6000803e3d6000fd5b505050508184846040516106c99291906120a5565b6040518091039020866040516106df91906120be565b60405180910390207f9e2ce841f586026d01f4cdb7bcd28c46154ba65e6766033fee248e3690c35a0d60008060405161071992919061215d565b60405180910390a45050505050565b6000806001602a81915080905080925081935050509091565b610749610823565b73ffffffffffffffffffffffffffffffffffffffff1663ff92b1a88484846040518463ffffffff1660e01b815260040161078593929190612218565b600060405180830381600087803b15801561079f57600080fd5b505af11580156107b3573d6000803e3d6000fd5b5050505080826040516107c691906120d9565b6040518091039020846040516107dc91906120be565b60405180910390207f054a2512b2e1ba381f3ca2abbf5515644385116f44cf8d635382f6df3f41055760008060405161081692919061215d565b60405180910390a4505050565b6000731d681d76ce96e4d70a88a00ebbcfc1e47808d0b8905090565b60008083146108df5761085061097e565b73ffffffffffffffffffffffffffffffffffffffff1663a9c70eaa846040518263ffffffff1660e01b81526004016108889190612256565b602060405180830381600087803b1580156108a257600080fd5b505af11580156108b6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506108da9190810190610e0a565b6108e1565b815b905092915050565b60006108f5838361099a565b905092915050565b6000821461097a5761090d61097e565b73ffffffffffffffffffffffffffffffffffffffff166361e3c94483836040518363ffffffff1660e01b81526004016109479291906122ba565b600060405180830381600087803b15801561096157600080fd5b505af1158015610975573d6000803e3d6000fd5b505050505b5050565b6000738a5419cfc711b2343c17a6abf4b2bafabb06957f905090565b60006109dc83836040518060400160405280601e81526020017f536166654d6174683a207375627472616374696f6e206f766572666c6f7700008152506109e4565b905092915050565b6000838311158290610a2c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610a2391906121a8565b60405180910390fd5b5060008385039050809150509392505050565b600081359050610a4e816128ec565b92915050565b60008083601f840112610a6657600080fd5b8235905067ffffffffffffffff811115610a7f57600080fd5b602083019150836020820283011115610a9757600080fd5b9250929050565b60008083601f840112610ab057600080fd5b8235905067ffffffffffffffff811115610ac957600080fd5b602083019150836020820283011115610ae157600080fd5b9250929050565b60008083601f840112610afa57600080fd5b8235905067ffffffffffffffff811115610b1357600080fd5b602083019150836020820283011115610b2b57600080fd5b9250929050565b60008083601f840112610b4457600080fd5b8235905067ffffffffffffffff811115610b5d57600080fd5b602083019150836020820283011115610b7557600080fd5b9250929050565b600081359050610b8b81612903565b92915050565b600081359050610ba08161291a565b92915050565b600081359050610bb58161292a565b92915050565b600060408284031215610bcd57600080fd5b81905092915050565b600060808284031215610be857600080fd5b81905092915050565b600081359050610c008161293a565b92915050565b600081519050610c158161293a565b92915050565b60008060008060008060008060c0898b031215610c3757600080fd5b6000610c458b828c01610a3f565b985050602089013567ffffffffffffffff811115610c6257600080fd5b610c6e8b828c01610ae8565b9750975050604089013567ffffffffffffffff811115610c8d57600080fd5b610c998b828c01610a54565b95509550506060610cac8b828c01610bf1565b9350506080610cbd8b828c01610bf1565b92505060a0610cce8b828c01610bf1565b9150509295985092959890939650565b60008060208385031215610cf157600080fd5b600083013567ffffffffffffffff811115610d0b57600080fd5b610d1785828601610a9e565b92509250509250929050565b600080600080600060a08688031215610d3b57600080fd5b6000610d4988828901610bbb565b955050604086013567ffffffffffffffff811115610d6657600080fd5b610d7288828901610b32565b94509450506060610d8588828901610bf1565b9250506080610d9688828901610bf1565b9150509295509295909350565b600080600060808486031215610db857600080fd5b6000610dc686828701610bbb565b935050604084013567ffffffffffffffff811115610de357600080fd5b610def86828701610bd6565b9250506060610e0086828701610bf1565b9150509250925092565b600060208284031215610e1c57600080fd5b6000610e2a84828501610c06565b91505092915050565b600080600080600080600060a0888a031215610e4e57600080fd5b6000610e5c8a828b01610bf1565b975050602088013567ffffffffffffffff811115610e7957600080fd5b610e858a828b01610ae8565b9650965050604088013567ffffffffffffffff811115610ea457600080fd5b610eb08a828b01610a54565b94509450506060610ec38a828b01610bf1565b9250506080610ed48a828b01610bf1565b91505092959891949750929550565b6000610eef83836110c1565b60208301905092915050565b6000610f0783836110df565b60208301905092915050565b6000610f20848484611205565b90509392505050565b6000610f368484846112d6565b90509392505050565b6000610f4c8484846113a7565b90509392505050565b6000610f628484846116eb565b90509392505050565b6000610f778383611757565b60208301905092915050565b6000610f90848484611793565b90509392505050565b6000610fa583836117cf565b60208301905092915050565b6000610fbd83836117ed565b60208301905092915050565b6000610fd5838361187d565b905092915050565b6000610fe98383611938565b905092915050565b6000610ffd83836119e5565b905092915050565b60006110118383611a34565b905092915050565b60006110258383611b34565b60408301905092915050565b600061103d8383611b71565b905092915050565b60006110518383611c65565b905092915050565b60006110658383611d47565b905092915050565b60006110798383611dba565b905092915050565b600061108d8383611f24565b905092915050565b60006110a18383611fb2565b905092915050565b60006110b5838361204b565b60208301905092915050565b6110ca816127db565b82525050565b6110d9816127db565b82525050565b6110e8816127db565b82525050565b60006110fa83856123f9565b935061110582612324565b8060005b8581101561113e5761111b82846124f5565b6111258882610ee3565b97506111308361238d565b925050600181019050611109565b5085925050509392505050565b60006111578385612415565b935061116282612324565b8060005b8581101561119b5761117882846124f5565b6111828882610efb565b975061118d8361238d565b925050600181019050611166565b5085925050509392505050565b60006111b483856123e8565b93506111bf8261231a565b8060005b858110156111f8576111d582846124f5565b6111df8882610ee3565b97506111ea83612380565b9250506001810190506111c3565b5085925050509392505050565b6000611211838561240a565b935061121c8261231a565b8060005b858110156112555761123282846124f5565b61123c8882610efb565b975061124783612380565b925050600181019050611220565b5085925050509392505050565b600061126e8385612420565b9350836020840285016112808461232e565b8060005b878110156112c457848403895261129b8284612704565b6112a58582610fc9565b94506112b08361239a565b925060208a01995050600181019050611284565b50829750879450505050509392505050565b60006112e28385612431565b93506112ed8261232e565b8060005b85811015611326576113038284612704565b61130d8882610fdd565b97506113188361239a565b9250506001810190506112f1565b5085925050509392505050565b600061133f838561243c565b93508360208402850161135184612338565b8060005b8781101561139557848403895261136c8284612728565b6113768582610ff1565b9450611381836123a7565b925060208a01995050600181019050611355565b50829750879450505050509392505050565b60006113b3838561244d565b93506113be82612338565b8060005b858110156113f7576113d48284612728565b6113de8882611005565b97506113e9836123a7565b9250506001810190506113c2565b5085925050509392505050565b60006114108385612458565b93508360208402850161142284612342565b8060005b8781101561146657848403895261143d8284612757565b6114478582611031565b9450611452836123b4565b925060208a01995050600181019050611426565b50829750879450505050509392505050565b60006114848385612469565b935061148f82612342565b8060005b858110156114c8576114a58284612757565b6114af8882611045565b97506114ba836123b4565b925050600181019050611493565b5085925050509392505050565b60006114e18385612474565b9350836020840285016114f38461234c565b8060005b8781101561153757848403895261150e828461277c565b6115188582611059565b9450611523836123c1565b925060208a019950506001810190506114f7565b50829750879450505050509392505050565b60006115558385612485565b93506115608261234c565b8060005b8581101561159957611576828461277c565b611580888261106d565b975061158b836123c1565b925050600181019050611564565b5085925050509392505050565b60006115b283856124a1565b9350836020840285016115c484612360565b8060005b878110156116085784840389526115df82846127a0565b6115e98582611081565b94506115f4836123db565b925060208a019950506001810190506115c8565b50829750879450505050509392505050565b600061162683856124bd565b935061163182612360565b8060005b8581101561166a5761164782846127a0565b6116518882611095565b975061165c836123db565b925050600181019050611635565b5085925050509392505050565b60006116838385612490565b93508360208402850161169584612356565b8060005b878110156116d95784840389526116b082846127a0565b6116ba8582611081565b94506116c5836123ce565b925060208a01995050600181019050611699565b50829750879450505050509392505050565b60006116f783856124b2565b935061170282612356565b8060005b8581101561173b5761171882846127a0565b6117228882611095565b975061172d836123ce565b925050600181019050611706565b5085925050509392505050565b611751816127ed565b82525050565b611760816127ed565b82525050565b600061177283856124c8565b935061177f83858461287f565b611788836128c1565b840190509392505050565b600061179f83856124d9565b93506117ac83858461287f565b6117b5836128c1565b840190509392505050565b6117c981612849565b82525050565b6117d881612849565b82525050565b6117e78161285b565b82525050565b6117f68161285b565b82525050565b6118058161286d565b82525050565b600061181682612375565b61182081856124e4565b935061183081856020860161288e565b611839816128c1565b840191505092915050565b600061184f8261236a565b61185981856124e4565b935061186981856020860161288e565b611872816128c1565b840191505092915050565b600060c0830161189060008401846124f5565b61189d60008601826110c1565b506118ab602084018461267f565b85830360208701526118be838284611766565b925050506118cf60408401846126ed565b6118dc60408601826117de565b506118ea60608401846126d6565b6118f760608601826117c0565b5061190560808401846127c4565b611912608086018261202d565b5061192060a0840184612668565b61192d60a0860182611748565b508091505092915050565b600080830161194a60008401846124f5565b6119548582610efb565b945050611964602084018461267f565b61196f868284610f83565b9550505061198060408401846126ed565b61198a8582610fb1565b94505061199a60608401846126d6565b6119a48582610f99565b9450506119b460808401846127c4565b6119be85826110a9565b9450506119ce60a0840184612668565b6119d88582610f6b565b9450508391505092915050565b6000604083016119f860008401846124f5565b611a0560008601826110c1565b50611a13602084018461267f565b8583036020870152611a26838284611766565b925050508091505092915050565b6000808301611a4660008401846124f5565b611a508582610efb565b945050611a60602084018461267f565b611a6b868284610f83565b955050508391505092915050565b60408201611a8a60008301836124f5565b611a9760008501826110c1565b50611aa560208301836124f5565b611ab260208501826110c1565b50505050565b60008201611ac960008301836124f5565b611ad38482610efb565b935050611ae360208301836124f5565b611aed8482610efb565b935050505050565b60408201611b0660008301836124f5565b611b1360008501826110c1565b50611b2160208301836124f5565b611b2e60208501826110c1565b50505050565b60008201611b4560008301836124f5565b611b4f8482610efb565b935050611b5f60208301836124f5565b611b698482610efb565b935050505050565b60006101208301611b8560008401846127c4565b611b92600086018261202d565b50611ba060208401846124f5565b611bad60208601826110c1565b50611bbb604084018461274c565b611bc86040860182611af5565b50611bd660808401846127c4565b611be3608086018261202d565b50611bf160a0840184612611565b85830360a0870152611c04838284611677565b92505050611c1560c08401846127c4565b611c2260c086018261202d565b50611c3060e08401846127c4565b611c3d60e086018261202d565b50611c4c6101008401846127c4565b611c5a61010086018261202d565b508091505092915050565b6000808301611c7760008401846127c4565b611c8185826110a9565b945050611c9160208401846124f5565b611c9b8582610efb565b945050611cab604084018461274c565b611cb58582611019565b945050611cc560808401846127c4565b611ccf85826110a9565b945050611cdf60a0840184612611565b611cea868284610f55565b95505050611cfb60c08401846127c4565b611d0585826110a9565b945050611d1560e08401846127c4565b611d1f85826110a9565b945050611d306101008401846127c4565b611d3a85826110a9565b9450508391505092915050565b600060608301611d5a600084018461250c565b8583036000870152611d6d8382846111a8565b92505050611d7e6020840184612563565b8583036020870152611d91838284611262565b92505050611da260408401846127c4565b611daf604086018261202d565b508091505092915050565b6000808301611dcc600084018461250c565b611dd7868284610f13565b95505050611de86020840184612563565b611df3868284610f29565b95505050611e0460408401846127c4565b611e0e85826110a9565b9450508391505092915050565b600060808301611e2e60008401846125ba565b8583036000870152611e41838284611333565b92505050611e526020840184612563565b8583036020870152611e65838284611262565b92505050611e7660408401846127c4565b611e83604086018261202d565b50611e9160608401846127c4565b611e9e606086018261202d565b508091505092915050565b6000808301611ebb60008401846125ba565b611ec6868284610f3f565b95505050611ed76020840184612563565b611ee2868284610f29565b95505050611ef360408401846127c4565b611efd85826110a9565b945050611f0d60608401846127c4565b611f1785826110a9565b9450508391505092915050565b600060808301611f3760008401846125ba565b8583036000870152611f4a838284611333565b92505050611f5b6020840184612563565b8583036020870152611f6e838284611262565b92505050611f7f60408401846127c4565b611f8c604086018261202d565b50611f9a60608401846127c4565b611fa7606086018261202d565b508091505092915050565b6000808301611fc460008401846125ba565b611fcf868284610f3f565b95505050611fe06020840184612563565b611feb868284610f29565b95505050611ffc60408401846127c4565b61200685826110a9565b94505061201660608401846127c4565b61202085826110a9565b9450508391505092915050565b6120368161283f565b82525050565b6120458161283f565b82525050565b6120548161283f565b82525050565b600061206782848661114b565b91508190509392505050565b6000612080828486611478565b91508190509392505050565b6000612099828486611549565b91508190509392505050565b60006120b282848661161a565b91508190509392505050565b60006120ca8284611ab8565b60408201915081905092915050565b60006120e58284611ea9565b915081905092915050565b600060608201905061210560008301886110d0565b81810360208301526121188186886114d5565b9050818103604083015261212d8184866110ee565b90509695505050505050565b60006020820190508181036000830152612154818486611404565b90509392505050565b600060408201905061217260008301856117fc565b61217f60208301846117fc565b9392505050565b600060208201905081810360008301526121a08184611844565b905092915050565b600060208201905081810360008301526121c2818461180b565b905092915050565b600060a0820190506121df6000830188611a79565b81810360408301526121f28186886115a6565b9050612201606083018561203c565b61220e608083018461203c565b9695505050505050565b600060808201905061222d6000830186611a79565b818103604083015261223f8185611e1b565b905061224e606083018461203c565b949350505050565b600060208201905061226b600083018461203c565b92915050565b6000606082019050612286600083018861203c565b81810360208301526122998186886114d5565b905081810360408301526122ae8184866110ee565b90509695505050505050565b60006040820190506122cf600083018561203c565b6122dc602083018461203c565b9392505050565b60006060820190506122f8600083018661203c565b612305602083018561203c565b612312604083018461203c565b949350505050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b6000819050919050565b600081519050919050565b600081519050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b6000602082019050919050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b600082825260208201905092915050565b600081905092915050565b600081905092915050565b600082825260208201905092915050565b600081905092915050565b600082825260208201905092915050565b60006125046020840184610a3f565b905092915050565b6000808335600160200384360303811261252557600080fd5b83810192508235915060208301925067ffffffffffffffff82111561254957600080fd5b60208202360384131561255b57600080fd5b509250929050565b6000808335600160200384360303811261257c57600080fd5b83810192508235915060208301925067ffffffffffffffff8211156125a057600080fd5b6020820236038413156125b257600080fd5b509250929050565b600080833560016020038436030381126125d357600080fd5b83810192508235915060208301925067ffffffffffffffff8211156125f757600080fd5b60208202360384131561260957600080fd5b509250929050565b6000808335600160200384360303811261262a57600080fd5b83810192508235915060208301925067ffffffffffffffff82111561264e57600080fd5b60208202360384131561266057600080fd5b509250929050565b60006126776020840184610b7c565b905092915050565b6000808335600160200384360303811261269857600080fd5b83810192508235915060208301925067ffffffffffffffff8211156126bc57600080fd5b6001820236038413156126ce57600080fd5b509250929050565b60006126e56020840184610b91565b905092915050565b60006126fc6020840184610ba6565b905092915050565b60008235600160c00383360303811261271c57600080fd5b82810191505092915050565b60008235600160400383360303811261274057600080fd5b82810191505092915050565b600082905092915050565b6000823560016101200383360303811261277057600080fd5b82810191505092915050565b60008235600160600383360303811261279457600080fd5b82810191505092915050565b6000823560016080038336030381126127b857600080fd5b82810191505092915050565b60006127d36020840184610bf1565b905092915050565b60006127e68261281f565b9050919050565b60008115159050919050565b6000819050612807826128d2565b919050565b600081905061281a826128df565b919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000819050919050565b6000612854826127f9565b9050919050565b60006128668261280c565b9050919050565b60006128788261283f565b9050919050565b82818337600083830152505050565b60005b838110156128ac578082015181840152602081019050612891565b838111156128bb576000848401525b50505050565b6000601f19601f8301169050919050565b600481106128dc57fe5b50565b600281106128e957fe5b50565b6128f5816127db565b811461290057600080fd5b50565b61290c816127ed565b811461291757600080fd5b50565b6004811061292757600080fd5b50565b6002811061293757600080fd5b50565b6129438161283f565b811461294e57600080fd5b5056fea264697066735822122088280a6b796c8b831d87a8e867c7a16ddf6e9d066a788dbb3b6423cf352f357864736f6c63430006020033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/pre-compiles/ConnectInstaPool.json b/pre-compiles/ConnectInstaPool.json new file mode 100644 index 0000000..7aa548d --- /dev/null +++ b/pre-compiles/ConnectInstaPool.json @@ -0,0 +1,443 @@ +{ + "contractName": "ConnectInstaPool", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogDepositLiquidity", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogFlashBorrow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "feeCollected", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogFlashPayback", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "origin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "originFeeAmt", + "type": "uint256" + } + ], + "name": "LogOriginFeeCollected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenAmt", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "LogWithdrawLiquidity", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "addFeeAmount", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "connectorID", + "outputs": [ + { + "internalType": "uint256", + "name": "_type", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_id", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "deposit", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "flashBorrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amts", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "getId", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "setId", + "type": "uint256[]" + } + ], + "name": "flashMultiBorrow", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "getId", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "setId", + "type": "uint256[]" + } + ], + "name": "flashMultiPayback", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "origin", + "type": "address" + }, + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "getId", + "type": "uint256[]" + }, + { + "internalType": "uint256[]", + "name": "setId", + "type": "uint256[]" + } + ], + "name": "flashMultiPaybackOrigin", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "flashPayback", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "origin", + "type": "address" + }, + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "flashPaybackOrigin", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amt", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "getId", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "setId", + "type": "uint256" + } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "payable", + "type": "function" + } + ], + "bytecode": "0x60c0604052600e60808190526d496e737461506f6f6c2d76322e3160901b60a090815262000031916000919062000046565b503480156200003f57600080fd5b50620000e2565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200008957805160ff1916838001178555620000b9565b82800160010185558215620000b9579182015b82811115620000b95782518255916020019190600101906200009c565b50620000c7929150620000cb565b5090565b5b80821115620000c75760008155600101620000cc565b61231680620000f26000396000f3fe60806040526004361061009c5760003560e01c80635aedbd68116100645780635aedbd681461011a57806362c587ef1461012d578063b737f01b14610140578063ce88b43914610153578063eaef2b7614610166578063eb15f781146101795761009c565b806306fdde03146100a15780630f65e079146100cc5780631690991c146100e15780632925a4f5146100f45780634532d77614610107575b600080fd5b3480156100ad57600080fd5b506100b661019c565b6040516100c391906120d2565b60405180910390f35b6100df6100da366004611cb1565b61022a565b005b6100df6100ef366004611db5565b6103ba565b6100df610102366004611ce5565b610575565b6100df610115366004611ce5565b6105c9565b6100df610128366004611ce5565b61075f565b6100df61013b366004611bc3565b61087c565b6100df61014e366004611d1f565b610a41565b6100df610161366004611ce5565b610c33565b6100df610174366004611c08565b610f21565b34801561018557600080fd5b5061018e611107565b6040516100c3929190612238565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156102225780601f106101f757610100808354040283529160200191610222565b820191906000526020600020905b81548152906001019060200180831161020557829003601f168201915b505050505081565b600061023461110f565b90506000816001600160a01b03166384a0e58f866040518263ffffffff1660e01b81526004016102649190611fa3565b60206040518083038186803b15801561027c57600080fd5b505afa158015610290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b49190611e94565b9050846000806102c48385611127565b604080516001808252818301909252929450909250606091906020808301908036833701905050905088816000815181106102fb57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061032686858761129c565b60405163030ecdeb60e21b81526001600160a01b03871690630c3b37ac90610352908490600401612091565b600060405180830381600087803b15801561036c57600080fd5b505af1158015610380573d6000803e3d6000fd5b5050505060008211156103985761039883858461129c565b6103a28786611312565b6103af8986848b8b61137f565b505050505050505050565b8660608167ffffffffffffffff811180156103d457600080fd5b506040519080825280602002602001820160405280156103fe578160200160208202803683370190505b50905060005b828110156104595761043a87878381811061041b57fe5b905060200201358a8a8481811061042e57fe5b90506020020135611404565b82828151811061044657fe5b6020908102919091010152600101610404565b5061046261110f565b6001600160a01b0316632a9dcb068b8b846040518463ffffffff1660e01b815260040161049193929190612061565b600060405180830381600087803b1580156104ab57600080fd5b505af11580156104bf573d6000803e3d6000fd5b5050505060005b82811015610568576104fd8585838181106104dd57fe5b905060200201358383815181106104f057fe5b6020026020010151611312565b6105608b8b8381811061050c57fe5b90506020020160208101906105219190611b8b565b83838151811061052d57fe5b602002602001015189898581811061054157fe5b9050602002013588888681811061055457fe5b9050602002013561149f565b6001016104c6565b5050505050505050505050565b60006105818385611404565b9050806105a95760405162461bcd60e51b81526004016105a090612113565b60405180910390fd5b60006105b58683611579565b90506105c18382611312565b505050505050565b60006105d58385611404565b90506105df61110f565b6001600160a01b031663f3fef3a386836040518363ffffffff1660e01b815260040161060c929190611fe0565b600060405180830381600087803b15801561062657600080fd5b505af115801561063a573d6000803e3d6000fd5b505050506106488282611312565b846001600160a01b03167f9ff4cb7f3b4986a113dbb55a03744331895ce0f50a84928bd60a323e213a82ab8285856040516106859392919061226b565b60405180910390a26040517f9ff4cb7f3b4986a113dbb55a03744331895ce0f50a84928bd60a323e213a82ab906060906106c9908890859088908890602001611ff9565b60405160208183030381529060405290506000806106e5611107565b915091506106f16116ae565b6001600160a01b031663e14d4fb1838387876040518563ffffffff1660e01b81526004016107229493929190612246565b600060405180830381600087803b15801561073c57600080fd5b505af1158015610750573d6000803e3d6000fd5b50505050505050505050505050565b600061076b8385611404565b6040805160018082528183019092529192506060919060208083019080368337019050509050858160008151811061079f57fe5b6001600160a01b03929092166020928302919091019091015260408051600180825281830190925260609181602001602082028036833701905050905082816000815181106107ea57fe5b6020026020010181815250506107fe61110f565b6001600160a01b0316632a9dcb0683836040518363ffffffff1660e01b815260040161082b9291906120a4565b600060405180830381600087803b15801561084557600080fd5b505af1158015610859573d6000803e3d6000fd5b505050506108678484611312565b6108738784878761149f565b50505050505050565b6001600160a01b0384166108a25760405162461bcd60e51b81526004016105a0906120e5565b60006108ac61110f565b90506000816001600160a01b03166384a0e58f866040518263ffffffff1660e01b81526004016108dc9190611fa3565b60206040518083038186803b1580156108f457600080fd5b505afa158015610908573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092c9190611e94565b9050846000808061093d84866116c6565b60408051600180825281830190925293965091945092506060919060208083019080368337019050509050898160008151811061097657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506109a187868861129c565b60405163030ecdeb60e21b81526001600160a01b03881690630c3b37ac906109cd908490600401612091565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050506000831115610a1e57610a1384868561129c565b610a1e8b868461129c565b610a288887611312565b610a358a87858c8c61137f565b6105688b8b8885611716565b6000610a4b61110f565b90508560005b81811015610bc8576000836001600160a01b03166384a0e58f8b8b85818110610a7657fe5b9050602002016020810190610a8b9190611b8b565b6040518263ffffffff1660e01b8152600401610aa79190611fa3565b60206040518083038186803b158015610abf57600080fd5b505afa158015610ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af79190611e94565b905060008a8a84818110610b0757fe5b9050602002016020810190610b1c9190611b8b565b9050600080610b2b8385611127565b91509150610b3a87848661129c565b8015610b4b57610b4b82848361129c565b610b67898987818110610b5a57fe5b9050602002013585611312565b610bb88d8d87818110610b7657fe5b9050602002016020810190610b8b9190611b8b565b85838e8e8a818110610b9957fe5b905060200201358d8d8b818110610bac57fe5b9050602002013561137f565b505060019092019150610a519050565b5060405163030ecdeb60e21b81526001600160a01b03831690630c3b37ac90610bf7908b908b9060040161204d565b600060405180830381600087803b158015610c1157600080fd5b505af1158015610c25573d6000803e3d6000fd5b505050505050505050505050565b6000610c3f8385611404565b90506000610c4b61179f565b6001600160a01b0316866001600160a01b03161415610c7f576000198214610c735781610c75565b475b9150819050610d97565b856000198314610c8f5782610d0b565b6040516370a0823160e01b81526001600160a01b038216906370a0823190610cbb903090600401611fa3565b60206040518083038186803b158015610cd357600080fd5b505afa158015610ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0b9190611e94565b9250806001600160a01b031663095ea7b3610d2461110f565b856040518363ffffffff1660e01b8152600401610d42929190611fe0565b602060405180830381600087803b158015610d5c57600080fd5b505af1158015610d70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d949190611e74565b50505b610d9f61110f565b6001600160a01b03166347e7ef248288856040518463ffffffff1660e01b8152600401610dcd929190611fe0565b6000604051808303818588803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b5050505050610e098383611312565b856001600160a01b03167f14f2c3630383ff6f8febe0920fe216fdd5215bad47bc4330529f4dec17994603838686604051610e469392919061226b565b60405180910390a26040517f14f2c3630383ff6f8febe0920fe216fdd5215bad47bc4330529f4dec1799460390606090610e8a908990869089908990602001611ff9565b6040516020818303038152906040529050600080610ea6611107565b91509150610eb26116ae565b6001600160a01b031663e14d4fb1838387876040518563ffffffff1660e01b8152600401610ee39493929190612246565b600060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b5050505050505050505050505050565b6000610f2b61110f565b90508560005b818110156110d8576000836001600160a01b03166384a0e58f8b8b85818110610f5657fe5b9050602002016020810190610f6b9190611b8b565b6040518263ffffffff1660e01b8152600401610f879190611fa3565b60206040518083038186803b158015610f9f57600080fd5b505afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd79190611e94565b905060008a8a84818110610fe757fe5b9050602002016020810190610ffc9190611b8b565b9050600080600061100d84866116c6565b92509250925061101e88858761129c565b811561103a5761102f83858461129c565b61103a8f858361129c565b6110568a8a8881811061104957fe5b9050602002013586611312565b61109b8e8e8881811061106557fe5b905060200201602081019061107a9190611b8b565b86848f8f8b81811061108857fe5b905060200201358e8e8c818110610bac57fe5b6110c78f8f8f898181106110ab57fe5b90506020020160208101906110c09190611b8b565b8784611716565b505060019093019250610f31915050565b5060405163030ecdeb60e21b81526001600160a01b03831690630c3b37ac90610722908b908b9060040161204d565b600190602190565b7306cb7c24990cbe6b9f99982f975f9147c000fec690565b60008060006111346117b7565b90506000816001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561117157600080fd5b505afa158015611185573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a99190611e94565b9050816001600160a01b031663c415b95c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111e457600080fd5b505afa1580156111f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121c9190611ba7565b93508061122c5760009250611293565b61123685826117cf565b925060006112448685611804565b905060006112518861182d565b9050600a82038110156112765760405162461bcd60e51b81526004016105a0906121b9565b81811161128c5761128781886118d7565b61128e565b845b945050505b50509250929050565b6112a461179f565b6001600160a01b0316826001600160a01b0316146112d5576112d06001600160a01b03831684836118fa565b61130d565b6040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561130b573d6000803e3d6000fd5b505b505050565b811561137b57611320611950565b6001600160a01b03166361e3c94483836040518363ffffffff1660e01b815260040161134d929190612238565b600060405180830381600087803b15801561136757600080fd5b505af11580156105c1573d6000803e3d6000fd5b5050565b846001600160a01b03167f718f2debe25ea9b628399a4db9e7a36b83b97b62308695be0df1b3f257582c92858585856040516113be9493929190612281565b60405180910390a26040517f718f2debe25ea9b628399a4db9e7a36b83b97b62308695be0df1b3f257582c92906060906106c9908890889088908890889060200161201f565b6000821561149657611414611950565b6001600160a01b031663a9c70eaa846040518263ffffffff1660e01b815260040161143f919061222f565b602060405180830381600087803b15801561145957600080fd5b505af115801561146d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114919190611e94565b611498565b815b9392505050565b836001600160a01b03167f019cbd45a253e15f12114d2ec3b4ff4029bbb4d9d484c003b11a06c358b5923c8484846040516114dc9392919061226b565b60405180910390a26040517f019cbd45a253e15f12114d2ec3b4ff4029bbb4d9d484c003b11a06c358b5923c90606090611520908790879087908790602001611ff9565b604051602081830303815290604052905060008061153c611107565b915091506115486116ae565b6001600160a01b031663e14d4fb1838387876040518563ffffffff1660e01b8152600401610bf79493929190612246565b6000806115846117b7565b6001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b1580156115bc57600080fd5b505afa1580156115d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f49190611e94565b9050600061160061110f565b6001600160a01b03166384a0e58f866040518263ffffffff1660e01b815260040161162b9190611fa3565b60206040518083038186803b15801561164357600080fd5b505afa158015611657573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167b9190611e94565b90508161168a578392506116a6565b600061169682846117cf565b90506116a28582611804565b9350505b505092915050565b732af7ea6cb911035f3eb1ed895cb6692c39ecba9790565b6000806000806116d68686611127565b9094509050806116ed57600092506000915061170e565b6116ff816702c68af0bb1400006117cf565b915061170b81836118d7565b92505b509250925092565b826001600160a01b0316846001600160a01b03167f052e745f308c35fe80c9dae44eed9043ab6e2fbadf46f56fa11dba91992ab32a848460405161175b929190612238565b60405180910390a36040517f052e745f308c35fe80c9dae44eed9043ab6e2fbadf46f56fa11dba91992ab32a90606090611520908790879087908790602001611fb7565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90565b73aaa91046c1d1a210017e36394c83bd5070dadda590565b6000670de0b6b3a76400006117f56117e78585611968565b6706f05b59d3b20000611804565b816117fc57fe5b049392505050565b808201828110156118275760405162461bcd60e51b81526004016105a090612135565b92915050565b600061183761179f565b6001600160a01b0316826001600160a01b0316146118d0576040516370a0823160e01b81526001600160a01b038316906370a082319061187b903090600401611fa3565b60206040518083038186803b15801561189357600080fd5b505afa1580156118a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cb9190611e94565b611827565b4792915050565b808203828111156118275760405162461bcd60e51b81526004016105a09061215c565b61130d8363a9059cbb60e01b8484604051602401611919929190611fe0565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261199f565b738a5419cfc711b2343c17a6abf4b2bafabb06957f90565b60008115806119835750508082028282828161198057fe5b04145b6118275760405162461bcd60e51b81526004016105a090612135565b60606119f4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a2e9092919063ffffffff16565b80519091501561130d5780806020019051810190611a129190611e74565b61130d5760405162461bcd60e51b81526004016105a0906121e5565b6060611a3d8484600085611a45565b949350505050565b6060611a5085611b09565b611a6c5760405162461bcd60e51b81526004016105a090612182565b60006060866001600160a01b03168587604051611a899190611f87565b60006040518083038185875af1925050503d8060008114611ac6576040519150601f19603f3d011682016040523d82523d6000602084013e611acb565b606091505b50915091508115611adf579150611a3d9050565b805115611aef5780518082602001fd5b8360405162461bcd60e51b81526004016105a091906120d2565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611a3d575050151592915050565b60008083601f840112611b53578182fd5b50813567ffffffffffffffff811115611b6a578182fd5b6020830191508360208083028501011115611b8457600080fd5b9250929050565b600060208284031215611b9c578081fd5b8135611498816122c8565b600060208284031215611bb8578081fd5b8151611498816122c8565b60008060008060808587031215611bd8578283fd5b8435611be3816122c8565b93506020850135611bf3816122c8565b93969395505050506040820135916060013590565b60008060008060008060006080888a031215611c22578283fd5b8735611c2d816122c8565b9650602088013567ffffffffffffffff80821115611c49578485fd5b611c558b838c01611b42565b909850965060408a0135915080821115611c6d578485fd5b611c798b838c01611b42565b909650945060608a0135915080821115611c91578384fd5b50611c9e8a828b01611b42565b989b979a50959850939692959293505050565b600080600060608486031215611cc5578283fd5b8335611cd0816122c8565b95602085013595506040909401359392505050565b60008060008060808587031215611cfa578384fd5b8435611d05816122c8565b966020860135965060408601359560600135945092505050565b60008060008060008060608789031215611d37578182fd5b863567ffffffffffffffff80821115611d4e578384fd5b611d5a8a838b01611b42565b90985096506020890135915080821115611d72578384fd5b611d7e8a838b01611b42565b90965094506040890135915080821115611d96578384fd5b50611da389828a01611b42565b979a9699509497509295939492505050565b6000806000806000806000806080898b031215611dd0578081fd5b883567ffffffffffffffff80821115611de7578283fd5b611df38c838d01611b42565b909a50985060208b0135915080821115611e0b578283fd5b611e178c838d01611b42565b909850965060408b0135915080821115611e2f578283fd5b611e3b8c838d01611b42565b909650945060608b0135915080821115611e53578283fd5b50611e608b828c01611b42565b999c989b5096995094979396929594505050565b600060208284031215611e85578081fd5b81518015158114611498578182fd5b600060208284031215611ea5578081fd5b5051919050565b60008284526020808501945082825b85811015611ee9578135611ece816122c8565b6001600160a01b031687529582019590820190600101611ebb565b509495945050505050565b6000815180845260208085019450808401835b83811015611ee95781516001600160a01b031687529582019590820190600101611f07565b6000815180845260208085019450808401835b83811015611ee957815187529582019590820190600101611f3f565b60008151808452611f7381602086016020860161229c565b601f01601f19169290920160200192915050565b60008251611f9981846020870161229c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03959095168552602085019390935260408401919091526060830152608082015260a00190565b600060208252611a3d602083018486611eac565b600060408252612075604083018587611eac565b82810360208401526120878185611f2c565b9695505050505050565b6000602082526114986020830184611ef4565b6000604082526120b76040830185611ef4565b82810360208401526120c98185611f2c565b95945050505050565b6000602082526114986020830184611f5b565b6020808252601490820152736f726967696e2d69732d6164647265737328302960601b604082015260600190565b6020808252600890820152670616d742d69732d360c41b604082015260600190565b6020808252600d908201526c6d6174682d6e6f742d7361666560981b604082015260600190565b6020808252600c908201526b7375622d6f766572666c6f7760a01b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601290820152714e6f742d656e6f7567682d62616c616e636560701b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b90815260200190565b918252602082015260400190565b6000858252846020830152836040830152608060608301526120876080830184611f5b565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b60005b838110156122b757818101518382015260200161229f565b8381111561130b5750506000910152565b6001600160a01b03811681146122dd57600080fd5b5056fea26469706673582212204d21e76bf7967029aa6dbf62c4fc819e2d51c9eddb5a59c01da679cdcda2ac8f64736f6c634300060c0033", + "deployedBytecode": "0x60806040526004361061009c5760003560e01c80635aedbd68116100645780635aedbd681461011a57806362c587ef1461012d578063b737f01b14610140578063ce88b43914610153578063eaef2b7614610166578063eb15f781146101795761009c565b806306fdde03146100a15780630f65e079146100cc5780631690991c146100e15780632925a4f5146100f45780634532d77614610107575b600080fd5b3480156100ad57600080fd5b506100b661019c565b6040516100c391906120d2565b60405180910390f35b6100df6100da366004611cb1565b61022a565b005b6100df6100ef366004611db5565b6103ba565b6100df610102366004611ce5565b610575565b6100df610115366004611ce5565b6105c9565b6100df610128366004611ce5565b61075f565b6100df61013b366004611bc3565b61087c565b6100df61014e366004611d1f565b610a41565b6100df610161366004611ce5565b610c33565b6100df610174366004611c08565b610f21565b34801561018557600080fd5b5061018e611107565b6040516100c3929190612238565b6000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156102225780601f106101f757610100808354040283529160200191610222565b820191906000526020600020905b81548152906001019060200180831161020557829003601f168201915b505050505081565b600061023461110f565b90506000816001600160a01b03166384a0e58f866040518263ffffffff1660e01b81526004016102649190611fa3565b60206040518083038186803b15801561027c57600080fd5b505afa158015610290573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102b49190611e94565b9050846000806102c48385611127565b604080516001808252818301909252929450909250606091906020808301908036833701905050905088816000815181106102fb57fe5b60200260200101906001600160a01b031690816001600160a01b03168152505061032686858761129c565b60405163030ecdeb60e21b81526001600160a01b03871690630c3b37ac90610352908490600401612091565b600060405180830381600087803b15801561036c57600080fd5b505af1158015610380573d6000803e3d6000fd5b5050505060008211156103985761039883858461129c565b6103a28786611312565b6103af8986848b8b61137f565b505050505050505050565b8660608167ffffffffffffffff811180156103d457600080fd5b506040519080825280602002602001820160405280156103fe578160200160208202803683370190505b50905060005b828110156104595761043a87878381811061041b57fe5b905060200201358a8a8481811061042e57fe5b90506020020135611404565b82828151811061044657fe5b6020908102919091010152600101610404565b5061046261110f565b6001600160a01b0316632a9dcb068b8b846040518463ffffffff1660e01b815260040161049193929190612061565b600060405180830381600087803b1580156104ab57600080fd5b505af11580156104bf573d6000803e3d6000fd5b5050505060005b82811015610568576104fd8585838181106104dd57fe5b905060200201358383815181106104f057fe5b6020026020010151611312565b6105608b8b8381811061050c57fe5b90506020020160208101906105219190611b8b565b83838151811061052d57fe5b602002602001015189898581811061054157fe5b9050602002013588888681811061055457fe5b9050602002013561149f565b6001016104c6565b5050505050505050505050565b60006105818385611404565b9050806105a95760405162461bcd60e51b81526004016105a090612113565b60405180910390fd5b60006105b58683611579565b90506105c18382611312565b505050505050565b60006105d58385611404565b90506105df61110f565b6001600160a01b031663f3fef3a386836040518363ffffffff1660e01b815260040161060c929190611fe0565b600060405180830381600087803b15801561062657600080fd5b505af115801561063a573d6000803e3d6000fd5b505050506106488282611312565b846001600160a01b03167f9ff4cb7f3b4986a113dbb55a03744331895ce0f50a84928bd60a323e213a82ab8285856040516106859392919061226b565b60405180910390a26040517f9ff4cb7f3b4986a113dbb55a03744331895ce0f50a84928bd60a323e213a82ab906060906106c9908890859088908890602001611ff9565b60405160208183030381529060405290506000806106e5611107565b915091506106f16116ae565b6001600160a01b031663e14d4fb1838387876040518563ffffffff1660e01b81526004016107229493929190612246565b600060405180830381600087803b15801561073c57600080fd5b505af1158015610750573d6000803e3d6000fd5b50505050505050505050505050565b600061076b8385611404565b6040805160018082528183019092529192506060919060208083019080368337019050509050858160008151811061079f57fe5b6001600160a01b03929092166020928302919091019091015260408051600180825281830190925260609181602001602082028036833701905050905082816000815181106107ea57fe5b6020026020010181815250506107fe61110f565b6001600160a01b0316632a9dcb0683836040518363ffffffff1660e01b815260040161082b9291906120a4565b600060405180830381600087803b15801561084557600080fd5b505af1158015610859573d6000803e3d6000fd5b505050506108678484611312565b6108738784878761149f565b50505050505050565b6001600160a01b0384166108a25760405162461bcd60e51b81526004016105a0906120e5565b60006108ac61110f565b90506000816001600160a01b03166384a0e58f866040518263ffffffff1660e01b81526004016108dc9190611fa3565b60206040518083038186803b1580156108f457600080fd5b505afa158015610908573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061092c9190611e94565b9050846000808061093d84866116c6565b60408051600180825281830190925293965091945092506060919060208083019080368337019050509050898160008151811061097657fe5b60200260200101906001600160a01b031690816001600160a01b0316815250506109a187868861129c565b60405163030ecdeb60e21b81526001600160a01b03881690630c3b37ac906109cd908490600401612091565b600060405180830381600087803b1580156109e757600080fd5b505af11580156109fb573d6000803e3d6000fd5b505050506000831115610a1e57610a1384868561129c565b610a1e8b868461129c565b610a288887611312565b610a358a87858c8c61137f565b6105688b8b8885611716565b6000610a4b61110f565b90508560005b81811015610bc8576000836001600160a01b03166384a0e58f8b8b85818110610a7657fe5b9050602002016020810190610a8b9190611b8b565b6040518263ffffffff1660e01b8152600401610aa79190611fa3565b60206040518083038186803b158015610abf57600080fd5b505afa158015610ad3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610af79190611e94565b905060008a8a84818110610b0757fe5b9050602002016020810190610b1c9190611b8b565b9050600080610b2b8385611127565b91509150610b3a87848661129c565b8015610b4b57610b4b82848361129c565b610b67898987818110610b5a57fe5b9050602002013585611312565b610bb88d8d87818110610b7657fe5b9050602002016020810190610b8b9190611b8b565b85838e8e8a818110610b9957fe5b905060200201358d8d8b818110610bac57fe5b9050602002013561137f565b505060019092019150610a519050565b5060405163030ecdeb60e21b81526001600160a01b03831690630c3b37ac90610bf7908b908b9060040161204d565b600060405180830381600087803b158015610c1157600080fd5b505af1158015610c25573d6000803e3d6000fd5b505050505050505050505050565b6000610c3f8385611404565b90506000610c4b61179f565b6001600160a01b0316866001600160a01b03161415610c7f576000198214610c735781610c75565b475b9150819050610d97565b856000198314610c8f5782610d0b565b6040516370a0823160e01b81526001600160a01b038216906370a0823190610cbb903090600401611fa3565b60206040518083038186803b158015610cd357600080fd5b505afa158015610ce7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d0b9190611e94565b9250806001600160a01b031663095ea7b3610d2461110f565b856040518363ffffffff1660e01b8152600401610d42929190611fe0565b602060405180830381600087803b158015610d5c57600080fd5b505af1158015610d70573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d949190611e74565b50505b610d9f61110f565b6001600160a01b03166347e7ef248288856040518463ffffffff1660e01b8152600401610dcd929190611fe0565b6000604051808303818588803b158015610de657600080fd5b505af1158015610dfa573d6000803e3d6000fd5b5050505050610e098383611312565b856001600160a01b03167f14f2c3630383ff6f8febe0920fe216fdd5215bad47bc4330529f4dec17994603838686604051610e469392919061226b565b60405180910390a26040517f14f2c3630383ff6f8febe0920fe216fdd5215bad47bc4330529f4dec1799460390606090610e8a908990869089908990602001611ff9565b6040516020818303038152906040529050600080610ea6611107565b91509150610eb26116ae565b6001600160a01b031663e14d4fb1838387876040518563ffffffff1660e01b8152600401610ee39493929190612246565b600060405180830381600087803b158015610efd57600080fd5b505af1158015610f11573d6000803e3d6000fd5b5050505050505050505050505050565b6000610f2b61110f565b90508560005b818110156110d8576000836001600160a01b03166384a0e58f8b8b85818110610f5657fe5b9050602002016020810190610f6b9190611b8b565b6040518263ffffffff1660e01b8152600401610f879190611fa3565b60206040518083038186803b158015610f9f57600080fd5b505afa158015610fb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd79190611e94565b905060008a8a84818110610fe757fe5b9050602002016020810190610ffc9190611b8b565b9050600080600061100d84866116c6565b92509250925061101e88858761129c565b811561103a5761102f83858461129c565b61103a8f858361129c565b6110568a8a8881811061104957fe5b9050602002013586611312565b61109b8e8e8881811061106557fe5b905060200201602081019061107a9190611b8b565b86848f8f8b81811061108857fe5b905060200201358e8e8c818110610bac57fe5b6110c78f8f8f898181106110ab57fe5b90506020020160208101906110c09190611b8b565b8784611716565b505060019093019250610f31915050565b5060405163030ecdeb60e21b81526001600160a01b03831690630c3b37ac90610722908b908b9060040161204d565b600190602190565b7306cb7c24990cbe6b9f99982f975f9147c000fec690565b60008060006111346117b7565b90506000816001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b15801561117157600080fd5b505afa158015611185573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a99190611e94565b9050816001600160a01b031663c415b95c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111e457600080fd5b505afa1580156111f8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121c9190611ba7565b93508061122c5760009250611293565b61123685826117cf565b925060006112448685611804565b905060006112518861182d565b9050600a82038110156112765760405162461bcd60e51b81526004016105a0906121b9565b81811161128c5761128781886118d7565b61128e565b845b945050505b50509250929050565b6112a461179f565b6001600160a01b0316826001600160a01b0316146112d5576112d06001600160a01b03831684836118fa565b61130d565b6040516001600160a01b0384169082156108fc029083906000818181858888f1935050505015801561130b573d6000803e3d6000fd5b505b505050565b811561137b57611320611950565b6001600160a01b03166361e3c94483836040518363ffffffff1660e01b815260040161134d929190612238565b600060405180830381600087803b15801561136757600080fd5b505af11580156105c1573d6000803e3d6000fd5b5050565b846001600160a01b03167f718f2debe25ea9b628399a4db9e7a36b83b97b62308695be0df1b3f257582c92858585856040516113be9493929190612281565b60405180910390a26040517f718f2debe25ea9b628399a4db9e7a36b83b97b62308695be0df1b3f257582c92906060906106c9908890889088908890889060200161201f565b6000821561149657611414611950565b6001600160a01b031663a9c70eaa846040518263ffffffff1660e01b815260040161143f919061222f565b602060405180830381600087803b15801561145957600080fd5b505af115801561146d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114919190611e94565b611498565b815b9392505050565b836001600160a01b03167f019cbd45a253e15f12114d2ec3b4ff4029bbb4d9d484c003b11a06c358b5923c8484846040516114dc9392919061226b565b60405180910390a26040517f019cbd45a253e15f12114d2ec3b4ff4029bbb4d9d484c003b11a06c358b5923c90606090611520908790879087908790602001611ff9565b604051602081830303815290604052905060008061153c611107565b915091506115486116ae565b6001600160a01b031663e14d4fb1838387876040518563ffffffff1660e01b8152600401610bf79493929190612246565b6000806115846117b7565b6001600160a01b031663ddca3f436040518163ffffffff1660e01b815260040160206040518083038186803b1580156115bc57600080fd5b505afa1580156115d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f49190611e94565b9050600061160061110f565b6001600160a01b03166384a0e58f866040518263ffffffff1660e01b815260040161162b9190611fa3565b60206040518083038186803b15801561164357600080fd5b505afa158015611657573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061167b9190611e94565b90508161168a578392506116a6565b600061169682846117cf565b90506116a28582611804565b9350505b505092915050565b732af7ea6cb911035f3eb1ed895cb6692c39ecba9790565b6000806000806116d68686611127565b9094509050806116ed57600092506000915061170e565b6116ff816702c68af0bb1400006117cf565b915061170b81836118d7565b92505b509250925092565b826001600160a01b0316846001600160a01b03167f052e745f308c35fe80c9dae44eed9043ab6e2fbadf46f56fa11dba91992ab32a848460405161175b929190612238565b60405180910390a36040517f052e745f308c35fe80c9dae44eed9043ab6e2fbadf46f56fa11dba91992ab32a90606090611520908790879087908790602001611fb7565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee90565b73aaa91046c1d1a210017e36394c83bd5070dadda590565b6000670de0b6b3a76400006117f56117e78585611968565b6706f05b59d3b20000611804565b816117fc57fe5b049392505050565b808201828110156118275760405162461bcd60e51b81526004016105a090612135565b92915050565b600061183761179f565b6001600160a01b0316826001600160a01b0316146118d0576040516370a0823160e01b81526001600160a01b038316906370a082319061187b903090600401611fa3565b60206040518083038186803b15801561189357600080fd5b505afa1580156118a7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118cb9190611e94565b611827565b4792915050565b808203828111156118275760405162461bcd60e51b81526004016105a09061215c565b61130d8363a9059cbb60e01b8484604051602401611919929190611fe0565b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b03199093169290921790915261199f565b738a5419cfc711b2343c17a6abf4b2bafabb06957f90565b60008115806119835750508082028282828161198057fe5b04145b6118275760405162461bcd60e51b81526004016105a090612135565b60606119f4826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c6564815250856001600160a01b0316611a2e9092919063ffffffff16565b80519091501561130d5780806020019051810190611a129190611e74565b61130d5760405162461bcd60e51b81526004016105a0906121e5565b6060611a3d8484600085611a45565b949350505050565b6060611a5085611b09565b611a6c5760405162461bcd60e51b81526004016105a090612182565b60006060866001600160a01b03168587604051611a899190611f87565b60006040518083038185875af1925050503d8060008114611ac6576040519150601f19603f3d011682016040523d82523d6000602084013e611acb565b606091505b50915091508115611adf579150611a3d9050565b805115611aef5780518082602001fd5b8360405162461bcd60e51b81526004016105a091906120d2565b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470818114801590611a3d575050151592915050565b60008083601f840112611b53578182fd5b50813567ffffffffffffffff811115611b6a578182fd5b6020830191508360208083028501011115611b8457600080fd5b9250929050565b600060208284031215611b9c578081fd5b8135611498816122c8565b600060208284031215611bb8578081fd5b8151611498816122c8565b60008060008060808587031215611bd8578283fd5b8435611be3816122c8565b93506020850135611bf3816122c8565b93969395505050506040820135916060013590565b60008060008060008060006080888a031215611c22578283fd5b8735611c2d816122c8565b9650602088013567ffffffffffffffff80821115611c49578485fd5b611c558b838c01611b42565b909850965060408a0135915080821115611c6d578485fd5b611c798b838c01611b42565b909650945060608a0135915080821115611c91578384fd5b50611c9e8a828b01611b42565b989b979a50959850939692959293505050565b600080600060608486031215611cc5578283fd5b8335611cd0816122c8565b95602085013595506040909401359392505050565b60008060008060808587031215611cfa578384fd5b8435611d05816122c8565b966020860135965060408601359560600135945092505050565b60008060008060008060608789031215611d37578182fd5b863567ffffffffffffffff80821115611d4e578384fd5b611d5a8a838b01611b42565b90985096506020890135915080821115611d72578384fd5b611d7e8a838b01611b42565b90965094506040890135915080821115611d96578384fd5b50611da389828a01611b42565b979a9699509497509295939492505050565b6000806000806000806000806080898b031215611dd0578081fd5b883567ffffffffffffffff80821115611de7578283fd5b611df38c838d01611b42565b909a50985060208b0135915080821115611e0b578283fd5b611e178c838d01611b42565b909850965060408b0135915080821115611e2f578283fd5b611e3b8c838d01611b42565b909650945060608b0135915080821115611e53578283fd5b50611e608b828c01611b42565b999c989b5096995094979396929594505050565b600060208284031215611e85578081fd5b81518015158114611498578182fd5b600060208284031215611ea5578081fd5b5051919050565b60008284526020808501945082825b85811015611ee9578135611ece816122c8565b6001600160a01b031687529582019590820190600101611ebb565b509495945050505050565b6000815180845260208085019450808401835b83811015611ee95781516001600160a01b031687529582019590820190600101611f07565b6000815180845260208085019450808401835b83811015611ee957815187529582019590820190600101611f3f565b60008151808452611f7381602086016020860161229c565b601f01601f19169290920160200192915050565b60008251611f9981846020870161229c565b9190910192915050565b6001600160a01b0391909116815260200190565b6001600160a01b0394851681529290931660208301526040820152606081019190915260800190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b0394909416845260208401929092526040830152606082015260800190565b6001600160a01b03959095168552602085019390935260408401919091526060830152608082015260a00190565b600060208252611a3d602083018486611eac565b600060408252612075604083018587611eac565b82810360208401526120878185611f2c565b9695505050505050565b6000602082526114986020830184611ef4565b6000604082526120b76040830185611ef4565b82810360208401526120c98185611f2c565b95945050505050565b6000602082526114986020830184611f5b565b6020808252601490820152736f726967696e2d69732d6164647265737328302960601b604082015260600190565b6020808252600890820152670616d742d69732d360c41b604082015260600190565b6020808252600d908201526c6d6174682d6e6f742d7361666560981b604082015260600190565b6020808252600c908201526b7375622d6f766572666c6f7760a01b604082015260600190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b6020808252601290820152714e6f742d656e6f7567682d62616c616e636560701b604082015260600190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e6040820152691bdd081cdd58d8d9595960b21b606082015260800190565b90815260200190565b918252602082015260400190565b6000858252846020830152836040830152608060608301526120876080830184611f5b565b9283526020830191909152604082015260600190565b93845260208401929092526040830152606082015260800190565b60005b838110156122b757818101518382015260200161229f565b8381111561130b5750506000910152565b6001600160a01b03811681146122dd57600080fd5b5056fea26469706673582212204d21e76bf7967029aa6dbf62c4fc819e2d51c9eddb5a59c01da679cdcda2ac8f64736f6c634300060c0033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/pre-compiles/DssCdpManager.json b/pre-compiles/DssCdpManager.json new file mode 100644 index 0000000..c49c2b1 --- /dev/null +++ b/pre-compiles/DssCdpManager.json @@ -0,0 +1,257 @@ +{ + "contractName": "DssCdpManager", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "cdpCan", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "count", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "flux", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + }, + { + "internalType": "int256", + "name": "", + "type": "int256" + } + ], + "name": "frob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "give", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "ilks", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "last", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + }, + { + "internalType": "address", + "name": "", + "type": "address" + }, + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "move", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "open", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "owns", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "urns", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "vat", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/pre-compiles/GetCdps.json b/pre-compiles/GetCdps.json new file mode 100644 index 0000000..cd27ba2 --- /dev/null +++ b/pre-compiles/GetCdps.json @@ -0,0 +1,77 @@ +{ + "contractName": "GetCdps", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "internalType": "address", + "name": "guy", + "type": "address" + } + ], + "name": "getCdpsAsc", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "urns", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "ilks", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "manager", + "type": "address" + }, + { + "internalType": "address", + "name": "guy", + "type": "address" + } + ], + "name": "getCdpsDesc", + "outputs": [ + { + "internalType": "uint256[]", + "name": "ids", + "type": "uint256[]" + }, + { + "internalType": "address[]", + "name": "urns", + "type": "address[]" + }, + { + "internalType": "bytes32[]", + "name": "ilks", + "type": "bytes32[]" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x", + "deployedBytecode": "0x", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/test/2_Debt-Bridge-External-Provider.test.js b/test/2_Debt-Bridge-External-Provider.test.js new file mode 100644 index 0000000..6cc18a3 --- /dev/null +++ b/test/2_Debt-Bridge-External-Provider.test.js @@ -0,0 +1,775 @@ +const {expect} = require("chai"); +const bre = require("@nomiclabs/buidler"); +const {constants} = require("ethers"); +const {ethers} = bre; +const GelatoCoreLib = require("@gelatonetwork/core"); + +// #region Contracts ABI + +const InstaIndex = require("../pre-compiles/InstaIndex.json"); +const InstaList = require("../pre-compiles/InstaList.json"); +const InstaAccount = require("../pre-compiles/InstaAccount.json"); +const ConnectGelato = require("../pre-compiles/ConnectGelato.json"); +const ConnectMaker = require("../pre-compiles/ConnectMaker.json"); +const ConnectCompound = require("../pre-compiles/ConnectCompound.json"); +const ConnectInstaPool = require("../pre-compiles/ConnectInstaPool.json"); +const ConnectAuth = require("../pre-compiles/ConnectAuth.json"); +const ConnectGelatoDebtBridgeABI = require("../artifacts/ConnectGelatoDebtBridge.json"); +const ConnectGelatoProviderPaymentABI = require("../artifacts/ConnectGelatoProviderPayment.json"); +const InstaConnector = require("../pre-compiles/InstaConnectors.json"); +const DssCdpManager = require("../pre-compiles/DssCdpManager.json"); +const GetCdps = require("../pre-compiles/GetCdps.json"); +const IERC20 = require("../pre-compiles/IERC20.json"); +const CTokenInterface = require("../pre-compiles/CTokenInterface.json"); + +const ETH = "0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE"; +const GAS_LIMIT = "4000000"; +const GAS_PRICE_CEIL = ethers.utils.parseUnits("1000", "gwei"); + +// #endregion + +describe("Debt Bridge with External Provider", function () { + this.timeout(0); + if (bre.network.name !== "ganache") { + console.error("Test Suite is meant to be run on ganache only"); + process.exit(1); + } + + // Wallet to use for local testing + let userWallet; + let userAddress; + let providerWallet; + let providerAddress; + + // Deployed instances + let connectGelato; + let connectMaker; + let connectInstaPool; + let connectCompound; + let instaIndex; + let instaList; + let dssCdpManager; + let getCdps; + let daiToken; + let gelatoCore; + let cDaiToken; + let instaMaster; + let instaConnectors; + + // Contracts to deploy and use for local testing + let conditionMakerVaultIsSafe; + let connectGelatoDebtBridge; + let connectGelatoProviderPayment; + let oracleAggregator; + let dsaProviderModule; + + // Creation during test + let dsa; + let connectedGelatoCore; + + before(async function () { + // Get Test Wallet for local testnet + [userWallet] = await ethers.getSigners(); + userAddress = await userWallet.getAddress(); + + [, providerWallet] = await ethers.getSigners(); + providerAddress = await providerWallet.getAddress(); + + instaMaster = await ethers.provider.getSigner( + bre.network.config.InstaMaster + ); + + // Ganache default accounts prefilled with 100 ETH + expect(await userWallet.getBalance()).to.be.gt( + ethers.utils.parseEther("10") + ); + + // ===== Get Deployed Contract Instance ================== + instaIndex = await ethers.getContractAt( + InstaIndex.abi, + bre.network.config.InstaIndex + ); + instaList = await ethers.getContractAt( + InstaList.abi, + bre.network.config.InstaList + ); + connectGelato = await ethers.getContractAt( + ConnectGelato.abi, + bre.network.config.ConnectGelato + ); + connectMaker = await ethers.getContractAt( + ConnectMaker.abi, + bre.network.config.ConnectMaker + ); + connectInstaPool = await ethers.getContractAt( + ConnectInstaPool.abi, + bre.network.config.ConnectInstaPool + ); + connectCompound = await ethers.getContractAt( + ConnectCompound.abi, + bre.network.config.ConnectCompound + ); + dssCdpManager = await ethers.getContractAt( + DssCdpManager.abi, + bre.network.config.DssCdpManager + ); + getCdps = await ethers.getContractAt( + GetCdps.abi, + bre.network.config.GetCdps + ); + daiToken = await ethers.getContractAt(IERC20.abi, bre.network.config.DAI); + gelatoCore = await ethers.getContractAt( + GelatoCoreLib.GelatoCore.abi, + bre.network.config.GelatoCore + ); + cDaiToken = await ethers.getContractAt( + CTokenInterface.abi, + bre.network.config.CDAI + ); + instaConnectors = await ethers.getContractAt( + InstaConnector.abi, + bre.network.config.InstaConnectors + ); + // instaEvent = await ethers.getContractAt( + // InstaEvent.abi, + // bre.network.config.InstaEvent + // ) + + // ===== Deploy Needed Contract ================== + + const OracleAggregator = await ethers.getContractFactory( + "OracleAggregator" + ); + oracleAggregator = await OracleAggregator.deploy(); + await oracleAggregator.deployed(); + + const ConditionMakerVaultIsSafe = await ethers.getContractFactory( + "ConditionMakerVaultIsSafe" + ); + conditionMakerVaultIsSafe = await ConditionMakerVaultIsSafe.deploy( + oracleAggregator.address + ); + await conditionMakerVaultIsSafe.deployed(); + + const connectorLength = await instaConnectors.connectorLength(); + const connectorId = connectorLength.add(1); + + const ConnectGelatoDebtBridge = await ethers.getContractFactory( + "ConnectGelatoDebtBridge" + ); + connectGelatoDebtBridge = await ConnectGelatoDebtBridge.deploy( + connectorId, + oracleAggregator.address + ); + await connectGelatoDebtBridge.deployed(); + + const ConnectGelatoProviderPayment = await ethers.getContractFactory( + "ConnectGelatoProviderPayment" + ); + connectGelatoProviderPayment = await ConnectGelatoProviderPayment.deploy( + connectorId.add(1) + ); + await connectGelatoProviderPayment.deployed(); + + const ProviderModuleDSA = await ethers.getContractFactory( + "ProviderModuleDSA" + ); + dsaProviderModule = await ProviderModuleDSA.deploy( + bre.network.config.InstaIndex, + bre.network.config.GelatoCore, + connectGelatoProviderPayment.address + ); + await dsaProviderModule.deployed(); + + /////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////// After Contracts Deployement : Setup /////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////// + /////////////////////////////////////////////////////////////////////////////////////////////////// + + // Gelato Testing environment setup. + // Step 1 : Add EUR/USD Maker Medianizer in the Oracle Aggregator + // Step 2 : Enable Debt Bridge Connector and Gelato Provider Payment Connector + // Step 3 : Executor Staking on Gelato + // Step 4 : Provider put some fund on gelato for paying future tasks executions + // Step 5 : Provider choose a executor + // Step 6 : Provider will add a module + // Step 7 : Provider should whitelist task + + //#region Step 1 Add EUR/USD Maker Medianizer in the Oracle Aggregator + + // Oracle Aggregator is a price feeder aggregator + // You will be able to query price from multiple source through this aggregator + // For the demo we add the ETH/USD Medianizer to the aggregator + // MakerDAO price oracle are called Medianizer + + await oracleAggregator.addOracle( + "ETH/USD", + "0x729D19f657BD0614b4985Cf1D82531c67569197B" + ); + + //#endregion + + //#region Step 2 Enable Debt Bridge Connector and Gelato Provider Payment Connector + + // Debt Bridge Connector is used during refinancing of debt + // This Connect help the user to split a position in one protocol. + // to 2 protocol in a safe way. Both debt position will be safe. + + // Gelato Provider Payment Connector is used for paying the provider + // for task execution. So when futur task will be executed, through a self financing + // transaction (user will pay during the execution of the task) task will + // be executed. Improvind user experience. + + await userWallet.sendTransaction({ + to: bre.network.config.InstaMaster, + value: ethers.utils.parseEther("0.1"), + }); + await instaConnectors + .connect(instaMaster) + .enable(connectGelatoDebtBridge.address); + await instaConnectors + .connect(instaMaster) + .enable(connectGelatoProviderPayment.address); + + expect( + await instaConnectors.isConnector([connectGelatoDebtBridge.address]) + ).to.be.true; + expect( + await instaConnectors.isConnector([connectGelatoProviderPayment.address]) + ).to.be.true; + + //#endregion + + //#region Step 3 Executor Staking on Gelato + + // For task execution provider will ask a executor to watch the + // blockchain for possible execution autorization given by + // the condition that user choose when submitting the task. + // And if all condition are meet executor will execute the task. + // For safety measure Gelato ask the executor to stake a minimum + // amount. + + connectedGelatoCore = gelatoCore.connect(providerWallet); + gelatoCore = gelatoCore.connect(userWallet); + await connectedGelatoCore.stakeExecutor({ + from: providerAddress, + value: await connectedGelatoCore.minExecutorStake(), + }); + + expect( + await connectedGelatoCore.isExecutorMinStaked(providerAddress) + ).to.be.true; + + //#endregion + + //#region Step 4 Provider put some fund on gelato for paying future tasks executions + + // Provider put some funds in gelato system for paying the + // Executor when this one will execute task on behalf of the + // Provider. At each provider's task execution, some funds (approximatively + // the gas cost value) will be transfered to the Executor stake. + + const TASK_AUTOMATION_FUNDS = await gelatoCore.minExecProviderFunds( + GAS_LIMIT, + GAS_PRICE_CEIL + ); + + await expect( + connectedGelatoCore.provideFunds(providerAddress, { + value: TASK_AUTOMATION_FUNDS, + }) + ).to.emit(gelatoCore, "LogFundsProvided"); + + expect( + await connectedGelatoCore.providerFunds(providerAddress) + ).to.be.equal(TASK_AUTOMATION_FUNDS); + + //#endregion + + //#region Step 5 Provider choose a executor + + // Provider choose a executor who will execute futur task + // for the provider, it will be compensated by the provider. + + await expect( + connectedGelatoCore.providerAssignsExecutor(providerAddress) + ).to.emit(gelatoCore, "LogProviderAssignedExecutor"); + + expect( + await connectedGelatoCore.executorByProvider(providerAddress) + ).to.be.equal(providerAddress); + + //#endregion + + //#region Step 6 Provider will add a module + + // By adding a module the provider will format future task's + // payload by adding some specificity like his address to the + // Payment connector for receiving payment of User. + + await expect( + connectedGelatoCore.addProviderModules([dsaProviderModule.address]) + ).to.emit(gelatoCore, "LogProviderModuleAdded"); + + expect( + await connectedGelatoCore.isModuleProvided( + providerAddress, + dsaProviderModule.address + ) + ).to.be.true; + + //#endregion + + //#region Step 7 Provider should whitelist task + + // By WhiteList task, the provider can constrain the type + // of task the user can submitting. + + //#region Actions + + const spells = []; + + let debtBridge = new GelatoCoreLib.Action({ + addr: connectGelatoDebtBridge.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(debtBridge); + + let flashBorrow = new GelatoCoreLib.Action({ + addr: connectInstaPool.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(flashBorrow); + + let paybackMaker = new GelatoCoreLib.Action({ + addr: connectMaker.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(paybackMaker); + + let withdrawMaker = new GelatoCoreLib.Action({ + addr: connectMaker.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(withdrawMaker); + + let depositCompound = new GelatoCoreLib.Action({ + addr: connectCompound.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(depositCompound); + + let borrowCompound = new GelatoCoreLib.Action({ + addr: connectCompound.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(borrowCompound); + + let flashPayBack = new GelatoCoreLib.Action({ + addr: connectInstaPool.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(flashPayBack); + + let payProvider = new GelatoCoreLib.Action({ + addr: connectGelatoProviderPayment.address, + data: constants.HashZero, + operation: GelatoCoreLib.Operation.Delegatecall, + dataFlow: GelatoCoreLib.DataFlow.None, + termsOkCheck: false, + value: 0, + }); + + spells.push(payProvider); + + const gasPriceCeil = constants.MaxUint256; + + const gelatoFlashLoanTaskSpec = new GelatoCoreLib.TaskSpec({ + conditions: [conditionMakerVaultIsSafe.address], + actions: spells, + gasPriceCeil, + }); + + await expect( + connectedGelatoCore.provideTaskSpecs([gelatoFlashLoanTaskSpec]) + ).to.emit(gelatoCore, "LogTaskSpecProvided"); + + expect( + await connectedGelatoCore.isTaskSpecProvided( + providerAddress, + gelatoFlashLoanTaskSpec + ) + ).to.be.equal("OK"); + + expect( + await connectedGelatoCore.taskSpecGasPriceCeil( + providerAddress, + await connectedGelatoCore.hashTaskSpec(gelatoFlashLoanTaskSpec) + ) + ).to.be.equal(gasPriceCeil); + + //#endregion + + //#endregion + }); + + it("Use Maker Compound refinancing if the maker vault become unsafe after a market move.", async function () { + // User Actions + // Step 1 : User create a DeFi Smart Account + // Step 2 : User open a Vault, put some ether on it and borrow some dai + // Step 3 : User give authorization to gelato to use his DSA on his behalf. + // Step 4 : User submit a Debt Refinancing task if market move against him + // Step 5 : Market Move against the user (Mock) + // Step 6 : Executor execute the user's task + + //#region Step 1 User create a DeFi Smart Account + + // User create a Instadapp DeFi Smart Account + // who give him the possibility to interact + // with a large list of DeFi protocol through one + // Proxy account. + + const dsaAccountCount = await instaList.accounts(); + + await expect(instaIndex.build(userAddress, 1, userAddress)).to.emit( + instaIndex, + "LogAccountCreated" + ); + const dsaID = dsaAccountCount.add(1); + await expect(await instaList.accounts()).to.be.equal(dsaID); + + // Instantiate the DSA + dsa = await ethers.getContractAt( + InstaAccount.abi, + await instaList.accountAddr(dsaID) + ); + + //#endregion + + //#region Step 2 User open a Vault, put some ether on it and borrow some dai + + // User open a maker vault + // He deposit 10 Eth on it + // He borrow a 1000 DAI + + const openVault = await bre.run("abi-encode-withselector", { + abi: ConnectMaker.abi, + functionname: "open", + inputs: ["ETH-A"], + }); + + await dsa.cast([bre.network.config.ConnectMaker], [openVault], userAddress); + + let cdps = await getCdps.getCdpsAsc(dssCdpManager.address, dsa.address); + let cdpId = String(cdps.ids[0]); + + expect(cdps.ids[0].isZero()).to.be.false; + + await dsa.cast( + [bre.network.config.ConnectMaker], + [ + await bre.run("abi-encode-withselector", { + abi: ConnectMaker.abi, + functionname: "deposit", + inputs: [cdpId, ethers.utils.parseEther("10"), 0, 0], + }), + ], + userAddress, + { + value: ethers.utils.parseEther("10"), + } + ); + + await dsa.cast( + [bre.network.config.ConnectMaker], + [ + await bre.run("abi-encode-withselector", { + abi: ConnectMaker.abi, + functionname: "borrow", + inputs: [cdpId, ethers.utils.parseUnits("1000", 18), 0, 0], + }), + ], + userAddress + ); + + expect(await daiToken.balanceOf(dsa.address)).to.be.equal( + ethers.utils.parseEther("1000") + ); + + //#endregion + + //#region Step 3 User give authorization to gelato to use his DSA on his behalf. + + // Instadapp DSA contract give the possibility to the user to delegate + // action by giving authorization. + // In this case user give authorization to gelato to execute + // task for him if needed. + + await dsa.cast( + [bre.network.config.ConnectAuth], + [ + await bre.run("abi-encode-withselector", { + abi: ConnectAuth.abi, + functionname: "add", + inputs: [gelatoCore.address], + }), + ], + userAddress + ); + + expect(await dsa.isAuth(gelatoCore.address)).to.be.true; + + //#endregion + + //#region Step 4 User submit a Debt Refinancing task if market move against him + + // User submit the refinancing task if market move against him. + // So in this case if the maker vault go to the unsafe area + // the refinancing task will be executed and the position + // will be split on two position on maker and compound. + // It will be done through a algorithm that will optimize the + // total borrow rate. + + const debtBridgeCondition = new GelatoCoreLib.Condition({ + inst: conditionMakerVaultIsSafe.address, + data: await conditionMakerVaultIsSafe.getConditionData( + cdpId, + "ETH/USD", + ethers.utils.parseUnits("3", 18) + ), + }); + + // ======= Action/Spells setup ====== + const spells = []; + + let debtBridgeCalculation = new GelatoCoreLib.Action({ + addr: connectGelatoDebtBridge.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectGelatoDebtBridgeABI.abi, + functionname: "debtBridgeMakerToCompound", + inputs: [ + cdpId, + ethers.utils.parseUnits("3", 18), + ethers.utils.parseUnits("18", 17), + "ETH/USD", + 0, + 0, + ], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(debtBridgeCalculation); + + let flashBorrow = new GelatoCoreLib.Action({ + addr: connectInstaPool.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectInstaPool.abi, + functionname: "flashBorrow", + inputs: [bre.network.config.DAI, 0, "100", 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(flashBorrow); + + let paybackMaker = new GelatoCoreLib.Action({ + addr: connectMaker.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectMaker.abi, + functionname: "payback", + inputs: [cdpId, 0, "101", 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(paybackMaker); + + let withdrawMaker = new GelatoCoreLib.Action({ + addr: connectMaker.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectMaker.abi, + functionname: "withdraw", + inputs: [cdpId, 0, "102", 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(withdrawMaker); + + let depositCompound = new GelatoCoreLib.Action({ + addr: connectCompound.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectCompound.abi, + functionname: "deposit", + inputs: [ETH, 0, "103", 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(depositCompound); + + let borrowCompound = new GelatoCoreLib.Action({ + addr: connectCompound.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectCompound.abi, + functionname: "borrow", + inputs: [bre.network.config.DAI, 0, "104", 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(borrowCompound); + + let flashPayBack = new GelatoCoreLib.Action({ + addr: connectInstaPool.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectInstaPool.abi, + functionname: "flashPayback", + inputs: [bre.network.config.DAI, 0, 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(flashPayBack); + + let payProvider = new GelatoCoreLib.Action({ + addr: connectGelatoProviderPayment.address, + data: await bre.run("abi-encode-withselector", { + abi: ConnectGelatoProviderPaymentABI.abi, + functionname: "payProvider", + inputs: [ethers.constants.AddressZero, ETH, 0, "105", 0], + }), + operation: GelatoCoreLib.Operation.Delegatecall, + }); + + spells.push(payProvider); + + const refinanceIfCompoundBorrowIsBetter = new GelatoCoreLib.Task({ + conditions: [debtBridgeCondition], + actions: spells, + }); + + const gelatoExternalProvider = new GelatoCoreLib.GelatoProvider({ + addr: providerAddress, + module: dsaProviderModule.address, + }); + + const expiryDate = 0; + await expect( + dsa.cast( + [connectGelato.address], // targets + [ + await bre.run("abi-encode-withselector", { + abi: ConnectGelato.abi, + functionname: "submitTask", + inputs: [ + gelatoExternalProvider, + refinanceIfCompoundBorrowIsBetter, + expiryDate, + ], + }), + ], // datas + userAddress, // origin + { + gasLimit: 5000000, + } + ) + ).to.emit(gelatoCore, "LogTaskSubmitted"); + + const taskReceipt = new GelatoCoreLib.TaskReceipt({ + id: await gelatoCore.currentTaskReceiptId(), + userProxy: dsa.address, + provider: gelatoExternalProvider, + tasks: [refinanceIfCompoundBorrowIsBetter], + expiryDate, + }); + + //#endregion + + //#region Step 5 Market Move against the user (Mock) + + // Ether market price went from the current price to 250$ + + const gelatoGasPrice = await bre.run("fetchGelatoGasPrice"); + expect(gelatoGasPrice).to.be.lte(GAS_PRICE_CEIL); + + expect( + await connectedGelatoCore.canExec(taskReceipt, GAS_LIMIT, gelatoGasPrice) + ).to.be.equal("ConditionNotOk:NotOKMakerVaultIsSafe"); + + await oracleAggregator.mock(true, ethers.utils.parseUnits("250", 18)); + + expect( + await connectedGelatoCore.canExec(taskReceipt, GAS_LIMIT, gelatoGasPrice) + ).to.be.equal("OK"); + + //#endregion + + //#region Step 6 Executor execute the user's task + + // The market move make the vault unsafe, so the executor + // will execute the user's task to make the user position safe + // by a debt refinancing in compound. + + let providerBalanceBeforeExecution = await providerWallet.getBalance(); + await expect( + connectedGelatoCore.exec(taskReceipt, { + gasPrice: gelatoGasPrice, // Exectutor must use gelatoGasPrice (Chainlink fast gwei) + gasLimit: GAS_LIMIT, + }) + ).to.emit(gelatoCore, "LogExecSuccess"); + + let providerBalanceAfterExecution = await providerWallet.getBalance(); + expect(providerBalanceAfterExecution).to.be.gt( + providerBalanceBeforeExecution + ); + const amtOfBorrowedDAIOnCompound = ( + await cDaiToken.getAccountSnapshot(dsa.address) + )[2]; + expect(amtOfBorrowedDAIOnCompound).to.be.lt( + ethers.utils.parseUnits("1000", 18) + ); // Check the borrow amount + expect(await daiToken.balanceOf(dsa.address)).to.be.equal( + ethers.utils.parseUnits("1000", 18) + ); + + //#endregion + }); +});