Gelato-automations/deployments/mainnet/solcInputs/d9397bda7e9d5c90e2ef9a83ef888759.json
2020-12-01 13:48:53 +01:00

280 lines
307 KiB
JSON

{
"language": "Solidity",
"sources": {
"contracts/dapp_interfaces/gnosis/IBatchExchange.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nstruct Order {\n uint16 buyToken;\n uint16 sellToken;\n uint32 validFrom; // order is valid from auction collection period: validFrom inclusive\n uint32 validUntil; // order is valid till auction collection period: validUntil inclusive\n uint128 priceNumerator;\n uint128 priceDenominator;\n uint128 usedAmount; // remainingAmount = priceDenominator - usedAmount\n}\n\ninterface IBatchExchange {\n\n function withdraw(address user, address token)\n external;\n\n function deposit(address token, uint256 amount)\n external;\n\n function getPendingWithdraw(address user, address token)\n external\n view\n returns (uint256, uint32);\n\n function getCurrentBatchId()\n external\n view\n returns (uint32);\n\n function hasValidWithdrawRequest(address user, address token)\n external\n view\n returns (bool);\n\n function tokenAddressToIdMap(address addr)\n external\n view\n returns (uint16);\n\n function orders(address userAddress)\n external\n view\n returns (Order[] memory);\n\n\n // Returns orderId\n function placeOrder(uint16 buyToken, uint16 sellToken, uint32 validUntil, uint128 buyAmount, uint128 sellAmount)\n external\n returns (uint256);\n\n function requestFutureWithdraw(address token, uint256 amount, uint32 batchId)\n external;\n\n function requestWithdraw(address token, uint256 amount)\n external;\n\n}\n"
},
"contracts/gelato_conditions/gnosis/ConditionBatchExchangeWithdrawStateful.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"../GelatoStatefulConditionsStandard.sol\";\nimport \"../../dapp_interfaces/gnosis/IBatchExchange.sol\";\nimport {IGelatoCore} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract ConditionBatchExchangeWithdrawStateful is GelatoStatefulConditionsStandard {\n\n\n constructor(IGelatoCore _gelatoCore) GelatoStatefulConditionsStandard(_gelatoCore)\n public\n {}\n\n // userProxy => taskReceiptId => refBatchId\n mapping(address => mapping(uint256 => uint256)) public refBatchId;\n\n uint32 public constant BATCH_TIME = 300;\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(address _userProxy)\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(this.checkRefBatchId.selector, uint256(0), _userProxy);\n }\n\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256 _taskReceiptId, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n address userProxy = abi.decode(_conditionData[36:], (address));\n return checkRefBatchId(_taskReceiptId, userProxy);\n }\n\n // Specific Implementation\n /// @dev Abi encode these parameter inputs. Use a placeholder for _taskReceiptId.\n /// @param _taskReceiptId Will be stripped from encoded data and replaced by\n /// the value passed in from GelatoCore.\n function checkRefBatchId(uint256 _taskReceiptId, address _userProxy)\n public\n view\n virtual\n returns(string memory)\n {\n uint256 _refBatchId = refBatchId[_userProxy][_taskReceiptId];\n uint256 currentBatchId = uint32(block.timestamp / BATCH_TIME);\n if (_refBatchId < currentBatchId) return OK;\n return \"NotOkBatchIdDidNotPass\";\n }\n\n /// @dev This function should be called via the userProxy of a Gelato Task as part\n /// of the Task.actions, if the Condition state should be updated after the task.\n /// This is for Task Cycles/Chains and we fetch the TaskReceipt.id of the\n // next Task that will be auto-submitted by GelatoCore in the same exec Task transaction.\n function setRefBatchId(uint256 _delta, uint256 _idDelta) external {\n uint256 currentBatchId = uint32(block.timestamp / BATCH_TIME);\n uint256 newRefBatchId = currentBatchId + _delta;\n refBatchId[msg.sender][_getIdOfNextTaskInCycle() + _idDelta] = newRefBatchId;\n }\n}"
},
"contracts/gelato_conditions/GelatoStatefulConditionsStandard.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"./GelatoConditionsStandard.sol\";\nimport {IGelatoCore} from \"../gelato_core/interfaces/IGelatoCore.sol\";\n\nabstract contract GelatoStatefulConditionsStandard is GelatoConditionsStandard {\n IGelatoCore public immutable gelatoCore;\n\n constructor(IGelatoCore _gelatoCore) public { gelatoCore = _gelatoCore; }\n\n function _getIdOfNextTaskInCycle() internal view returns(uint256 nextTaskReceiptId) {\n try gelatoCore.currentTaskReceiptId() returns(uint256 currentId) {\n nextTaskReceiptId = currentId + 1;\n } catch Error(string memory _err) {\n revert(\n string(abi.encodePacked(\n \"GelatoStatefulConditionsStandard._getIdOfNextTaskInCycle\", _err\n ))\n );\n } catch {\n revert(\"GelatoStatefulConditionsStandard._getIdOfNextTaskInCycle:undefined\");\n }\n }\n}\n"
},
"contracts/gelato_core/interfaces/IGelatoCore.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoProviderModule} from \"../../gelato_provider_modules/IGelatoProviderModule.sol\";\nimport {IGelatoCondition} from \"../../gelato_conditions/IGelatoCondition.sol\";\n\nstruct Provider {\n address addr; // if msg.sender == provider => self-Provider\n IGelatoProviderModule module; // can be IGelatoProviderModule(0) for self-Providers\n}\n\nstruct Condition {\n IGelatoCondition inst; // can be AddressZero for self-conditional Actions\n bytes data; // can be bytes32(0) for self-conditional Actions\n}\n\nenum Operation { Call, Delegatecall }\n\nenum DataFlow { None, In, Out, InAndOut }\n\nstruct Action {\n address addr;\n bytes data;\n Operation operation;\n DataFlow dataFlow;\n uint256 value;\n bool termsOkCheck;\n}\n\nstruct Task {\n Condition[] conditions; // optional\n Action[] actions;\n uint256 selfProviderGasLimit; // optional: 0 defaults to gelatoMaxGas\n uint256 selfProviderGasPriceCeil; // optional: 0 defaults to NO_CEIL\n}\n\nstruct TaskReceipt {\n uint256 id;\n address userProxy;\n Provider provider;\n uint256 index;\n Task[] tasks;\n uint256 expiryDate;\n uint256 cycleId; // auto-filled by GelatoCore. 0 for non-cyclic/chained tasks\n uint256 submissionsLeft;\n}\n\ninterface IGelatoCore {\n event LogTaskSubmitted(\n uint256 indexed taskReceiptId,\n bytes32 indexed taskReceiptHash,\n TaskReceipt taskReceipt\n );\n\n event LogExecSuccess(\n address indexed executor,\n uint256 indexed taskReceiptId,\n uint256 executorSuccessFee,\n uint256 sysAdminSuccessFee\n );\n event LogCanExecFailed(\n address indexed executor,\n uint256 indexed taskReceiptId,\n string reason\n );\n event LogExecReverted(\n address indexed executor,\n uint256 indexed taskReceiptId,\n uint256 executorRefund,\n string reason\n );\n\n event LogTaskCancelled(uint256 indexed taskReceiptId, address indexed cancellor);\n\n /// @notice API to query whether Task can be submitted successfully.\n /// @dev In submitTask the msg.sender must be the same as _userProxy here.\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _userProxy The userProxy from which the task will be submitted.\n /// @param _task Selected provider, conditions, actions, expiry date of the task\n function canSubmitTask(\n address _userProxy,\n Provider calldata _provider,\n Task calldata _task,\n uint256 _expiryDate\n )\n external\n view\n returns(string memory);\n\n /// @notice API to submit a single Task.\n /// @dev You can let users submit multiple tasks at once by batching calls to this.\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _task A Gelato Task object: provider, conditions, actions.\n /// @param _expiryDate From then on the task cannot be executed. 0 for infinity.\n function submitTask(\n Provider calldata _provider,\n Task calldata _task,\n uint256 _expiryDate\n )\n external;\n\n\n /// @notice A Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed.\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _cycles How many full cycles will be submitted\n function submitTaskCycle(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external;\n\n\n /// @notice A Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed.\n /// @dev CAUTION: _sumOfRequestedTaskSubmits does not mean the number of cycles.\n /// @dev If _sumOfRequestedTaskSubmits = 1 && _tasks.length = 2, only the first task\n /// would be submitted, but not the second\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _sumOfRequestedTaskSubmits The TOTAL number of Task auto-submits\n /// that should have occured once the cycle is complete:\n /// _sumOfRequestedTaskSubmits = 0 => One Task will resubmit the next Task infinitly\n /// _sumOfRequestedTaskSubmits = 1 => One Task will resubmit no other task\n /// _sumOfRequestedTaskSubmits = 2 => One Task will resubmit 1 other task\n /// ...\n function submitTaskChain(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n external;\n\n // ================ Exec Suite =========================\n /// @notice Off-chain API for executors to check, if a TaskReceipt is executable\n /// @dev GelatoCore checks this during execution, in order to safeguard the Conditions\n /// @param _TR TaskReceipt, consisting of user task, user proxy address and id\n /// @param _gasLimit Task.selfProviderGasLimit is used for SelfProviders. All other\n /// Providers must use gelatoMaxGas. If the _gasLimit is used by an Executor and the\n /// tx reverts, a refund is paid by the Provider and the TaskReceipt is annulated.\n /// @param _execTxGasPrice Must be used by Executors. Gas Price fed by gelatoCore's\n /// Gas Price Oracle. Executors can query the current gelatoGasPrice from events.\n function canExec(TaskReceipt calldata _TR, uint256 _gasLimit, uint256 _execTxGasPrice)\n external\n view\n returns(string memory);\n\n /// @notice Executors call this when Conditions allow it to execute submitted Tasks.\n /// @dev Executors get rewarded for successful Execution. The Task remains open until\n /// successfully executed, or when the execution failed, despite of gelatoMaxGas usage.\n /// In the latter case Executors are refunded by the Task Provider.\n /// @param _TR TaskReceipt: id, userProxy, Task.\n function exec(TaskReceipt calldata _TR) external;\n\n /// @notice Cancel task\n /// @dev Callable only by userProxy or selected provider\n /// @param _TR TaskReceipt: id, userProxy, Task.\n function cancelTask(TaskReceipt calldata _TR) external;\n\n /// @notice Cancel multiple tasks at once\n /// @dev Callable only by userProxy or selected provider\n /// @param _taskReceipts TaskReceipts: id, userProxy, Task.\n function multiCancelTasks(TaskReceipt[] calldata _taskReceipts) external;\n\n /// @notice Compute hash of task receipt\n /// @param _TR TaskReceipt, consisting of user task, user proxy address and id\n /// @return hash of taskReceipt\n function hashTaskReceipt(TaskReceipt calldata _TR) external pure returns(bytes32);\n\n // ================ Getters =========================\n /// @notice Returns the taskReceiptId of the last TaskReceipt submitted\n /// @return currentId currentId, last TaskReceiptId submitted\n function currentTaskReceiptId() external view returns(uint256);\n\n /// @notice Returns computed taskReceipt hash, used to check for taskReceipt validity\n /// @param _taskReceiptId Id of taskReceipt emitted in submission event\n /// @return hash of taskReceipt\n function taskReceiptHash(uint256 _taskReceiptId) external view returns(bytes32);\n}\n"
},
"contracts/gelato_conditions/GelatoConditionsStandard.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"./IGelatoCondition.sol\";\n\nabstract contract GelatoConditionsStandard is IGelatoCondition {\n string internal constant OK = \"OK\";\n}\n"
},
"contracts/gelato_conditions/IGelatoCondition.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\n/// @title IGelatoCondition - solidity interface of GelatoConditionsStandard\n/// @notice all the APIs of GelatoConditionsStandard\n/// @dev all the APIs are implemented inside GelatoConditionsStandard\ninterface IGelatoCondition {\n\n /// @notice GelatoCore calls this to verify securely the specified Condition securely\n /// @dev Be careful only to encode a Task's condition.data as is and not with the\n /// \"ok\" selector or _taskReceiptId, since those two things are handled by GelatoCore.\n /// @param _taskReceiptId This is passed by GelatoCore so we can rely on it as a secure\n /// source of Task identification.\n /// @param _conditionData This is the Condition.data field developers must encode their\n /// Condition's specific parameters in.\n /// @param _cycleId For Tasks that are executed as part of a cycle.\n function ok(uint256 _taskReceiptId, bytes calldata _conditionData, uint256 _cycleId)\n external\n view\n returns(string memory);\n}"
},
"contracts/gelato_provider_modules/IGelatoProviderModule.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {Action, Task} from \"../gelato_core/interfaces/IGelatoCore.sol\";\n\ninterface IGelatoProviderModule {\n\n /// @notice Check if provider agrees to pay for inputted task receipt\n /// @dev Enables arbitrary checks by provider\n /// @param _userProxy The smart contract account of the user who submitted the Task.\n /// @param _provider The account of the Provider who uses the ProviderModule.\n /// @param _task Gelato Task to be executed.\n /// @return \"OK\" if provider agrees\n function isProvided(address _userProxy, address _provider, Task calldata _task)\n external\n view\n returns(string memory);\n\n /// @notice Convert action specific payload into proxy specific payload\n /// @dev Encoded multiple actions into a multisend\n /// @param _taskReceiptId Unique ID of Gelato Task to be executed.\n /// @param _userProxy The smart contract account of the user who submitted the Task.\n /// @param _provider The account of the Provider who uses the ProviderModule.\n /// @param _task Gelato Task to be executed.\n /// @param _cycleId For Tasks that form part of a cycle/chain.\n /// @return Encoded payload that will be used for low-level .call on user proxy\n /// @return checkReturndata if true, fwd returndata from userProxy.call to ProviderModule\n function execPayload(\n uint256 _taskReceiptId,\n address _userProxy,\n address _provider,\n Task calldata _task,\n uint256 _cycleId\n )\n external\n view\n returns(bytes memory, bool checkReturndata);\n\n /// @notice Called by GelatoCore.exec to verifiy that no revert happend on userProxy\n /// @dev If a caught revert is detected, this fn should revert with the detected error\n /// @param _proxyReturndata Data from GelatoCore._exec.userProxy.call(execPayload)\n function execRevertCheck(bytes calldata _proxyReturndata) external pure;\n}\n"
},
"contracts/user_proxies/gelato_user_proxy/GelatoUserProxyFactory.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoUserProxyFactory} from \"./interfaces/IGelatoUserProxyFactory.sol\";\nimport {Address} from \"../../external/Address.sol\";\nimport {GelatoUserProxy} from \"./GelatoUserProxy.sol\";\nimport {GelatoUserProxySet} from \"../../libraries/GelatoUserProxySet.sol\";\nimport {Action, Provider, Task} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract GelatoUserProxyFactory is IGelatoUserProxyFactory {\n\n using Address for address payable; /// for oz's sendValue method\n using GelatoUserProxySet for GelatoUserProxySet.Set;\n\n address public immutable override gelatoCore;\n\n mapping(GelatoUserProxy => address) public override userByGelatoProxy;\n mapping(address => GelatoUserProxySet.Set) private _gelatoProxiesByUser;\n\n constructor(address _gelatoCore) public { gelatoCore = _gelatoCore; }\n\n // ==================== CREATE =======================================\n function create() public payable override returns (GelatoUserProxy userProxy) {\n userProxy = new GelatoUserProxy{value: msg.value}(msg.sender, gelatoCore);\n _storeGelatoUserProxy(userProxy);\n }\n\n function createExecActions(Action[] calldata _actions)\n external\n payable\n override\n returns (GelatoUserProxy userProxy)\n {\n userProxy = create();\n if (_actions.length != 0) _execActions(userProxy, _actions);\n }\n\n function createSubmitTasks(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n override\n returns (GelatoUserProxy userProxy)\n {\n userProxy = create();\n if (_tasks.length != 0) _submitTasks(userProxy, _provider, _tasks, _expiryDates);\n }\n\n function createExecActionsSubmitTasks(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n override\n returns(GelatoUserProxy userProxy)\n {\n userProxy = create();\n if (_actions.length != 0) _execActions(userProxy, _actions);\n if (_tasks.length != 0) _submitTasks(userProxy, _provider, _tasks, _expiryDates);\n }\n\n function createExecActionsSubmitTaskCycle(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external\n payable\n override\n returns(GelatoUserProxy userProxy)\n {\n userProxy = create();\n if (_actions.length != 0) _execActions(userProxy, _actions);\n if (_tasks.length == 0)\n revert(\"GelatoUserProxyFactory.createExecActionsSubmitTaskCycle: 0 _tasks\");\n _submitTaskCycle(userProxy, _provider, _tasks, _expiryDate, _cycles);\n }\n\n function createExecActionsSubmitTaskChain(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n external\n payable\n override\n returns(GelatoUserProxy userProxy)\n {\n userProxy = create();\n if (_actions.length != 0) _execActions(userProxy, _actions);\n if (_tasks.length == 0)\n revert(\"GelatoUserProxyFactory.createExecActionsSubmitTaskChain: 0 _tasks\");\n _submitTaskChain(userProxy, _provider, _tasks, _expiryDate, _sumOfRequestedTaskSubmits);\n }\n\n // ==================== CREATE 2 =======================================\n function createTwo(uint256 _saltNonce)\n public\n payable\n override\n returns (GelatoUserProxy userProxy)\n {\n bytes32 salt = keccak256(abi.encode(msg.sender, _saltNonce));\n userProxy = new GelatoUserProxy{salt: salt, value: msg.value}(msg.sender, gelatoCore);\n require(\n address(userProxy) == predictProxyAddress(msg.sender, _saltNonce),\n \"GelatoUserProxyFactory.createTwo: wrong address prediction\"\n );\n _storeGelatoUserProxy(userProxy);\n }\n\n function createTwoExecActions(uint256 _saltNonce, Action[] calldata _actions)\n external\n payable\n override\n returns (GelatoUserProxy userProxy)\n {\n userProxy = createTwo(_saltNonce);\n if (_actions.length != 0) _execActions(userProxy, _actions);\n }\n\n function createTwoSubmitTasks(\n uint256 _saltNonce,\n // Submit Tasks Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n override\n returns (GelatoUserProxy userProxy)\n {\n userProxy = createTwo(_saltNonce);\n if (_tasks.length != 0) _submitTasks(userProxy, _provider, _tasks, _expiryDates);\n }\n\n // A standard _saltNonce can be used for deterministic shared address derivation\n function createTwoExecActionsSubmitTasks(\n uint256 _saltNonce,\n Action[] calldata _actions,\n // Submit Tasks Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n override\n returns(GelatoUserProxy userProxy)\n {\n userProxy = createTwo(_saltNonce);\n if (_actions.length != 0) _execActions(userProxy, _actions);\n if (_tasks.length != 0) _submitTasks(userProxy, _provider, _tasks, _expiryDates);\n }\n\n function createTwoExecActionsSubmitTaskCycle(\n uint256 _saltNonce,\n Action[] calldata _actions,\n // Submit TaskCycle Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external\n payable\n override\n returns(GelatoUserProxy userProxy)\n {\n userProxy = createTwo(_saltNonce);\n if (_actions.length != 0) _execActions(userProxy, _actions);\n if (_tasks.length == 0)\n revert(\"GelatoUserProxyFactory.createTwoExecActionsSubmitTaskCycle: 0 _tasks\");\n _submitTaskCycle(userProxy, _provider, _tasks, _expiryDate, _cycles);\n }\n\n function createTwoExecActionsSubmitTaskChain(\n uint256 _saltNonce,\n Action[] calldata _actions,\n // Submit TaskChain Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n external\n payable\n override\n returns(GelatoUserProxy userProxy)\n {\n userProxy = createTwo(_saltNonce);\n if (_actions.length != 0) _execActions(userProxy, _actions);\n if (_tasks.length == 0)\n revert(\"GelatoUserProxyFactory.createTwoExecActionsSubmitTaskChain: 0 _tasks\");\n _submitTaskChain(userProxy, _provider, _tasks, _expiryDate, _sumOfRequestedTaskSubmits);\n }\n\n // ==================== GETTERS =======================================\n function predictProxyAddress(address _user, uint256 _saltNonce)\n public\n view\n override\n returns(address)\n {\n // Standard Way of deriving salt\n bytes32 salt = keccak256(abi.encode(_user, _saltNonce));\n\n // Derive undeployed userProxy address\n return address(uint(keccak256(abi.encodePacked(\n byte(0xff),\n address(this),\n salt,\n keccak256(abi.encodePacked(proxyCreationCode(), abi.encode(_user, gelatoCore)))\n ))));\n }\n\n function isGelatoUserProxy(address _proxy) external view override returns(bool) {\n return userByGelatoProxy[GelatoUserProxy(payable(_proxy))] != address(0);\n }\n\n function isGelatoProxyUser(address _user, GelatoUserProxy _userProxy)\n external\n view\n override\n returns(bool)\n {\n return _gelatoProxiesByUser[_user].contains(_userProxy);\n }\n\n function gelatoProxiesByUser(address _user)\n external\n view\n override\n returns(GelatoUserProxy[] memory)\n {\n return _gelatoProxiesByUser[_user].enumerate();\n }\n\n function getGelatoUserProxyByIndex(address _user, uint256 _index)\n external\n view\n override\n returns(GelatoUserProxy)\n {\n return _gelatoProxiesByUser[_user].get(_index);\n }\n\n function proxyCreationCode() public pure override returns(bytes memory) {\n return type(GelatoUserProxy).creationCode;\n }\n\n // ==================== HELPERS =======================================\n // store and emit LogCreation\n function _storeGelatoUserProxy(GelatoUserProxy _userProxy) private {\n _gelatoProxiesByUser[msg.sender].add(_userProxy);\n userByGelatoProxy[_userProxy] = msg.sender;\n emit LogCreation(msg.sender, _userProxy, msg.value);\n }\n\n function _execActions(GelatoUserProxy _userProxy, Action[] calldata _actions) private {\n try _userProxy.multiExecActions(_actions) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxyFactory._execActions:\", err)));\n } catch {\n revert(\"GelatoUserProxyFactory._execActions:undefined\");\n }\n }\n\n function _submitTasks(\n GelatoUserProxy _userProxy,\n // Submit Tasks Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n private\n {\n try _userProxy.multiSubmitTasks(_provider, _tasks, _expiryDates) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxyFactory._submitTasks:\", err)));\n } catch {\n revert(\"GelatoUserProxyFactory._submitTasks:undefined\");\n }\n }\n\n function _submitTaskCycle(\n GelatoUserProxy _userProxy,\n // Submit TaskCyle Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n private\n {\n try _userProxy.submitTaskCycle(_provider, _tasks, _expiryDate, _cycles) {\n } catch Error(string memory err) {\n revert(\n string(abi.encodePacked(\"GelatoUserProxyFactory._submitTaskCycle:\", err))\n );\n } catch {\n revert(\"GelatoUserProxyFactory._submitTaskCycle:undefined\");\n }\n }\n\n function _submitTaskChain(\n GelatoUserProxy _userProxy,\n // Submit TaskChain Data\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n private\n {\n try _userProxy.submitTaskChain(\n _provider,\n _tasks,\n _expiryDate,\n _sumOfRequestedTaskSubmits\n ) {\n } catch Error(string memory err) {\n revert(\n string(abi.encodePacked(\"GelatoUserProxyFactory._submitTaskChain:\", err))\n );\n } catch {\n revert(\"GelatoUserProxyFactory._submitTaskChain:undefined\");\n }\n }\n}\n"
},
"contracts/user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxyFactory.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoUserProxy} from \"../GelatoUserProxy.sol\";\nimport {Action, Provider, Task} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ninterface IGelatoUserProxyFactory {\n event LogCreation(\n address indexed user,\n GelatoUserProxy indexed userProxy,\n uint256 funding\n );\n\n // ==================== CREATE =======================================\n /// @notice Create a GelatoUserProxy.\n /// @return userProxy address of deployed proxy contract.\n function create()\n external\n payable\n returns (GelatoUserProxy userProxy);\n\n /// @notice Create a GelatoUserProxy and exec actions\n /// @param _actions Optional actions to execute.\n /// @return userProxy address of deployed proxy contract.\n function createExecActions(Action[] calldata _actions)\n external\n payable\n returns (GelatoUserProxy userProxy);\n\n /// @notice Create a GelatoUserProxy and submit Tasks to Gelato in the same tx.\n /// @param _provider Provider for each of the _tasks.\n /// @param _tasks Tasks to submit to Gelato. Must each have their own Provider.\n /// @param _expiryDates expiryDate for each of the _tasks.\n /// CAUTION: The ordering of _tasks<=>_expiryDates must be coordinated.\n /// @return userProxy address of deployed proxy contract.\n function createSubmitTasks(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n returns (GelatoUserProxy userProxy);\n\n /// @notice Create a GelatoUserProxy.\n /// @param _actions Optional actions to execute.\n /// @param _provider Provider for each of the _tasks.\n /// @param _tasks Tasks to submit to Gelato. Must each have their own Provider.\n /// @param _expiryDates expiryDate for each of the _tasks.\n /// CAUTION: The ordering of _tasks<=>_expiryDates must be coordinated.\n /// @return userProxy address of deployed proxy contract.\n function createExecActionsSubmitTasks(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n returns(GelatoUserProxy userProxy);\n\n /// @notice Like create but for submitting a Task Cycle to Gelato. A\n // Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed\n /// @notice A Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed.\n /// @param _actions Optional actions to execute.\n /// @param _provider Gelato Provider object for _tasks: provider address and module.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _cycles How many full cycles will be submitted\n function createExecActionsSubmitTaskCycle(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external\n payable\n returns(GelatoUserProxy userProxy);\n\n /// @notice Like create but for submitting a Task Cycle to Gelato. A\n // Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed\n /// @dev CAUTION: _sumOfRequestedTaskSubmits does not mean the number of cycles.\n /// @param _actions Optional actions to execute.\n /// @param _provider Gelato Provider object for _tasks: provider address and module.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _sumOfRequestedTaskSubmits The TOTAL number of Task auto-submits\n // that should have occured once the cycle is complete:\n /// 1) _sumOfRequestedTaskSubmits=X: number of times to run the same task or the sum\n /// of total cyclic task executions in the case of a sequence of different tasks.\n /// 2) _submissionsLeft=0: infinity - run the same task or sequence of tasks infinitely.\n function createExecActionsSubmitTaskChain(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n external\n payable\n returns(GelatoUserProxy userProxy);\n\n // ==================== CREATE 2 =======================================\n\n /// @notice Create a GelatoUserProxy using the create2 opcode.\n /// @param _saltNonce salt is generated thusly: keccak256(abi.encode(_user, _saltNonce))\n /// @return userProxy address of deployed proxy contract.\n function createTwo(uint256 _saltNonce)\n external\n payable\n returns (GelatoUserProxy userProxy);\n\n /// @notice Create a GelatoUserProxy using the create2 opcode and exec actions\n /// @param _saltNonce salt is generated thusly: keccak256(abi.encode(_user, _saltNonce))\n /// @param _actions Optional actions to execute.\n /// @return userProxy address of deployed proxy contract.\n function createTwoExecActions(uint256 _saltNonce, Action[] calldata _actions)\n external\n payable\n returns (GelatoUserProxy userProxy);\n\n /// @notice Create a salted GelatoUserProxy and submit Tasks to Gelato in the same tx.\n /// @param _provider Provider for each of the _tasks.\n /// @param _tasks Tasks to submit to Gelato. Must each have their own Provider.\n /// @param _expiryDates expiryDate for each of the _tasks.\n /// CAUTION: The ordering of _tasks<=>_expiryDates must be coordinated.\n /// @return userProxy address of deployed proxy contract.\n function createTwoSubmitTasks(\n uint256 _saltNonce,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n returns (GelatoUserProxy userProxy);\n\n /// @notice Create a GelatoUserProxy using the create2 opcode.\n /// @dev This allows for creating a GelatoUserProxy instance at a specific address.\n /// which can be predicted and e.g. prefunded.\n /// @param _saltNonce salt is generated thusly: keccak256(abi.encode(_user, _saltNonce))\n /// @param _actions Optional actions to execute.\n /// @param _provider Provider for each of the _tasks.\n /// @param _tasks Tasks to submit to Gelato. Must each have their own Provider.\n /// @param _expiryDates expiryDate for each of the _tasks.\n /// CAUTION: The ordering of _tasks<=>_expiryDates must be coordinated.\n function createTwoExecActionsSubmitTasks(\n uint256 _saltNonce,\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n payable\n returns(GelatoUserProxy userProxy);\n\n /// @notice Just like createAndSubmitTaskCycle just using create2, thus allowing for\n /// knowing the address the GelatoUserProxy will be assigned to in advance.\n /// @param _saltNonce salt is generated thusly: keccak256(abi.encode(_user, _saltNonce))\n function createTwoExecActionsSubmitTaskCycle(\n uint256 _saltNonce,\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external\n payable\n returns(GelatoUserProxy userProxy);\n\n /// @notice Just like createAndSubmitTaskChain just using create2, thus allowing for\n /// knowing the address the GelatoUserProxy will be assigned to in advance.\n /// @param _saltNonce salt is generated thusly: keccak256(abi.encode(_user, _saltNonce))\n function createTwoExecActionsSubmitTaskChain(\n uint256 _saltNonce,\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n external\n payable\n returns(GelatoUserProxy userProxy);\n\n // ==================== GETTERS =======================================\n function predictProxyAddress(address _user, uint256 _saltNonce)\n external\n view\n returns(address);\n\n /// @notice Get address of user (EOA) from proxy contract address\n /// @param _userProxy Address of proxy contract\n /// @return User (EOA) address\n function userByGelatoProxy(GelatoUserProxy _userProxy) external view returns(address);\n\n /// @notice Get a list of userProxies that belong to one user.\n /// @param _user Address of user\n /// @return array of deployed GelatoUserProxies that belong to the _user.\n function gelatoProxiesByUser(address _user) external view returns(GelatoUserProxy[] memory);\n\n function getGelatoUserProxyByIndex(address _user, uint256 _index)\n external\n view\n returns(GelatoUserProxy);\n\n /// @notice Check if proxy was deployed from gelato proxy factory\n /// @param _userProxy Address of proxy contract\n /// @return true if it was deployed from gelato user proxy factory\n function isGelatoUserProxy(address _userProxy) external view returns(bool);\n\n /// @notice Check if user has deployed a proxy from gelato proxy factory\n /// @param _user Address of user\n /// @param _userProxy Address of supposed userProxy\n /// @return true if user deployed a proxy from gelato user proxy factory\n function isGelatoProxyUser(address _user, GelatoUserProxy _userProxy)\n external\n view\n returns(bool);\n\n /// @notice Returns address of gelato\n /// @return Gelato core address\n function gelatoCore() external pure returns(address);\n\n /// @notice Returns the CreationCode used by the Factory to create GelatoUserProxies.\n /// @dev This is internally used by the factory to predict the address during create2.\n function proxyCreationCode() external pure returns(bytes memory);\n}"
},
"contracts/external/Address.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * This test is non-exhaustive, and there may be false-negatives: during the\n * execution of a contract's constructor, its address will be reported as\n * not containing a contract.\n *\n * IMPORTANT: It is unsafe to assume that an address for which this\n * function returns false is an externally-owned account (EOA) and not a\n * contract.\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies in extcodesize, which returns 0 for contracts in\n // construction, since the code is only stored at the end of the\n // constructor execution.\n\n // According to EIP-1052, 0x0 is the value returned for not-yet created accounts\n // and 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470 is returned\n // for accounts without code, i.e. `keccak256('')`\n bytes32 codehash;\n bytes32 accountHash = 0xc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470;\n // solhint-disable-next-line no-inline-assembly\n assembly { codehash := extcodehash(account) }\n return (codehash != 0x0 && codehash != accountHash);\n }\n\n /**\n * @dev Converts an `address` into `address payable`. Note that this is\n * simply a type cast: the actual underlying value is not changed.\n *\n * _Available since v2.4.0._\n */\n function toPayable(address account) internal pure returns (address payable) {\n return address(uint160(account));\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n *\n * _Available since v2.4.0._\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n // solhint-disable-next-line avoid-call-value\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n}\n"
},
"contracts/user_proxies/gelato_user_proxy/GelatoUserProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoUserProxy} from \"./interfaces/IGelatoUserProxy.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {\n Action, Operation, Provider, Task, TaskReceipt, IGelatoCore\n} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract GelatoUserProxy is IGelatoUserProxy {\n\n using GelatoBytes for bytes;\n\n address public immutable override factory;\n address public immutable override user;\n address public immutable override gelatoCore;\n\n constructor(address _user, address _gelatoCore)\n public\n payable\n noZeroAddress(_user)\n noZeroAddress(_gelatoCore)\n {\n factory = msg.sender;\n user = _user;\n gelatoCore = _gelatoCore;\n }\n\n receive() external payable {}\n\n modifier noZeroAddress(address _) {\n require(_ != address(0), \"GelatoUserProxy.noZeroAddress\");\n _;\n }\n\n modifier onlyUser() {\n require(msg.sender == user, \"GelatoUserProxy.onlyUser: failed\");\n _;\n }\n\n modifier userOrFactory() {\n require(\n msg.sender == user || msg.sender == factory,\n \"GelatoUserProxy.userOrFactory: failed\");\n _;\n }\n\n modifier auth() {\n require(\n msg.sender == gelatoCore || msg.sender == user || msg.sender == factory,\n \"GelatoUserProxy.auth: failed\"\n );\n _;\n }\n\n function submitTask(Provider calldata _provider, Task calldata _task, uint256 _expiryDate)\n public\n override\n userOrFactory\n {\n\n try IGelatoCore(gelatoCore).submitTask(_provider, _task, _expiryDate) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxy.submitTask:\", err)));\n } catch {\n revert(\"GelatoUserProxy.submitTask:undefinded\");\n }\n }\n\n function multiSubmitTasks(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external\n override\n {\n require(\n _tasks.length == _expiryDates.length,\n \"GelatoUserProxy.multiSubmitTasks: each task needs own expiryDate\"\n );\n for (uint i; i < _tasks.length; i++)\n submitTask(_provider, _tasks[i], _expiryDates[i]);\n }\n\n function submitTaskCycle(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles // num of full cycles\n )\n public\n override\n userOrFactory\n {\n try IGelatoCore(gelatoCore).submitTaskCycle(\n _provider,\n _tasks,\n _expiryDate,\n _cycles\n ) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxy.submitTaskCycle:\", err)));\n } catch {\n revert(\"GelatoUserProxy.submitTaskCycle:undefinded\");\n }\n }\n\n function submitTaskChain(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits // num of all prospective task submissions\n )\n public\n override\n userOrFactory\n {\n try IGelatoCore(gelatoCore).submitTaskChain(\n _provider,\n _tasks,\n _expiryDate,\n _sumOfRequestedTaskSubmits\n ) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxy.submitTaskChain:\", err)));\n } catch {\n revert(\"GelatoUserProxy.submitTaskChain:undefinded\");\n }\n }\n\n function cancelTask(TaskReceipt calldata _TR) external override onlyUser {\n try IGelatoCore(gelatoCore).cancelTask(_TR) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxy.cancelTask:\", err)));\n } catch {\n revert(\"GelatoUserProxy.cancelTask:undefinded\");\n }\n }\n\n function multiCancelTasks(TaskReceipt[] calldata _TRs) external override onlyUser {\n try IGelatoCore(gelatoCore).multiCancelTasks(_TRs) {\n } catch Error(string memory err) {\n revert(string(abi.encodePacked(\"GelatoUserProxy.multiCancelTasks:\", err)));\n } catch {\n revert(\"GelatoUserProxy.multiCancelTasks:undefinded\");\n }\n }\n\n // @dev we have to write duplicate code due to calldata _action FeatureNotImplemented\n function execAction(Action calldata _action) external payable override auth {\n if (_action.operation == Operation.Call)\n _callAction(_action.addr, _action.data, _action.value);\n else if (_action.operation == Operation.Delegatecall)\n _delegatecallAction(_action.addr, _action.data);\n else\n revert(\"GelatoUserProxy.execAction: invalid operation\");\n }\n\n // @dev we have to write duplicate code due to calldata _action FeatureNotImplemented\n function multiExecActions(Action[] calldata _actions) public payable override auth {\n for (uint i = 0; i < _actions.length; i++) {\n if (_actions[i].operation == Operation.Call)\n _callAction(_actions[i].addr, _actions[i].data, _actions[i].value);\n else if (_actions[i].operation == Operation.Delegatecall)\n _delegatecallAction(address(_actions[i].addr), _actions[i].data);\n else\n revert(\"GelatoUserProxy.multiExecActions: invalid operation\");\n }\n }\n\n // @dev we have to write duplicate code due to calldata _action FeatureNotImplemented\n function execActionsAndSubmitTaskCycle(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external\n payable\n override\n auth\n {\n if (_actions.length != 0) multiExecActions(_actions);\n if(_tasks.length != 0) submitTaskCycle(_provider, _tasks, _expiryDate, _cycles);\n }\n\n function _callAction(address _action, bytes calldata _data, uint256 _value)\n internal\n noZeroAddress(_action)\n {\n (bool success, bytes memory returndata) = _action.call{value: _value}(_data);\n if (!success) returndata.revertWithErrorString(\"GelatoUserProxy._callAction:\");\n }\n\n function _delegatecallAction(address _action, bytes calldata _data)\n internal\n noZeroAddress(_action)\n {\n (bool success, bytes memory returndata) = _action.delegatecall(_data);\n if (!success) returndata.revertWithErrorString(\"GelatoUserProxy._delegatecallAction:\");\n }\n}"
},
"contracts/libraries/GelatoUserProxySet.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoUserProxy} from \"../user_proxies/gelato_user_proxy/GelatoUserProxy.sol\";\n\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * As of v2.5.0, only `GelatoUserProxy` sets are supported.\n *\n * Include with `using EnumerableSet for EnumerableSet.Set;`.\n *\n * _Available since v2.5.0._\n *\n * @author Alberto Cuesta Cañada\n * @author Luis Schliessske (modified to GelatoUserProxySet)\n */\nlibrary GelatoUserProxySet {\n\n struct Set {\n // Position of the proxy in the `gelatoUserProxies` array, plus 1 because index 0\n // means a proxy is not in the set.\n mapping (GelatoUserProxy => uint256) index;\n GelatoUserProxy[] gelatoUserProxies;\n }\n\n /**\n * @dev Add a proxy to a set. O(1).\n * Returns false if the proxy was already in the set.\n */\n function add(Set storage set, GelatoUserProxy proxy)\n internal\n returns (bool)\n {\n if (!contains(set, proxy)) {\n set.gelatoUserProxies.push(proxy);\n // The element is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel proxy\n set.index[proxy] = set.gelatoUserProxies.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a proxy from a set. O(1).\n * Returns false if the proxy was not present in the set.\n */\n function remove(Set storage set, GelatoUserProxy proxy)\n internal\n returns (bool)\n {\n if (contains(set, proxy)){\n uint256 toDeleteIndex = set.index[proxy] - 1;\n uint256 lastIndex = set.gelatoUserProxies.length - 1;\n\n // If the element we're deleting is the last one, we can just remove it without doing a swap\n if (lastIndex != toDeleteIndex) {\n GelatoUserProxy lastValue = set.gelatoUserProxies[lastIndex];\n\n // Move the last proxy to the index where the deleted proxy is\n set.gelatoUserProxies[toDeleteIndex] = lastValue;\n // Update the index for the moved proxy\n set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based\n }\n\n // Delete the index entry for the deleted proxy\n delete set.index[proxy];\n\n // Delete the old entry for the moved proxy\n set.gelatoUserProxies.pop();\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the proxy is in the set. O(1).\n */\n function contains(Set storage set, GelatoUserProxy proxy)\n internal\n view\n returns (bool)\n {\n return set.index[proxy] != 0;\n }\n\n /**\n * @dev Returns an array with all gelatoUserProxies in the set. O(N).\n * Note that there are no guarantees on the ordering of gelatoUserProxies inside the\n * array, and it may change when more gelatoUserProxies are added or removed.\n\n * WARNING: This function may run out of gas on large sets: use {length} and\n * {get} instead in these cases.\n */\n function enumerate(Set storage set)\n internal\n view\n returns (GelatoUserProxy[] memory)\n {\n GelatoUserProxy[] memory output = new GelatoUserProxy[](set.gelatoUserProxies.length);\n for (uint256 i; i < set.gelatoUserProxies.length; i++) output[i] = set.gelatoUserProxies[i];\n return output;\n }\n\n /**\n * @dev Returns the number of elements on the set. O(1).\n */\n function length(Set storage set)\n internal\n view\n returns (uint256)\n {\n return set.gelatoUserProxies.length;\n }\n\n /** @dev Returns the element stored at position `index` in the set. O(1).\n * Note that there are no guarantees on the ordering of gelatoUserProxies inside the\n * array, and it may change when more gelatoUserProxies are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function get(Set storage set, uint256 index)\n internal\n view\n returns (GelatoUserProxy)\n {\n return set.gelatoUserProxies[index];\n }\n}"
},
"contracts/user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {\n Action, Provider, Task, TaskReceipt\n} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ninterface IGelatoUserProxy {\n\n /// @notice API to submit a single Task.\n /// @dev You can let users submit multiple tasks at once by batching calls to this.\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _task A Gelato Task object: provider, conditions, actions.\n /// @param _expiryDate From then on the task cannot be executed. 0 for infinity.\n function submitTask(Provider calldata _provider, Task calldata _task, uint256 _expiryDate)\n external;\n\n /// @notice API to submit multiple \"single\" Tasks.\n /// @dev CAUTION: The ordering of _tasks<=>_expiryDates must be coordinated.\n /// @param _providers Gelato Provider object: provider address and module.\n /// @param _tasks An array of Gelato Task objects: provider, conditions, actions.\n /// @param _expiryDates From then on the task cannot be executed. 0 for infinity.\n function multiSubmitTasks(\n Provider calldata _providers,\n Task[] calldata _tasks,\n uint256[] calldata _expiryDates\n )\n external;\n\n /// @notice A Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _cycles How many full cycles will be submitted\n function submitTaskCycle(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external;\n\n /// @notice A Gelato Task Cycle consists of 1 or more Tasks that automatically submit\n /// the next one, after they have been executed.\n /// @dev CAUTION: _sumOfRequestedTaskSubmits does not mean the number of cycles.\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _sumOfRequestedTaskSubmits The TOTAL number of Task auto-submits\n // that should have occured once the cycle is complete:\n /// 1) _sumOfRequestedTaskSubmits=X: number of times to run the same task or the sum\n /// of total cyclic task executions in the case of a sequence of different tasks.\n /// 2) _submissionsLeft=0: infinity - run the same task or sequence of tasks infinitely.\n function submitTaskChain(\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n ) external;\n\n\n /// @notice Execs actions and submits task cycle in one tx\n /// @param _actions Actions to execute\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _tasks This can be a single task or a sequence of tasks.\n /// @param _expiryDate After this no task of the sequence can be executed any more.\n /// @param _cycles How many full cycles will be submitted\n function execActionsAndSubmitTaskCycle(\n Action[] calldata _actions,\n Provider calldata _provider,\n Task[] calldata _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n external\n payable;\n\n /// @notice Cancel a task receipt on gelato\n /// @dev Proxy users or the Task providers can cancel.\n /// @param _TR Task Receipt to cancel\n function cancelTask(TaskReceipt calldata _TR) external;\n\n /// @notice Cancel Tasks with their receipts on gelato\n /// @dev Proxy users or the Task providers can cancel.\n /// @param _TRs Task Receipts of Tasks to cancel\n function multiCancelTasks(TaskReceipt[] calldata _TRs) external;\n\n /// @notice Execute an action\n /// @param _action Action to execute\n function execAction(Action calldata _action) external payable;\n\n /// @notice Execute multiple actions\n /// @param _actions Actions to execute\n function multiExecActions(Action[] calldata _actions) external payable;\n\n /// @notice Get the factory address whence the proxy was created.\n /// @return Address of proxy's factory\n function factory() external pure returns(address);\n\n /// @notice Get the owner (EOA) address of the proxy\n /// @return Address of proxy owner\n function user() external pure returns(address);\n\n /// @notice Get the address of gelato\n /// @return Address of gelato\n function gelatoCore() external pure returns(address);\n}\n"
},
"contracts/libraries/GelatoBytes.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nlibrary GelatoBytes {\n function calldataSliceSelector(bytes calldata _bytes)\n internal\n pure\n returns (bytes4 selector)\n {\n selector =\n _bytes[0] |\n (bytes4(_bytes[1]) >> 8) |\n (bytes4(_bytes[2]) >> 16) |\n (bytes4(_bytes[3]) >> 24);\n }\n\n function memorySliceSelector(bytes memory _bytes)\n internal\n pure\n returns (bytes4 selector)\n {\n selector =\n _bytes[0] |\n (bytes4(_bytes[1]) >> 8) |\n (bytes4(_bytes[2]) >> 16) |\n (bytes4(_bytes[3]) >> 24);\n }\n\n function revertWithErrorString(bytes memory _bytes, string memory _tracingInfo)\n internal\n pure\n {\n // 68: 32-location, 32-length, 4-ErrorSelector, UTF-8 err\n if (_bytes.length % 32 == 4) {\n bytes4 selector;\n assembly { selector := mload(add(0x20, _bytes)) }\n if (selector == 0x08c379a0) { // Function selector for Error(string)\n assembly { _bytes := add(_bytes, 68) }\n revert(string(abi.encodePacked(_tracingInfo, string(_bytes))));\n } else {\n revert(string(abi.encodePacked(_tracingInfo, \"NoErrorSelector\")));\n }\n } else {\n revert(string(abi.encodePacked(_tracingInfo, \"UnexpectedReturndata\")));\n }\n }\n}"
},
"contracts/gelato_provider_modules/gnosis_safe_proxy_provider/ProviderModuleGnosisSafeProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoProviderModuleStandard} from \"../GelatoProviderModuleStandard.sol\";\nimport {IProviderModuleGnosisSafeProxy} from \"./IProviderModuleGnosisSafeProxy.sol\";\nimport {Ownable} from \"../../external/Ownable.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {GelatoActionPipeline} from \"../../gelato_actions/GelatoActionPipeline.sol\";\nimport {\n IGnosisSafe\n} from \"../../user_proxies/gnosis_safe_proxy/interfaces/IGnosisSafe.sol\";\nimport {\n IGnosisSafeProxy\n} from \"../../user_proxies/gnosis_safe_proxy/interfaces/IGnosisSafeProxy.sol\";\nimport {Task} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract ProviderModuleGnosisSafeProxy is\n GelatoProviderModuleStandard,\n IProviderModuleGnosisSafeProxy,\n Ownable\n{\n using GelatoBytes for bytes;\n\n mapping(bytes32 => bool) public override isProxyExtcodehashProvided;\n mapping(address => bool) public override isMastercopyProvided;\n address public override immutable gelatoCore;\n address public override immutable gelatoActionPipeline;\n\n constructor(\n bytes32[] memory hashes,\n address[] memory masterCopies,\n address _gelatoCore,\n address _gelatoActionPipeline\n )\n public\n {\n multiProvide(hashes, masterCopies);\n gelatoCore = _gelatoCore;\n gelatoActionPipeline = _gelatoActionPipeline;\n }\n\n // ================= GELATO PROVIDER MODULE STANDARD ================\n // @dev since we check extcodehash prior to execution, we forego the execution option\n // where the userProxy is deployed at execution time.\n function isProvided(address _userProxy, address, Task calldata)\n external\n view\n override\n returns(string memory)\n {\n bytes32 codehash;\n assembly { codehash := extcodehash(_userProxy) }\n if (!isProxyExtcodehashProvided[codehash])\n return \"ProviderModuleGnosisSafeProxy.isProvided:InvalidGSPCodehash\";\n address mastercopy = IGnosisSafeProxy(_userProxy).masterCopy();\n if (!isMastercopyProvided[mastercopy])\n return \"ProviderModuleGnosisSafeProxy.isProvided:InvalidGSPMastercopy\";\n if (!isGelatoCoreWhitelisted(_userProxy))\n return \"ProviderModuleGnosisSafeProxy.isProvided:GelatoCoreNotWhitelisted\";\n return OK;\n }\n\n function execPayload(uint256, address, address, Task calldata _task, uint256)\n external\n view\n override\n returns(bytes memory payload, bool proxyReturndataCheck)\n {\n // execTransactionFromModuleReturnData catches reverts so must check for reverts\n proxyReturndataCheck = true;\n\n if (_task.actions.length == 1) {\n payload = abi.encodeWithSelector(\n IGnosisSafe.execTransactionFromModuleReturnData.selector,\n _task.actions[0].addr, // to\n _task.actions[0].value,\n _task.actions[0].data,\n _task.actions[0].operation\n );\n } else if (_task.actions.length > 1) {\n // Action.Operation encoded into multiSendPayload and handled by Multisend\n bytes memory gelatoActionPipelinePayload = abi.encodeWithSelector(\n GelatoActionPipeline.execActionsAndPipeData.selector,\n _task.actions\n );\n\n payload = abi.encodeWithSelector(\n IGnosisSafe.execTransactionFromModuleReturnData.selector,\n gelatoActionPipeline, // to\n 0, // value\n gelatoActionPipelinePayload, // data\n IGnosisSafe.Operation.DelegateCall\n );\n\n } else {\n revert(\"ProviderModuleGnosisSafeProxy.execPayload: 0 _task.actions length\");\n }\n }\n\n function execRevertCheck(bytes calldata _proxyReturndata)\n external\n pure\n virtual\n override\n {\n (bool success, bytes memory returndata) = abi.decode(_proxyReturndata, (bool,bytes));\n if (!success) returndata.revertWithErrorString(\":ProviderModuleGnosisSafeProxy:\");\n }\n\n // GnosisSafeProxy\n function provideProxyExtcodehashes(bytes32[] memory _hashes) public override onlyOwner {\n for (uint i; i < _hashes.length; i++) {\n require(\n !isProxyExtcodehashProvided[_hashes[i]],\n \"ProviderModuleGnosisSafeProxy.provideProxyExtcodehashes: redundant\"\n );\n isProxyExtcodehashProvided[_hashes[i]] = true;\n emit LogProvideProxyExtcodehash(_hashes[i]);\n }\n }\n\n function unprovideProxyExtcodehashes(bytes32[] memory _hashes) public override onlyOwner {\n for (uint i; i < _hashes.length; i++) {\n require(\n isProxyExtcodehashProvided[_hashes[i]],\n \"ProviderModuleGnosisSafeProxy.unprovideProxyExtcodehashes: redundant\"\n );\n delete isProxyExtcodehashProvided[_hashes[i]];\n emit LogUnprovideProxyExtcodehash(_hashes[i]);\n }\n }\n\n function provideMastercopies(address[] memory _mastercopies) public override onlyOwner {\n for (uint i; i < _mastercopies.length; i++) {\n require(\n !isMastercopyProvided[_mastercopies[i]],\n \"ProviderModuleGnosisSafeProxy.provideMastercopy: redundant\"\n );\n isMastercopyProvided[_mastercopies[i]] = true;\n emit LogProvideMastercopy(_mastercopies[i]);\n }\n }\n\n function unprovideMastercopies(address[] memory _mastercopies) public override onlyOwner {\n for (uint i; i < _mastercopies.length; i++) {\n require(\n isMastercopyProvided[_mastercopies[i]],\n \"ProviderModuleGnosisSafeProxy.unprovideMastercopies: redundant\"\n );\n delete isMastercopyProvided[_mastercopies[i]];\n emit LogUnprovideMastercopy(_mastercopies[i]);\n }\n }\n\n // Batch (un-)provide\n function multiProvide(bytes32[] memory _hashes, address[] memory _mastercopies)\n public\n override\n onlyOwner\n {\n provideProxyExtcodehashes(_hashes);\n provideMastercopies(_mastercopies);\n }\n\n function multiUnprovide(bytes32[] calldata _hashes, address[] calldata _mastercopies)\n external\n override\n onlyOwner\n {\n unprovideProxyExtcodehashes(_hashes);\n unprovideMastercopies(_mastercopies);\n }\n\n function isGelatoCoreWhitelisted(address _userProxy)\n view\n internal\n returns(bool)\n {\n address[] memory whitelistedModules = IGnosisSafe(_userProxy).getModules();\n for (uint i = 0; i < whitelistedModules.length; i++)\n if (whitelistedModules[i] == gelatoCore) return true;\n return false;\n }\n\n}"
},
"contracts/gelato_provider_modules/GelatoProviderModuleStandard.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoProviderModule} from \"./IGelatoProviderModule.sol\";\nimport {Task} from \"../gelato_core/interfaces/IGelatoCore.sol\";\n\nabstract contract GelatoProviderModuleStandard is IGelatoProviderModule {\n\n string internal constant OK = \"OK\";\n\n function isProvided(address, address, Task calldata)\n external\n view\n virtual\n override\n returns(string memory)\n {\n return OK;\n }\n\n /// @dev Overriding fns should revert with the revertMsg they detected on the userProxy\n function execRevertCheck(bytes calldata) external pure override virtual {\n // By default no reverts detected => do nothing\n }\n}\n"
},
"contracts/gelato_provider_modules/gnosis_safe_proxy_provider/IProviderModuleGnosisSafeProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\ninterface IProviderModuleGnosisSafeProxy{\n event LogProvideProxyExtcodehash(bytes32 indexed extcodehash);\n event LogUnprovideProxyExtcodehash(bytes32 indexed extcodehash);\n\n event LogProvideMastercopy(address indexed mastercopy);\n event LogUnprovideMastercopy(address indexed mastercopy);\n\n // GnosisSafeProxy\n function provideProxyExtcodehashes(bytes32[] calldata _hashes) external;\n function unprovideProxyExtcodehashes(bytes32[] calldata _hashes) external;\n\n function provideMastercopies(address[] calldata _mastercopies) external;\n function unprovideMastercopies(address[] calldata _mastercopies) external;\n\n // Batch (un-)provide\n function multiProvide(bytes32[] calldata _hashes, address[] calldata _mastercopies)\n external;\n\n function multiUnprovide(bytes32[] calldata _hashes, address[] calldata _mastercopies)\n external;\n\n function isProxyExtcodehashProvided(bytes32 _hash)\n external\n view\n returns(bool);\n function isMastercopyProvided(address _mastercopy)\n external\n view\n returns(bool);\n\n\n function gelatoCore() external pure returns(address);\n function gelatoActionPipeline() external pure returns(address);\n}\n"
},
"contracts/external/Ownable.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\ncontract Ownable {\n address private _owner;\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() internal {\n _owner = msg.sender;\n emit OwnershipTransferred(address(0), _owner);\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(isOwner(), \"Ownable: caller is not the owner\");\n _;\n }\n\n /**\n * @dev Returns true if the caller is the current owner.\n */\n function isOwner() public view returns (bool) {\n return msg.sender == _owner;\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n emit OwnershipTransferred(_owner, address(0));\n _owner = address(0);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n */\n function _transferOwnership(address newOwner) internal virtual {\n require(\n newOwner != address(0),\n \"Ownable: new owner is the zero address\"\n );\n emit OwnershipTransferred(_owner, newOwner);\n _owner = newOwner;\n }\n}\n"
},
"contracts/gelato_actions/GelatoActionPipeline.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {Action, Operation, DataFlow} from \"../gelato_core/interfaces/IGelatoCore.sol\";\nimport {GelatoBytes} from \"../libraries/GelatoBytes.sol\";\nimport {IGelatoInFlowAction} from \"./action_pipeline_interfaces/IGelatoInFlowAction.sol\";\nimport {IGelatoOutFlowAction} from \"./action_pipeline_interfaces/IGelatoOutFlowAction.sol\";\nimport {\n IGelatoInAndOutFlowAction\n} from \"./action_pipeline_interfaces/IGelatoInAndOutFlowAction.sol\";\n\n/// @title GelatoActionPipeline\n/// @notice Runtime Environment for executing multiple Actions that can share data\ncontract GelatoActionPipeline {\n\n using GelatoBytes for bytes;\n\n address public immutable thisActionAddress;\n constructor() public { thisActionAddress = address(this); }\n\n /// @notice This code can be delegatecalled by User Proxies during the execution\n /// of multiple Actions, in order to let data flow between them, in\n /// accordance with their Action.DataFlow specifications.\n /// @dev ProviderModules should encode their execPayload with this function selector.\n /// @param _actions List of _actions to be executed sequentially in pipeline\n function execActionsAndPipeData(Action[] calldata _actions) external {\n require(thisActionAddress != address(this), \"GelatoActionPipeline.delegatecallOnly\");\n\n // Store for reusable data from Actions that DataFlow.Out or DataFlow.InAndOut\n bytes memory dataFromLastOutFlowAction;\n\n // We execute Actions sequentially and store reusable outflowing Data\n for (uint i = 0; i < _actions.length; i++) {\n require(_actions[i].addr != address(0), \"GelatoActionPipeline.noZeroAddress\");\n\n bytes memory actionPayload;\n\n if (_actions[i].dataFlow == DataFlow.In) {\n actionPayload = abi.encodeWithSelector(\n IGelatoInFlowAction.execWithDataFlowIn.selector,\n _actions[i].data,\n dataFromLastOutFlowAction\n );\n } else if (_actions[i].dataFlow == DataFlow.Out) {\n actionPayload = abi.encodeWithSelector(\n IGelatoOutFlowAction.execWithDataFlowOut.selector,\n _actions[i].data\n );\n } else if (_actions[i].dataFlow == DataFlow.InAndOut) {\n actionPayload = abi.encodeWithSelector(\n IGelatoInAndOutFlowAction.execWithDataFlowInAndOut.selector,\n _actions[i].data,\n dataFromLastOutFlowAction\n );\n } else {\n actionPayload = _actions[i].data;\n }\n\n bool success;\n bytes memory returndata;\n if (_actions[i].operation == Operation.Call){\n (success, returndata) = _actions[i].addr.call{value: _actions[i].value}(\n actionPayload\n );\n } else {\n (success, returndata) = _actions[i].addr.delegatecall(actionPayload);\n }\n\n if (!success)\n returndata.revertWithErrorString(\"GelatoActionPipeline.execActionsAndPipeData:\");\n\n if (\n _actions[i].dataFlow == DataFlow.Out ||\n _actions[i].dataFlow == DataFlow.InAndOut\n ) {\n // All OutFlow actions return (bytes memory). But the low-level\n // delegatecall encoded those bytes into returndata.\n // So we have to decode them again to obtain the original bytes value.\n dataFromLastOutFlowAction = abi.decode(returndata, (bytes));\n }\n }\n }\n\n function isValid(Action[] calldata _actions)\n external\n pure\n returns (\n bool ok,\n uint256 outActionIndex,\n uint256 inActionIndex,\n bytes32 currentOutflowType,\n bytes32 nextInflowType\n )\n {\n ok = true;\n for (uint256 i = 0; i < _actions.length; i++) {\n if (_actions[i].dataFlow == DataFlow.In || _actions[i].dataFlow == DataFlow.InAndOut) {\n // Make sure currentOutflowType matches what the inFlowAction expects\n try IGelatoInFlowAction(_actions[i].addr).DATA_FLOW_IN_TYPE()\n returns (bytes32 inFlowType)\n {\n if (inFlowType != currentOutflowType) {\n nextInflowType = inFlowType;\n inActionIndex = i;\n ok = false;\n break;\n } else {\n ok = true;\n }\n } catch {\n revert(\"GelatoActionPipeline.isValid: error DATA_FLOW_IN_TYPE\");\n }\n }\n if (_actions[i].dataFlow == DataFlow.Out || _actions[i].dataFlow == DataFlow.InAndOut) {\n if (ok == false) break;\n // Store this Actions outFlowType to be used by the next inFlowAction\n try IGelatoOutFlowAction(_actions[i].addr).DATA_FLOW_OUT_TYPE()\n returns (bytes32 outFlowType)\n {\n currentOutflowType = outFlowType;\n outActionIndex = i;\n ok = false;\n } catch {\n revert(\"GelatoActionPipeline.isValid: error DATA_FLOW_OUT_TYPE\");\n }\n }\n }\n }\n}"
},
"contracts/user_proxies/gnosis_safe_proxy/interfaces/IGnosisSafe.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\ninterface IGnosisSafe {\n enum Operation {Call, DelegateCall}\n\n event ExecutionFailure(bytes32 txHash, uint256 payment);\n event ExecutionSuccess(bytes32 txHash, uint256 payment);\n\n function setup(\n address[] calldata _owners,\n uint256 _threshold,\n address to,\n bytes calldata data,\n address fallbackHandler,\n address paymentToken,\n uint256 payment,\n address payable paymentReceiver\n ) external;\n\n function execTransaction(\n address to,\n uint256 value,\n bytes calldata data,\n Operation operation,\n uint256 safeTxGas,\n uint256 baseGas,\n uint256 gasPrice,\n address gasToken,\n address payable refundReceiver,\n bytes calldata signatures\n ) external returns (bool success);\n\n function enableModule(address module) external;\n function disableModule(address prevModule, address module) external;\n\n function execTransactionFromModuleReturnData(\n address to,\n uint256 value,\n bytes calldata data,\n Operation operation\n ) external returns (bool success, bytes memory returndata);\n\n function isOwner(address owner) external view returns (bool);\n function getOwners() external view returns (address[] memory);\n\n function getModules() external view returns (address[] memory);\n}\n"
},
"contracts/user_proxies/gnosis_safe_proxy/interfaces/IGnosisSafeProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\ninterface IGnosisSafeProxy {\n function masterCopy() external view returns (address);\n}"
},
"contracts/gelato_actions/action_pipeline_interfaces/IGelatoInFlowAction.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/// @title IGelatoInFlowAction\n/// @notice Solidity interface for Actions that make use of DataFlow.In\n/// @dev Inherit this, if you want your Action to use DataFlow.In in a standard way.\ninterface IGelatoInFlowAction {\n /// @notice Executes the action implementation with data flowing in from a previous\n /// Action in the sequence.\n /// @dev The _inFlowData format should be defined by DATA_FLOW_IN_TYPE\n /// @param _actionData Known prior to execution and probably encoded off-chain.\n /// @param _inFlowData Not known prior to execution. Passed in via GelatoActionPipeline.\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable;\n\n /// @notice Returns the expected format of the execWithDataFlowIn _inFlowData.\n /// @dev Strict adherence to these formats is crucial for GelatoActionPipelines.\n function DATA_FLOW_IN_TYPE() external pure returns (bytes32);\n}\n"
},
"contracts/gelato_actions/action_pipeline_interfaces/IGelatoOutFlowAction.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/// @title IGelatoOutFlowAction\n/// @notice Solidity interface for Actions that make use of DataFlow.Out\n/// @dev Inherit this, if you want implement your Action.DataFlow.Out in a standard way.\ninterface IGelatoOutFlowAction {\n /// @notice Executes the Action implementation with data flowing out to consecutive\n /// Actions in a GelatoActionPipeline.\n /// @dev The outFlowData format should be defined by DATA_FLOW_OUT_TYPE\n /// @param _actionData Known prior to execution and probably encoded off-chain.\n /// @return outFlowData The bytes encoded data this action implementation emits.\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n returns (bytes memory outFlowData);\n\n /// @notice Returns the expected format of the execWithDataFlowOut outFlowData.\n /// @dev Strict adherence to these formats is crucial for GelatoActionPipelines.\n function DATA_FLOW_OUT_TYPE() external pure returns (bytes32);\n}\n"
},
"contracts/gelato_actions/action_pipeline_interfaces/IGelatoInAndOutFlowAction.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {Action} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\n/// @title IGelatoInAndOutFlowAction\n/// @notice Solidity interface for Actions that make use of DataFlow.InAndOut\ninterface IGelatoInAndOutFlowAction {\n\n /// @notice Executes the Action implementation with data flowing in from a previous\n /// Action in the GelatoActionPipeline and with data flowing out to consecutive\n /// Actions in the pipeline.\n /// @dev The _inFlowData format should be defined by DATA_FLOW_IN_TYPE and\n /// the outFlowData format should be defined by DATA_FLOW_OUT_TYPE.\n /// @param _actionData Known prior to execution and probably encoded off-chain.\n /// @param _inFlowData Not known prior to execution. Passed in via GelatoActionPipeline.\n /// @return outFlowData The bytes encoded data this action implementation emits.\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n returns (bytes memory outFlowData);\n\n /// @notice Returns the expected format of the execWithDataFlowIn _inFlowData.\n /// @dev Strict adherence to these formats is crucial for GelatoActionPipelines.\n function DATA_FLOW_IN_TYPE() external pure returns (bytes32);\n\n /// @notice Returns the expected format of the execWithDataFlowOut outFlowData.\n /// @dev Strict adherence to these formats is crucial for GelatoActionPipelines.\n function DATA_FLOW_OUT_TYPE() external pure returns (bytes32);\n}"
},
"contracts/user_proxies/gnosis_safe_proxy/interfaces/IGnosisSafeProxyFactory.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"./IGnosisSafe.sol\";\n\ninterface IGnosisSafeProxyFactory {\n\n event ProxyCreation(address proxy);\n\n /// @dev Allows to create new proxy contact and exec a message call to the\n /// new proxy within one transaction. Emits ProxyCreation.\n /// @param masterCopy Address of master copy.\n /// @param data Payload for message call sent to new proxy contract.\n /// @return proxy address\n function createProxy(address masterCopy, bytes calldata data)\n external\n returns (IGnosisSafe proxy);\n\n /// @dev Allows to create new proxy contact and exec a message call to the\n /// new proxy within one transaction. Emits ProxyCreation.\n /// @param _mastercopy Address of master copy.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate the\n /// address of the new proxy contract.\n /// @return proxy address\n function createProxyWithNonce(\n address _mastercopy,\n bytes calldata initializer,\n uint256 saltNonce\n )\n external\n returns (IGnosisSafe proxy);\n\n /// @dev Allows to create new proxy contact, exec a message call to the\n // new proxy and call a specified callback within one transaction\n /// @param _mastercopy Address of master copy.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate\n /// the address of the new proxy contract.\n /// @param callback Callback that will be invoced after the new proxy contract\n /// has been successfully deployed and initialized.\n function createProxyWithCallback(\n address _mastercopy,\n bytes calldata initializer,\n uint256 saltNonce,\n IProxyCreationCallback callback\n )\n external\n returns (IGnosisSafe proxy);\n\n /// @dev Allows to get the address for a new proxy contact created via `createProxyWithNonce`\n /// This method is only meant for address calculation purpose when you use an\n /// initializer that would revert, therefore the response is returned with a revert.\n /// When calling this method set `from` to the address of the proxy factory.\n /// @param _mastercopy Address of master copy.\n /// @param initializer Payload for message call sent to new proxy contract.\n /// @param saltNonce Nonce that will be used to generate the salt to calculate the\n /// address of the new proxy contract.\n /// @return proxy address from a revert() reason string message\n function calculateCreateProxyWithNonceAddress(\n address _mastercopy,\n bytes calldata initializer,\n uint256 saltNonce\n )\n external\n returns (address proxy);\n\n /// @dev Allows to retrieve the runtime code of a deployed Proxy.\n /// This can be used to check that the expected Proxy was deployed.\n /// @return proxysRuntimeBytecode bytes\n function proxyRuntimeCode() external pure returns (bytes memory);\n\n /// @dev Allows to retrieve the creation code used for the Proxy deployment.\n /// With this it is easily possible to calculate predicted address.\n /// @return proxysCreationCode bytes\n function proxyCreationCode() external pure returns (bytes memory);\n\n}\n\ninterface IProxyCreationCallback {\n function proxyCreated(\n address proxy,\n address _mastercopy,\n bytes calldata initializer,\n uint256 saltNonce\n )\n external;\n}"
},
"contracts/gelato_provider_modules/gelato_user_proxy_provider/ProviderModuleGelatoUserProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoProviderModuleStandard} from \"../GelatoProviderModuleStandard.sol\";\nimport {\n Action, Operation, DataFlow, Task\n} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {\n IGelatoUserProxyFactory\n} from \"../../user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxyFactory.sol\";\nimport {\n IGelatoUserProxy\n} from \"../../user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxy.sol\";\nimport {GelatoActionPipeline} from \"../../gelato_actions/GelatoActionPipeline.sol\";\n\ncontract ProviderModuleGelatoUserProxy is GelatoProviderModuleStandard {\n\n IGelatoUserProxyFactory public immutable gelatoUserProxyFactory;\n address public immutable gelatoActionPipeline;\n\n constructor(\n IGelatoUserProxyFactory _gelatoUserProxyFactory,\n address _gelatoActionPipeline\n )\n public\n {\n gelatoUserProxyFactory = _gelatoUserProxyFactory;\n gelatoActionPipeline = _gelatoActionPipeline;\n }\n\n // ================= GELATO PROVIDER MODULE STANDARD ================\n function isProvided(address _userProxy, address, Task calldata)\n external\n view\n override\n returns(string memory)\n {\n bool proxyOk = gelatoUserProxyFactory.isGelatoUserProxy(_userProxy);\n if (!proxyOk) return \"ProviderModuleGelatoUserProxy.isProvided:InvalidUserProxy\";\n return OK;\n }\n\n function execPayload(uint256, address, address, Task calldata _task, uint256)\n external\n view\n override\n returns(bytes memory payload, bool) // bool==false: no execRevertCheck\n {\n if (_task.actions.length > 1) {\n bytes memory gelatoActionPipelinePayload = abi.encodeWithSelector(\n GelatoActionPipeline.execActionsAndPipeData.selector,\n _task.actions\n );\n Action memory pipelinedActions = Action({\n addr: gelatoActionPipeline,\n data: gelatoActionPipelinePayload,\n operation: Operation.Delegatecall,\n dataFlow: DataFlow.None,\n value: 0,\n termsOkCheck: false\n });\n payload = abi.encodeWithSelector(\n IGelatoUserProxy.execAction.selector,\n pipelinedActions\n );\n } else if (_task.actions.length == 1) {\n payload = abi.encodeWithSelector(\n IGelatoUserProxy.execAction.selector,\n _task.actions[0]\n );\n } else {\n revert(\"ProviderModuleGelatoUserProxy.execPayload: 0 _task.actions length\");\n }\n }\n}"
},
"contracts/mocks/provider_modules/gelato_user_proxy_provider/MockProviderModuleGelatoUserProxyExecRevertCheckRevert.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {\n GelatoProviderModuleStandard\n} from \"../../../gelato_provider_modules/GelatoProviderModuleStandard.sol\";\nimport {Task} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {\n IGelatoUserProxy\n} from \"../../../user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxy.sol\";\n\ncontract MockProviderModuleGelatoUserProxyExecRevertCheckRevert is\n GelatoProviderModuleStandard\n{\n // Incorrect execPayload func on purpose\n function execPayload(uint256, address, address, Task calldata _task, uint256)\n external\n view\n virtual\n override\n returns(bytes memory payload, bool execRevertCheck)\n {\n if (_task.actions.length > 1) {\n payload = abi.encodeWithSelector(\n IGelatoUserProxy.multiExecActions.selector,\n _task.actions\n );\n } else if (_task.actions.length == 1) {\n payload = abi.encodeWithSelector(\n IGelatoUserProxy.execAction.selector,\n _task.actions[0]\n );\n } else {\n revert(\"ProviderModuleGelatoUserProxy.execPayload: 0 _actions length\");\n }\n execRevertCheck = true;\n }\n\n function execRevertCheck(bytes memory)\n public\n pure\n virtual\n override\n {\n revert(\"MockProviderModuleGelatoUserProxyExecRevertCheck.execRevertCheck\");\n }\n}"
},
"contracts/mocks/provider_modules/gelato_user_proxy_provider/MockProviderModuleGelatoUserProxyExecRevertCheckError.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {\n GelatoProviderModuleStandard\n} from \"../../../gelato_provider_modules/GelatoProviderModuleStandard.sol\";\nimport {Task} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {\n IGelatoUserProxy\n} from \"../../../user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxy.sol\";\n\ncontract MockProviderModuleGelatoUserProxyExecRevertCheckError is\n GelatoProviderModuleStandard\n{\n\n // Incorrect execPayload func on purpose\n function execPayload(uint256, address, address, Task calldata _task, uint256)\n external\n view\n virtual\n override\n returns(bytes memory payload, bool execRevertCheck)\n {\n if (_task.actions.length > 1) {\n payload = abi.encodeWithSelector(\n IGelatoUserProxy.multiExecActions.selector,\n _task.actions\n );\n } else if (_task.actions.length == 1) {\n payload = abi.encodeWithSelector(\n IGelatoUserProxy.execAction.selector,\n _task.actions[0]\n );\n } else {\n revert(\"ProviderModuleGelatoUserProxy.execPayload: 0 _actions length\");\n }\n execRevertCheck = true;\n }\n\n function execRevertCheck(bytes memory)\n public\n pure\n virtual\n override\n {\n assert(false);\n }\n}"
},
"contracts/mocks/provider_modules/gelato_user_proxy_provider/MockProviderModuleExecPayloadWrong.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {\n GelatoProviderModuleStandard\n} from \"../../../gelato_provider_modules/GelatoProviderModuleStandard.sol\";\nimport {Task} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract MockProviderModuleExecPayloadWrong is GelatoProviderModuleStandard {\n // Incorrect execPayload func on purpose\n function execPayload(uint256, address, address, Task calldata, uint256)\n external\n view\n override\n returns(bytes memory, bool)\n {\n return (abi.encodeWithSelector(this.bogus.selector), false);\n }\n\n function bogus() external {}\n}"
},
"contracts/mocks/provider_modules/gelato_user_proxy_provider/MockProviderModuleExecPayloadRevert.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {\n GelatoProviderModuleStandard\n} from \"../../../gelato_provider_modules/GelatoProviderModuleStandard.sol\";\nimport {Task} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract MockProviderModuleExecPayloadRevert is GelatoProviderModuleStandard {\n // Incorrect execPayload func on purpose\n function execPayload(uint256, address, address, Task calldata, uint256)\n external\n view\n override\n returns(bytes memory, bool)\n {\n revert(\"MockProviderModuleExecPayloadRevert.execPayload: test revert\");\n }\n}"
},
"contracts/mocks/gelato_actions/one-off/MockActionMaliciousProvider.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoActionsStandard} from \"../../../gelato_actions/GelatoActionsStandard.sol\";\nimport {IGelatoAction} from \"../../../gelato_actions/IGelatoAction.sol\";\nimport {\n IGelatoProviders,\n TaskSpec\n} from \"../../../gelato_core/interfaces/IGelatoProviders.sol\";\nimport {IGelatoProviderModule} from \"../../../gelato_provider_modules/IGelatoProviderModule.sol\";\n\n// This Action is the Provider and must be called from any UserProxy with .call a\ncontract MockActionMaliciousProvider {\n IGelatoProviders immutable gelato;\n\n constructor(IGelatoProviders _gelato) public { gelato = _gelato; }\n\n receive() external payable {}\n\n function action() public payable virtual {\n uint256 providerFunds = gelato.providerFunds(address(this));\n try gelato.unprovideFunds(providerFunds) {\n } catch Error(string memory err) {\n revert(\n string(\n abi.encodePacked(\"MockActionMaliciousProvider.action.unprovideFunds:\", err)\n )\n );\n } catch {\n revert(\"MockActionMaliciousProvider.action.unprovideFunds:undefinded\");\n }\n }\n\n function multiProvide(\n address _executor,\n TaskSpec[] calldata _taskSpecs,\n IGelatoProviderModule[] calldata _modules\n )\n external\n payable\n {\n try gelato.multiProvide{value: msg.value}(_executor, _taskSpecs, _modules) {\n } catch Error(string memory err) {\n revert(\n string(abi.encodePacked(\"MockActionMaliciousProvider.multiProvide:\", err))\n );\n } catch {\n revert(\"MockActionMaliciousProvider.multiProvide:undefinded\");\n }\n }\n}\n"
},
"contracts/gelato_actions/GelatoActionsStandard.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {IGelatoAction} from \"./IGelatoAction.sol\";\nimport {DataFlow} from \"../gelato_core/interfaces/IGelatoCore.sol\";\n\n/// @title GelatoActionsStandard\n/// @dev find all the NatSpecs inside IGelatoAction\nabstract contract GelatoActionsStandard is IGelatoAction {\n\n string internal constant OK = \"OK\";\n address internal constant ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;\n\n address public immutable thisActionAddress;\n\n constructor() public { thisActionAddress = address(this); }\n\n modifier delegatecallOnly(string memory _tracingInfo) {\n require(\n thisActionAddress != address(this),\n string(abi.encodePacked(_tracingInfo, \":delegatecallOnly\"))\n );\n _;\n }\n\n function termsOk(\n uint256, // _taskReceiptId\n address, // _userProxy\n bytes calldata, // _actionData\n DataFlow,\n uint256, // _value: for actions that send ETH around\n uint256 // cycleId\n )\n external\n view\n virtual\n override\n returns(string memory) // actionTermsOk\n {\n // Standard return value for actionConditions fulfilled and no erros:\n return OK;\n }\n}\n"
},
"contracts/gelato_actions/IGelatoAction.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {DataFlow} from \"../gelato_core/interfaces/IGelatoCore.sol\";\n\n/// @title IGelatoAction - solidity interface of GelatoActionsStandard\n/// @notice all the APIs and events of GelatoActionsStandard\n/// @dev all the APIs are implemented inside GelatoActionsStandard\ninterface IGelatoAction {\n event LogOneWay(\n address origin,\n address sendToken,\n uint256 sendAmount,\n address destination\n );\n\n event LogTwoWay(\n address origin,\n address sendToken,\n uint256 sendAmount,\n address destination,\n address receiveToken,\n uint256 receiveAmount,\n address receiver\n );\n\n /// @notice Providers can use this for pre-execution sanity checks, to prevent reverts.\n /// @dev GelatoCore checks this in canExec and passes the parameters.\n /// @param _taskReceiptId The id of the task from which all arguments are passed.\n /// @param _userProxy The userProxy of the task. Often address(this) for delegatecalls.\n /// @param _actionData The encoded payload to be used in the Action.\n /// @param _dataFlow The dataFlow of the Action.\n /// @param _value A special param for ETH sending Actions. If the Action sends ETH\n /// in its Action function implementation, one should expect msg.value therein to be\n /// equal to _value. So Providers can check in termsOk that a valid ETH value will\n /// be used because they also have access to the same value when encoding the\n /// execPayload on their ProviderModule.\n /// @param _cycleId For tasks that are part of a Cycle.\n /// @return Returns OK, if Task can be executed safely according to the Provider's\n /// terms laid out in this function implementation.\n function termsOk(\n uint256 _taskReceiptId,\n address _userProxy,\n bytes calldata _actionData,\n DataFlow _dataFlow,\n uint256 _value,\n uint256 _cycleId\n )\n external\n view\n returns(string memory);\n}\n"
},
"contracts/gelato_core/interfaces/IGelatoProviders.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoProviderModule} from \"../../gelato_provider_modules/IGelatoProviderModule.sol\";\nimport {Action, Provider, Task, TaskReceipt} from \"../interfaces/IGelatoCore.sol\";\nimport {IGelatoCondition} from \"../../gelato_conditions/IGelatoCondition.sol\";\n\n// TaskSpec - Will be whitelised by providers and selected by users\nstruct TaskSpec {\n IGelatoCondition[] conditions; // Address: optional AddressZero for self-conditional actions\n Action[] actions;\n uint256 gasPriceCeil;\n}\n\ninterface IGelatoProviders {\n // Provider Funding\n event LogFundsProvided(\n address indexed provider,\n uint256 amount,\n uint256 newProviderFunds\n );\n event LogFundsUnprovided(\n address indexed provider,\n uint256 realWithdrawAmount,\n uint256 newProviderFunds\n );\n\n // Executor By Provider\n event LogProviderAssignedExecutor(\n address indexed provider,\n address indexed oldExecutor,\n address indexed newExecutor\n );\n event LogExecutorAssignedExecutor(\n address indexed provider,\n address indexed oldExecutor,\n address indexed newExecutor\n );\n\n // Actions\n event LogTaskSpecProvided(address indexed provider, bytes32 indexed taskSpecHash);\n event LogTaskSpecUnprovided(address indexed provider, bytes32 indexed taskSpecHash);\n event LogTaskSpecGasPriceCeilSet(\n address indexed provider,\n bytes32 taskSpecHash,\n uint256 oldTaskSpecGasPriceCeil,\n uint256 newTaskSpecGasPriceCeil\n );\n\n // Provider Module\n event LogProviderModuleAdded(\n address indexed provider,\n IGelatoProviderModule indexed module\n );\n event LogProviderModuleRemoved(\n address indexed provider,\n IGelatoProviderModule indexed module\n );\n\n // =========== GELATO PROVIDER APIs ==============\n\n /// @notice Validation that checks whether Task Spec is being offered by the selected provider\n /// @dev Checked in submitTask(), unless provider == userProxy\n /// @param _provider Address of selected provider\n /// @param _taskSpec Task Spec\n /// @return Expected to return \"OK\"\n function isTaskSpecProvided(address _provider, TaskSpec calldata _taskSpec)\n external\n view\n returns(string memory);\n\n /// @notice Validates that provider has provider module whitelisted + conducts isProvided check in ProviderModule\n /// @dev Checked in submitTask() if provider == userProxy\n /// @param _userProxy userProxy passed by GelatoCore during submission and exec\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _task Task defined in IGelatoCore\n /// @return Expected to return \"OK\"\n function providerModuleChecks(\n address _userProxy,\n Provider calldata _provider,\n Task calldata _task\n )\n external\n view\n returns(string memory);\n\n\n /// @notice Validate if provider module and seleced TaskSpec is whitelisted by provider\n /// @dev Combines \"isTaskSpecProvided\" and providerModuleChecks\n /// @param _userProxy userProxy passed by GelatoCore during submission and exec\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _task Task defined in IGelatoCore\n /// @return res Expected to return \"OK\"\n function isTaskProvided(\n address _userProxy,\n Provider calldata _provider,\n Task calldata _task\n )\n external\n view\n returns(string memory res);\n\n\n /// @notice Validate if selected TaskSpec is whitelisted by provider and that current gelatoGasPrice is below GasPriceCeil\n /// @dev If gasPriceCeil is != 0, Task Spec is whitelisted\n /// @param _userProxy userProxy passed by GelatoCore during submission and exec\n /// @param _provider Gelato Provider object: provider address and module.\n /// @param _task Task defined in IGelatoCore\n /// @param _gelatoGasPrice Task Receipt defined in IGelatoCore\n /// @return res Expected to return \"OK\"\n function providerCanExec(\n address _userProxy,\n Provider calldata _provider,\n Task calldata _task,\n uint256 _gelatoGasPrice\n )\n external\n view\n returns(string memory res);\n\n // =========== PROVIDER STATE WRITE APIs ==============\n // Provider Funding\n /// @notice Deposit ETH as provider on Gelato\n /// @param _provider Address of provider who receives ETH deposit\n function provideFunds(address _provider) external payable;\n\n /// @notice Withdraw provider funds from gelato\n /// @param _withdrawAmount Amount\n /// @return amount that will be withdrawn\n function unprovideFunds(uint256 _withdrawAmount) external returns(uint256);\n\n /// @notice Assign executor as provider\n /// @param _executor Address of new executor\n function providerAssignsExecutor(address _executor) external;\n\n /// @notice Assign executor as previous selected executor\n /// @param _provider Address of provider whose executor to change\n /// @param _newExecutor Address of new executor\n function executorAssignsExecutor(address _provider, address _newExecutor) external;\n\n // (Un-)provide Task Spec\n\n /// @notice Whitelist TaskSpecs (A combination of a Condition, Action(s) and a gasPriceCeil) that users can select from\n /// @dev If gasPriceCeil is == 0, Task Spec will be executed at any gas price (no ceil)\n /// @param _taskSpecs Task Receipt List defined in IGelatoCore\n function provideTaskSpecs(TaskSpec[] calldata _taskSpecs) external;\n\n /// @notice De-whitelist TaskSpecs (A combination of a Condition, Action(s) and a gasPriceCeil) that users can select from\n /// @dev If gasPriceCeil was set to NO_CEIL, Input NO_CEIL constant as GasPriceCeil\n /// @param _taskSpecs Task Receipt List defined in IGelatoCore\n function unprovideTaskSpecs(TaskSpec[] calldata _taskSpecs) external;\n\n /// @notice Update gasPriceCeil of selected Task Spec\n /// @param _taskSpecHash Result of hashTaskSpec()\n /// @param _gasPriceCeil New gas price ceil for Task Spec\n function setTaskSpecGasPriceCeil(bytes32 _taskSpecHash, uint256 _gasPriceCeil) external;\n\n // Provider Module\n /// @notice Whitelist new provider Module(s)\n /// @param _modules Addresses of the modules which will be called during providerModuleChecks()\n function addProviderModules(IGelatoProviderModule[] calldata _modules) external;\n\n /// @notice De-Whitelist new provider Module(s)\n /// @param _modules Addresses of the modules which will be removed\n function removeProviderModules(IGelatoProviderModule[] calldata _modules) external;\n\n // Batch (un-)provide\n\n /// @notice Whitelist new executor, TaskSpec(s) and Module(s) in one tx\n /// @param _executor Address of new executor of provider\n /// @param _taskSpecs List of Task Spec which will be whitelisted by provider\n /// @param _modules List of module addresses which will be whitelisted by provider\n function multiProvide(\n address _executor,\n TaskSpec[] calldata _taskSpecs,\n IGelatoProviderModule[] calldata _modules\n )\n external\n payable;\n\n\n /// @notice De-Whitelist TaskSpec(s), Module(s) and withdraw funds from gelato in one tx\n /// @param _withdrawAmount Amount to withdraw from ProviderFunds\n /// @param _taskSpecs List of Task Spec which will be de-whitelisted by provider\n /// @param _modules List of module addresses which will be de-whitelisted by provider\n function multiUnprovide(\n uint256 _withdrawAmount,\n TaskSpec[] calldata _taskSpecs,\n IGelatoProviderModule[] calldata _modules\n )\n external;\n\n // =========== PROVIDER STATE READ APIs ==============\n // Provider Funding\n\n /// @notice Get balance of provider\n /// @param _provider Address of provider\n /// @return Provider Balance\n function providerFunds(address _provider) external view returns(uint256);\n\n /// @notice Get min stake required by all providers for executors to call exec\n /// @param _gelatoMaxGas Current gelatoMaxGas\n /// @param _gelatoGasPrice Current gelatoGasPrice\n /// @return How much provider balance is required for executor to submit exec tx\n function minExecProviderFunds(uint256 _gelatoMaxGas, uint256 _gelatoGasPrice)\n external\n view\n returns(uint256);\n\n /// @notice Check if provider has sufficient funds for executor to call exec\n /// @param _provider Address of provider\n /// @param _gelatoMaxGas Currentt gelatoMaxGas\n /// @param _gelatoGasPrice Current gelatoGasPrice\n /// @return Whether provider is liquid (true) or not (false)\n function isProviderLiquid(\n address _provider,\n uint256 _gelatoMaxGas,\n uint256 _gelatoGasPrice\n )\n external\n view\n returns(bool);\n\n // Executor Stake\n\n /// @notice Get balance of executor\n /// @param _executor Address of executor\n /// @return Executor Balance\n function executorStake(address _executor) external view returns(uint256);\n\n /// @notice Check if executor has sufficient stake on gelato\n /// @param _executor Address of provider\n /// @return Whether executor has sufficient stake (true) or not (false)\n function isExecutorMinStaked(address _executor) external view returns(bool);\n\n /// @notice Get executor of provider\n /// @param _provider Address of provider\n /// @return Provider's executor\n function executorByProvider(address _provider)\n external\n view\n returns(address);\n\n /// @notice Get num. of providers which haved assigned an executor\n /// @param _executor Address of executor\n /// @return Count of how many providers assigned the executor\n function executorProvidersCount(address _executor) external view returns(uint256);\n\n /// @notice Check if executor has one or more providers assigned\n /// @param _executor Address of provider\n /// @return Where 1 or more providers have assigned the executor\n function isExecutorAssigned(address _executor) external view returns(bool);\n\n // Task Spec and Gas Price Ceil\n /// @notice The maximum gas price the transaction will be executed with\n /// @param _provider Address of provider\n /// @param _taskSpecHash Hash of provider TaskSpec\n /// @return Max gas price an executor will execute the transaction with in wei\n function taskSpecGasPriceCeil(address _provider, bytes32 _taskSpecHash)\n external\n view\n returns(uint256);\n\n /// @notice Returns the hash of the formatted TaskSpec.\n /// @dev The action.data field of each Action is stripped before hashing.\n /// @param _taskSpec TaskSpec\n /// @return keccak256 hash of encoded condition address and Action List\n function hashTaskSpec(TaskSpec calldata _taskSpec) external view returns(bytes32);\n\n /// @notice Constant used to specify the highest gas price available in the gelato system\n /// @dev Input 0 as gasPriceCeil and it will be assigned to NO_CEIL\n /// @return MAX_UINT\n function NO_CEIL() external pure returns(uint256);\n\n // Providers' Module Getters\n\n /// @notice Check if inputted module is whitelisted by provider\n /// @param _provider Address of provider\n /// @param _module Address of module\n /// @return true if it is whitelisted\n function isModuleProvided(address _provider, IGelatoProviderModule _module)\n external\n view\n returns(bool);\n\n /// @notice Get all whitelisted provider modules from a given provider\n /// @param _provider Address of provider\n /// @return List of whitelisted provider modules\n function providerModules(address _provider)\n external\n view\n returns(IGelatoProviderModule[] memory);\n}\n"
},
"contracts/gelato_core/GelatoProviders.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoProviders, TaskSpec} from \"./interfaces/IGelatoProviders.sol\";\nimport {GelatoSysAdmin} from \"./GelatoSysAdmin.sol\";\nimport {Address} from \"../external/Address.sol\";\nimport {GelatoString} from \"../libraries/GelatoString.sol\";\nimport {Math} from \"../external/Math.sol\";\nimport {SafeMath} from \"../external/SafeMath.sol\";\nimport {IGelatoProviderModule} from \"../gelato_provider_modules/IGelatoProviderModule.sol\";\nimport {ProviderModuleSet} from \"../libraries/ProviderModuleSet.sol\";\nimport {\n Condition, Action, Operation, DataFlow, Provider, Task, TaskReceipt\n} from \"./interfaces/IGelatoCore.sol\";\nimport {IGelatoCondition} from \"../gelato_conditions/IGelatoCondition.sol\";\n\n/// @title GelatoProviders\n/// @notice Provider Management API - Whitelist TaskSpecs\n/// @dev Find all NatSpecs inside IGelatoProviders\nabstract contract GelatoProviders is IGelatoProviders, GelatoSysAdmin {\n\n using Address for address payable; /// for sendValue method\n using GelatoString for string;\n using ProviderModuleSet for ProviderModuleSet.Set;\n using SafeMath for uint256;\n\n // This is only for internal use by hashTaskSpec()\n struct NoDataAction {\n address addr;\n Operation operation;\n DataFlow dataFlow;\n bool value;\n bool termsOkCheck;\n }\n\n uint256 public constant override NO_CEIL = type(uint256).max;\n\n mapping(address => uint256) public override providerFunds;\n mapping(address => uint256) public override executorStake;\n mapping(address => address) public override executorByProvider;\n mapping(address => uint256) public override executorProvidersCount;\n // The Task-Spec Gas-Price-Ceil => taskSpecGasPriceCeil\n mapping(address => mapping(bytes32 => uint256)) public override taskSpecGasPriceCeil;\n mapping(address => ProviderModuleSet.Set) internal _providerModules;\n\n // GelatoCore: canSubmit\n function isTaskSpecProvided(address _provider, TaskSpec memory _taskSpec)\n public\n view\n override\n returns(string memory)\n {\n if (taskSpecGasPriceCeil[_provider][hashTaskSpec(_taskSpec)] == 0)\n return \"TaskSpecNotProvided\";\n return OK;\n }\n\n // IGelatoProviderModule: GelatoCore canSubmit & canExec\n function providerModuleChecks(\n address _userProxy,\n Provider memory _provider,\n Task memory _task\n )\n public\n view\n override\n returns(string memory)\n {\n if (!isModuleProvided(_provider.addr, _provider.module))\n return \"InvalidProviderModule\";\n\n if (_userProxy != _provider.addr) {\n IGelatoProviderModule providerModule = IGelatoProviderModule(\n _provider.module\n );\n\n try providerModule.isProvided(_userProxy, _provider.addr, _task)\n returns(string memory res)\n {\n return res;\n } catch {\n return \"GelatoProviders.providerModuleChecks\";\n }\n } else return OK;\n }\n\n // GelatoCore: canSubmit\n function isTaskProvided(\n address _userProxy,\n Provider memory _provider,\n Task memory _task\n )\n public\n view\n override\n returns(string memory res)\n {\n TaskSpec memory _taskSpec = _castTaskToSpec(_task);\n res = isTaskSpecProvided(_provider.addr, _taskSpec);\n if (res.startsWithOK())\n return providerModuleChecks(_userProxy, _provider, _task);\n }\n\n // GelatoCore canExec Gate\n function providerCanExec(\n address _userProxy,\n Provider memory _provider,\n Task memory _task,\n uint256 _gelatoGasPrice\n )\n public\n view\n override\n returns(string memory)\n {\n if (_userProxy == _provider.addr) {\n if (_task.selfProviderGasPriceCeil < _gelatoGasPrice)\n return \"SelfProviderGasPriceCeil\";\n } else {\n bytes32 taskSpecHash = hashTaskSpec(_castTaskToSpec(_task));\n if (taskSpecGasPriceCeil[_provider.addr][taskSpecHash] < _gelatoGasPrice)\n return \"taskSpecGasPriceCeil-OR-notProvided\";\n }\n return providerModuleChecks(_userProxy, _provider, _task);\n }\n\n // Provider Funding\n function provideFunds(address _provider) public payable override {\n require(msg.value > 0, \"GelatoProviders.provideFunds: zero value\");\n uint256 newProviderFunds = providerFunds[_provider].add(msg.value);\n emit LogFundsProvided(_provider, msg.value, newProviderFunds);\n providerFunds[_provider] = newProviderFunds;\n }\n\n // Unprovide funds\n function unprovideFunds(uint256 _withdrawAmount)\n public\n override\n returns(uint256 realWithdrawAmount)\n {\n uint256 previousProviderFunds = providerFunds[msg.sender];\n realWithdrawAmount = Math.min(_withdrawAmount, previousProviderFunds);\n\n uint256 newProviderFunds = previousProviderFunds - realWithdrawAmount;\n\n // Effects\n providerFunds[msg.sender] = newProviderFunds;\n\n // Interaction\n msg.sender.sendValue(realWithdrawAmount);\n\n emit LogFundsUnprovided(msg.sender, realWithdrawAmount, newProviderFunds);\n }\n\n // Called by Providers\n function providerAssignsExecutor(address _newExecutor) public override {\n address currentExecutor = executorByProvider[msg.sender];\n\n // CHECKS\n require(\n currentExecutor != _newExecutor,\n \"GelatoProviders.providerAssignsExecutor: already assigned.\"\n );\n if (_newExecutor != address(0)) {\n require(\n isExecutorMinStaked(_newExecutor),\n \"GelatoProviders.providerAssignsExecutor: isExecutorMinStaked()\"\n );\n }\n\n // EFFECTS: Provider reassigns from currentExecutor to newExecutor (or no executor)\n if (currentExecutor != address(0)) executorProvidersCount[currentExecutor]--;\n executorByProvider[msg.sender] = _newExecutor;\n if (_newExecutor != address(0)) executorProvidersCount[_newExecutor]++;\n\n emit LogProviderAssignedExecutor(msg.sender, currentExecutor, _newExecutor);\n }\n\n // Called by Executors\n function executorAssignsExecutor(address _provider, address _newExecutor) public override {\n address currentExecutor = executorByProvider[_provider];\n\n // CHECKS\n require(\n currentExecutor == msg.sender,\n \"GelatoProviders.executorAssignsExecutor: msg.sender is not assigned executor\"\n );\n require(\n currentExecutor != _newExecutor,\n \"GelatoProviders.executorAssignsExecutor: already assigned.\"\n );\n // Checks at the same time if _nexExecutor != address(0)\n require(\n isExecutorMinStaked(_newExecutor),\n \"GelatoProviders.executorAssignsExecutor: isExecutorMinStaked()\"\n );\n\n // EFFECTS: currentExecutor reassigns to newExecutor\n executorProvidersCount[currentExecutor]--;\n executorByProvider[_provider] = _newExecutor;\n executorProvidersCount[_newExecutor]++;\n\n emit LogExecutorAssignedExecutor(_provider, currentExecutor, _newExecutor);\n }\n\n // (Un-)provide Condition Action Combos at different Gas Price Ceils\n function provideTaskSpecs(TaskSpec[] memory _taskSpecs) public override {\n for (uint i; i < _taskSpecs.length; i++) {\n if (_taskSpecs[i].gasPriceCeil == 0) _taskSpecs[i].gasPriceCeil = NO_CEIL;\n bytes32 taskSpecHash = hashTaskSpec(_taskSpecs[i]);\n setTaskSpecGasPriceCeil(taskSpecHash, _taskSpecs[i].gasPriceCeil);\n emit LogTaskSpecProvided(msg.sender, taskSpecHash);\n }\n }\n\n function unprovideTaskSpecs(TaskSpec[] memory _taskSpecs) public override {\n for (uint i; i < _taskSpecs.length; i++) {\n bytes32 taskSpecHash = hashTaskSpec(_taskSpecs[i]);\n require(\n taskSpecGasPriceCeil[msg.sender][taskSpecHash] != 0,\n \"GelatoProviders.unprovideTaskSpecs: redundant\"\n );\n delete taskSpecGasPriceCeil[msg.sender][taskSpecHash];\n emit LogTaskSpecUnprovided(msg.sender, taskSpecHash);\n }\n }\n\n function setTaskSpecGasPriceCeil(bytes32 _taskSpecHash, uint256 _gasPriceCeil)\n public\n override\n {\n uint256 currentTaskSpecGasPriceCeil = taskSpecGasPriceCeil[msg.sender][_taskSpecHash];\n require(\n currentTaskSpecGasPriceCeil != _gasPriceCeil,\n \"GelatoProviders.setTaskSpecGasPriceCeil: Already whitelisted with gasPriceCeil\"\n );\n taskSpecGasPriceCeil[msg.sender][_taskSpecHash] = _gasPriceCeil;\n emit LogTaskSpecGasPriceCeilSet(\n msg.sender,\n _taskSpecHash,\n currentTaskSpecGasPriceCeil,\n _gasPriceCeil\n );\n }\n\n // Provider Module\n function addProviderModules(IGelatoProviderModule[] memory _modules) public override {\n for (uint i; i < _modules.length; i++) {\n require(\n !isModuleProvided(msg.sender, _modules[i]),\n \"GelatoProviders.addProviderModules: redundant\"\n );\n _providerModules[msg.sender].add(_modules[i]);\n emit LogProviderModuleAdded(msg.sender, _modules[i]);\n }\n }\n\n function removeProviderModules(IGelatoProviderModule[] memory _modules) public override {\n for (uint i; i < _modules.length; i++) {\n require(\n isModuleProvided(msg.sender, _modules[i]),\n \"GelatoProviders.removeProviderModules: redundant\"\n );\n _providerModules[msg.sender].remove(_modules[i]);\n emit LogProviderModuleRemoved(msg.sender, _modules[i]);\n }\n }\n\n // Batch (un-)provide\n function multiProvide(\n address _executor,\n TaskSpec[] memory _taskSpecs,\n IGelatoProviderModule[] memory _modules\n )\n public\n payable\n override\n {\n if (msg.value != 0) provideFunds(msg.sender);\n if (_executor != address(0)) providerAssignsExecutor(_executor);\n provideTaskSpecs(_taskSpecs);\n addProviderModules(_modules);\n }\n\n function multiUnprovide(\n uint256 _withdrawAmount,\n TaskSpec[] memory _taskSpecs,\n IGelatoProviderModule[] memory _modules\n )\n public\n override\n {\n if (_withdrawAmount != 0) unprovideFunds(_withdrawAmount);\n unprovideTaskSpecs(_taskSpecs);\n removeProviderModules(_modules);\n }\n\n // Provider Liquidity\n function minExecProviderFunds(uint256 _gelatoMaxGas, uint256 _gelatoGasPrice)\n public\n view\n override\n returns(uint256)\n {\n uint256 maxExecTxCost = (EXEC_TX_OVERHEAD + _gelatoMaxGas) * _gelatoGasPrice;\n return maxExecTxCost + (maxExecTxCost * totalSuccessShare) / 100;\n }\n\n function isProviderLiquid(\n address _provider,\n uint256 _gelatoMaxGas,\n uint256 _gelatoGasPrice\n )\n public\n view\n override\n returns(bool)\n {\n return minExecProviderFunds(_gelatoMaxGas, _gelatoGasPrice) <= providerFunds[_provider];\n }\n\n // An Executor qualifies and remains registered for as long as he has minExecutorStake\n function isExecutorMinStaked(address _executor) public view override returns(bool) {\n return executorStake[_executor] >= minExecutorStake;\n }\n\n // Providers' Executor Assignment\n function isExecutorAssigned(address _executor) public view override returns(bool) {\n return executorProvidersCount[_executor] != 0;\n }\n\n // Helper fn that can also be called to query taskSpecHash off-chain\n function hashTaskSpec(TaskSpec memory _taskSpec) public view override returns(bytes32) {\n NoDataAction[] memory noDataActions = new NoDataAction[](_taskSpec.actions.length);\n for (uint i = 0; i < _taskSpec.actions.length; i++) {\n NoDataAction memory noDataAction = NoDataAction({\n addr: _taskSpec.actions[i].addr,\n operation: _taskSpec.actions[i].operation,\n dataFlow: _taskSpec.actions[i].dataFlow,\n value: _taskSpec.actions[i].value == 0 ? false : true,\n termsOkCheck: _taskSpec.actions[i].termsOkCheck\n });\n noDataActions[i] = noDataAction;\n }\n return keccak256(abi.encode(_taskSpec.conditions, noDataActions));\n }\n\n // Providers' Module Getters\n function isModuleProvided(address _provider, IGelatoProviderModule _module)\n public\n view\n override\n returns(bool)\n {\n return _providerModules[_provider].contains(_module);\n }\n\n function providerModules(address _provider)\n external\n view\n override\n returns(IGelatoProviderModule[] memory)\n {\n return _providerModules[_provider].enumerate();\n }\n\n // Internal helper for is isTaskProvided() and providerCanExec\n function _castTaskToSpec(Task memory _task)\n private\n pure\n returns(TaskSpec memory taskSpec)\n {\n taskSpec = TaskSpec({\n conditions: _stripConditionData(_task.conditions),\n actions: _task.actions,\n gasPriceCeil: 0 // default: provider can set gasPriceCeil dynamically.\n });\n }\n\n function _stripConditionData(Condition[] memory _conditionsWithData)\n private\n pure\n returns(IGelatoCondition[] memory conditionInstances)\n {\n conditionInstances = new IGelatoCondition[](_conditionsWithData.length);\n for (uint i; i < _conditionsWithData.length; i++)\n conditionInstances[i] = _conditionsWithData[i].inst;\n }\n\n}\n"
},
"contracts/gelato_core/GelatoSysAdmin.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {IGelatoSysAdmin} from \"./interfaces/IGelatoSysAdmin.sol\";\nimport {Ownable} from \"../external/Ownable.sol\";\nimport {Address} from \"../external/Address.sol\";\nimport {GelatoBytes} from \"../libraries/GelatoBytes.sol\";\nimport {SafeMath} from \"../external/SafeMath.sol\";\nimport {Math} from \"../external/Math.sol\";\n\nabstract contract GelatoSysAdmin is IGelatoSysAdmin, Ownable {\n\n using Address for address payable;\n using GelatoBytes for bytes;\n using SafeMath for uint256;\n\n // Executor compensation for estimated tx costs not accounted for by startGas\n uint256 public constant override EXEC_TX_OVERHEAD = 55000;\n string internal constant OK = \"OK\";\n\n address public override gelatoGasPriceOracle;\n bytes public override oracleRequestData;\n uint256 public override gelatoMaxGas;\n uint256 public override internalGasRequirement;\n uint256 public override minExecutorStake;\n uint256 public override executorSuccessShare;\n uint256 public override sysAdminSuccessShare;\n uint256 public override totalSuccessShare;\n uint256 public override sysAdminFunds;\n\n // == The main functions of the Sys Admin (DAO) ==\n // The oracle defines the system-critical gelatoGasPrice\n function setGelatoGasPriceOracle(address _newOracle) external override onlyOwner {\n require(_newOracle != address(0), \"GelatoSysAdmin.setGelatoGasPriceOracle: 0\");\n emit LogGelatoGasPriceOracleSet(gelatoGasPriceOracle, _newOracle);\n gelatoGasPriceOracle = _newOracle;\n }\n\n function setOracleRequestData(bytes calldata _requestData) external override onlyOwner {\n emit LogOracleRequestDataSet(oracleRequestData, _requestData);\n oracleRequestData = _requestData;\n }\n\n // exec-tx gasprice: pulled in from the Oracle by the Executor during exec()\n function _getGelatoGasPrice() internal view returns(uint256) {\n (bool success, bytes memory returndata) = gelatoGasPriceOracle.staticcall(\n oracleRequestData\n );\n if (!success)\n returndata.revertWithErrorString(\"GelatoSysAdmin._getGelatoGasPrice:\");\n int oracleGasPrice = abi.decode(returndata, (int256));\n if (oracleGasPrice <= 0) revert(\"GelatoSysAdmin._getGelatoGasPrice:0orBelow\");\n return uint256(oracleGasPrice);\n }\n\n // exec-tx gas\n function setGelatoMaxGas(uint256 _newMaxGas) external override onlyOwner {\n emit LogGelatoMaxGasSet(gelatoMaxGas, _newMaxGas);\n gelatoMaxGas = _newMaxGas;\n }\n\n // exec-tx GelatoCore internal gas requirement\n function setInternalGasRequirement(uint256 _newRequirement) external override onlyOwner {\n emit LogInternalGasRequirementSet(internalGasRequirement, _newRequirement);\n internalGasRequirement = _newRequirement;\n }\n\n // Minimum Executor Stake Per Provider\n function setMinExecutorStake(uint256 _newMin) external override onlyOwner {\n emit LogMinExecutorStakeSet(minExecutorStake, _newMin);\n minExecutorStake = _newMin;\n }\n\n // Executors' profit share on exec costs\n function setExecutorSuccessShare(uint256 _percentage) external override onlyOwner {\n emit LogExecutorSuccessShareSet(\n executorSuccessShare,\n _percentage,\n _percentage + sysAdminSuccessShare\n );\n executorSuccessShare = _percentage;\n totalSuccessShare = _percentage + sysAdminSuccessShare;\n }\n\n // Sys Admin (DAO) Business Model\n function setSysAdminSuccessShare(uint256 _percentage) external override onlyOwner {\n emit LogSysAdminSuccessShareSet(\n sysAdminSuccessShare,\n _percentage,\n executorSuccessShare + _percentage\n );\n sysAdminSuccessShare = _percentage;\n totalSuccessShare = executorSuccessShare + _percentage;\n }\n\n function withdrawSysAdminFunds(uint256 _amount, address payable _to)\n external\n override\n onlyOwner\n returns(uint256 realWithdrawAmount)\n {\n uint256 currentBalance = sysAdminFunds;\n\n realWithdrawAmount = Math.min(_amount, currentBalance);\n\n uint256 newSysAdminFunds = currentBalance - realWithdrawAmount;\n\n // Effects\n sysAdminFunds = newSysAdminFunds;\n\n _to.sendValue(realWithdrawAmount);\n emit LogSysAdminFundsWithdrawn(currentBalance, newSysAdminFunds);\n }\n\n // Executors' total fee for a successful exec\n function executorSuccessFee(uint256 _gas, uint256 _gasPrice)\n public\n view\n override\n returns(uint256)\n {\n uint256 estExecCost = _gas.mul(_gasPrice);\n return estExecCost + estExecCost.mul(executorSuccessShare).div(\n 100,\n \"GelatoSysAdmin.executorSuccessFee: div error\"\n );\n }\n\n function sysAdminSuccessFee(uint256 _gas, uint256 _gasPrice)\n public\n view\n override\n returns(uint256)\n {\n uint256 estExecCost = _gas.mul(_gasPrice);\n return\n estExecCost.mul(sysAdminSuccessShare).div(\n 100,\n \"GelatoSysAdmin.sysAdminSuccessShare: div error\"\n );\n }\n}\n"
},
"contracts/libraries/GelatoString.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nlibrary GelatoString {\n function startsWithOK(string memory _str) internal pure returns(bool) {\n if (bytes(_str).length >= 2 && bytes(_str)[0] == \"O\" && bytes(_str)[1] == \"K\")\n return true;\n return false;\n }\n}"
},
"contracts/external/Math.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a >= b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow, so we distribute\n return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);\n }\n}"
},
"contracts/external/SafeMath.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations with added overflow\n * checks.\n *\n * Arithmetic operations in Solidity wrap on overflow. This can easily result\n * in bugs, because programmers usually assume that an overflow raises an\n * error, which is the standard behavior in high level programming languages.\n * `SafeMath` restores this intuition by reverting the transaction when an\n * operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n uint256 c = a + b;\n require(c >= a, \"SafeMath: addition overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return sub(a, b, \"SafeMath: subtraction overflow\");\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n * - Subtraction cannot overflow.\n *\n * _Available since v2.4.0._\n */\n function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b <= a, errorMessage);\n uint256 c = a - b;\n\n return c;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) {\n return 0;\n }\n\n uint256 c = a * b;\n require(c / a == b, \"SafeMath: multiplication overflow\");\n\n return c;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return div(a, b, \"SafeMath: division by zero\");\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers. Reverts with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n *\n * _Available since v2.4.0._\n */\n function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n // Solidity only automatically asserts when dividing by 0\n require(b > 0, errorMessage);\n uint256 c = a / b;\n // assert(a == b * c + a % b); // There is no case in which this doesn't hold\n\n return c;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return mod(a, b, \"SafeMath: modulo by zero\");\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * Reverts with custom message when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n * - The divisor cannot be zero.\n *\n * _Available since v2.4.0._\n */\n function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {\n require(b != 0, errorMessage);\n return a % b;\n }\n}"
},
"contracts/libraries/ProviderModuleSet.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {IGelatoProviderModule} from \"../gelato_provider_modules/IGelatoProviderModule.sol\";\n\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * As of v2.5.0, only `IGelatoProviderModule` sets are supported.\n *\n * Include with `using EnumerableSet for EnumerableSet.Set;`.\n *\n * _Available since v2.5.0._\n *\n * @author Alberto Cuesta Cañada\n * @author Luis Schliessske (modified to ProviderModuleSet)\n */\nlibrary ProviderModuleSet {\n\n struct Set {\n // Position of the module in the `modules` array, plus 1 because index 0\n // means a module is not in the set.\n mapping (IGelatoProviderModule => uint256) index;\n IGelatoProviderModule[] modules;\n }\n\n /**\n * @dev Add a module to a set. O(1).\n * Returns false if the module was already in the set.\n */\n function add(Set storage set, IGelatoProviderModule module)\n internal\n returns (bool)\n {\n if (!contains(set, module)) {\n set.modules.push(module);\n // The element is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel module\n set.index[module] = set.modules.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a module from a set. O(1).\n * Returns false if the module was not present in the set.\n */\n function remove(Set storage set, IGelatoProviderModule module)\n internal\n returns (bool)\n {\n if (contains(set, module)){\n uint256 toDeleteIndex = set.index[module] - 1;\n uint256 lastIndex = set.modules.length - 1;\n\n // If the element we're deleting is the last one, we can just remove it without doing a swap\n if (lastIndex != toDeleteIndex) {\n IGelatoProviderModule lastValue = set.modules[lastIndex];\n\n // Move the last module to the index where the deleted module is\n set.modules[toDeleteIndex] = lastValue;\n // Update the index for the moved module\n set.index[lastValue] = toDeleteIndex + 1; // All indexes are 1-based\n }\n\n // Delete the index entry for the deleted module\n delete set.index[module];\n\n // Delete the old entry for the moved module\n set.modules.pop();\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the module is in the set. O(1).\n */\n function contains(Set storage set, IGelatoProviderModule module)\n internal\n view\n returns (bool)\n {\n return set.index[module] != 0;\n }\n\n /**\n * @dev Returns an array with all modules in the set. O(N).\n * Note that there are no guarantees on the ordering of modules inside the\n * array, and it may change when more modules are added or removed.\n\n * WARNING: This function may run out of gas on large sets: use {length} and\n * {get} instead in these cases.\n */\n function enumerate(Set storage set)\n internal\n view\n returns (IGelatoProviderModule[] memory)\n {\n IGelatoProviderModule[] memory output = new IGelatoProviderModule[](set.modules.length);\n for (uint256 i; i < set.modules.length; i++) output[i] = set.modules[i];\n return output;\n }\n\n /**\n * @dev Returns the number of elements on the set. O(1).\n */\n function length(Set storage set)\n internal\n view\n returns (uint256)\n {\n return set.modules.length;\n }\n\n /** @dev Returns the element stored at position `index` in the set. O(1).\n * Note that there are no guarantees on the ordering of modules inside the\n * array, and it may change when more modules are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function get(Set storage set, uint256 index)\n internal\n view\n returns (IGelatoProviderModule)\n {\n return set.modules[index];\n }\n}"
},
"contracts/gelato_core/interfaces/IGelatoSysAdmin.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\ninterface IGelatoSysAdmin {\n struct GelatoSysAdminInitialState {\n address gelatoGasPriceOracle;\n bytes oracleRequestData;\n uint256 gelatoMaxGas;\n uint256 internalGasRequirement;\n uint256 minExecutorStake;\n uint256 executorSuccessShare;\n uint256 sysAdminSuccessShare;\n uint256 totalSuccessShare;\n }\n\n // Events\n event LogGelatoGasPriceOracleSet(address indexed oldOracle, address indexed newOracle);\n event LogOracleRequestDataSet(bytes oldData, bytes newData);\n\n event LogGelatoMaxGasSet(uint256 oldMaxGas, uint256 newMaxGas);\n event LogInternalGasRequirementSet(uint256 oldRequirment, uint256 newRequirment);\n\n event LogMinExecutorStakeSet(uint256 oldMin, uint256 newMin);\n\n event LogExecutorSuccessShareSet(uint256 oldShare, uint256 newShare, uint256 total);\n event LogSysAdminSuccessShareSet(uint256 oldShare, uint256 newShare, uint256 total);\n\n event LogSysAdminFundsWithdrawn(uint256 oldBalance, uint256 newBalance);\n\n // State Writing\n\n /// @notice Assign new gas price oracle\n /// @dev Only callable by sysAdmin\n /// @param _newOracle Address of new oracle\n function setGelatoGasPriceOracle(address _newOracle) external;\n\n /// @notice Assign new gas price oracle\n /// @dev Only callable by sysAdmin\n /// @param _requestData The encoded payload for the staticcall to the oracle.\n function setOracleRequestData(bytes calldata _requestData) external;\n\n /// @notice Assign new maximum gas limit providers can consume in executionWrapper()\n /// @dev Only callable by sysAdmin\n /// @param _newMaxGas New maximum gas limit\n function setGelatoMaxGas(uint256 _newMaxGas) external;\n\n /// @notice Assign new interal gas limit requirement for exec()\n /// @dev Only callable by sysAdmin\n /// @param _newRequirement New internal gas requirement\n function setInternalGasRequirement(uint256 _newRequirement) external;\n\n /// @notice Assign new minimum executor stake\n /// @dev Only callable by sysAdmin\n /// @param _newMin New minimum executor stake\n function setMinExecutorStake(uint256 _newMin) external;\n\n /// @notice Assign new success share for executors to receive after successful execution\n /// @dev Only callable by sysAdmin\n /// @param _percentage New % success share of total gas consumed\n function setExecutorSuccessShare(uint256 _percentage) external;\n\n /// @notice Assign new success share for sysAdmin to receive after successful execution\n /// @dev Only callable by sysAdmin\n /// @param _percentage New % success share of total gas consumed\n function setSysAdminSuccessShare(uint256 _percentage) external;\n\n /// @notice Withdraw sysAdmin funds\n /// @dev Only callable by sysAdmin\n /// @param _amount Amount to withdraw\n /// @param _to Address to receive the funds\n function withdrawSysAdminFunds(uint256 _amount, address payable _to) external returns(uint256);\n\n // State Reading\n /// @notice Unaccounted tx overhead that will be refunded to executors\n function EXEC_TX_OVERHEAD() external pure returns(uint256);\n\n /// @notice Addess of current Gelato Gas Price Oracle\n function gelatoGasPriceOracle() external view returns(address);\n\n /// @notice Getter for oracleRequestData state variable\n function oracleRequestData() external view returns(bytes memory);\n\n /// @notice Gas limit an executor has to submit to get refunded even if actions revert\n function gelatoMaxGas() external view returns(uint256);\n\n /// @notice Internal gas limit requirements ti ensure executor payout\n function internalGasRequirement() external view returns(uint256);\n\n /// @notice Minimum stake required from executors\n function minExecutorStake() external view returns(uint256);\n\n /// @notice % Fee executors get as a reward for a successful execution\n function executorSuccessShare() external view returns(uint256);\n\n /// @notice Total % Fee executors and sysAdmin collectively get as a reward for a successful execution\n /// @dev Saves a state read\n function totalSuccessShare() external view returns(uint256);\n\n /// @notice Get total fee providers pay executors for a successful execution\n /// @param _gas Gas consumed by transaction\n /// @param _gasPrice Current gelato gas price\n function executorSuccessFee(uint256 _gas, uint256 _gasPrice)\n external\n view\n returns(uint256);\n\n /// @notice % Fee sysAdmin gets as a reward for a successful execution\n function sysAdminSuccessShare() external view returns(uint256);\n\n /// @notice Get total fee providers pay sysAdmin for a successful execution\n /// @param _gas Gas consumed by transaction\n /// @param _gasPrice Current gelato gas price\n function sysAdminSuccessFee(uint256 _gas, uint256 _gasPrice)\n external\n view\n returns(uint256);\n\n /// @notice Get sysAdminds funds\n function sysAdminFunds() external view returns(uint256);\n}\n"
},
"contracts/gelato_core/GelatoExecutors.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoExecutors} from \"./interfaces/IGelatoExecutors.sol\";\nimport {GelatoProviders} from \"./GelatoProviders.sol\";\nimport {Address} from \"../external/Address.sol\";\nimport {SafeMath} from \"../external/SafeMath.sol\";\nimport {Math} from \"../external/Math.sol\";\n\n/// @title GelatoExecutors\n/// @author Luis Schliesske & Hilmar Orth\n/// @notice Stake Management of executors & batch Unproving providers\n/// @dev Find all NatSpecs inside IGelatoExecutors\nabstract contract GelatoExecutors is IGelatoExecutors, GelatoProviders {\n\n using Address for address payable; /// for sendValue method\n using SafeMath for uint256;\n\n // Executor De/Registrations and Staking\n function stakeExecutor() external payable override {\n uint256 currentStake = executorStake[msg.sender];\n uint256 newStake = currentStake + msg.value;\n require(\n newStake >= minExecutorStake,\n \"GelatoExecutors.stakeExecutor: below minStake\"\n );\n executorStake[msg.sender] = newStake;\n emit LogExecutorStaked(msg.sender, currentStake, newStake);\n }\n\n function unstakeExecutor() external override {\n require(\n !isExecutorAssigned(msg.sender),\n \"GelatoExecutors.unstakeExecutor: msg.sender still assigned\"\n );\n uint256 unbondedStake = executorStake[msg.sender];\n require(\n unbondedStake != 0,\n \"GelatoExecutors.unstakeExecutor: already unstaked\"\n );\n delete executorStake[msg.sender];\n msg.sender.sendValue(unbondedStake);\n emit LogExecutorUnstaked(msg.sender);\n }\n\n function withdrawExcessExecutorStake(uint256 _withdrawAmount)\n external\n override\n returns(uint256 realWithdrawAmount)\n {\n require(\n isExecutorMinStaked(msg.sender),\n \"GelatoExecutors.withdrawExcessExecutorStake: not minStaked\"\n );\n\n uint256 currentExecutorStake = executorStake[msg.sender];\n uint256 excessExecutorStake = currentExecutorStake - minExecutorStake;\n\n realWithdrawAmount = Math.min(_withdrawAmount, excessExecutorStake);\n\n uint256 newExecutorStake = currentExecutorStake - realWithdrawAmount;\n\n // Effects\n executorStake[msg.sender] = newExecutorStake;\n\n // Interaction\n msg.sender.sendValue(realWithdrawAmount);\n emit LogExecutorBalanceWithdrawn(msg.sender, realWithdrawAmount);\n }\n\n // To unstake, Executors must reassign ALL their Providers to another staked Executor\n function multiReassignProviders(address[] calldata _providers, address _newExecutor)\n external\n override\n {\n for (uint i; i < _providers.length; i++)\n executorAssignsExecutor(_providers[i], _newExecutor);\n }\n}"
},
"contracts/gelato_core/interfaces/IGelatoExecutors.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\ninterface IGelatoExecutors {\n event LogExecutorStaked(address indexed executor, uint256 oldStake, uint256 newStake);\n event LogExecutorUnstaked(address indexed executor);\n\n event LogExecutorBalanceWithdrawn(\n address indexed executor,\n uint256 withdrawAmount\n );\n\n /// @notice Stake on Gelato to become a whitelisted executor\n /// @dev Msg.value has to be >= minExecutorStake\n function stakeExecutor() external payable;\n\n /// @notice Unstake on Gelato to become de-whitelisted and withdraw minExecutorStake\n function unstakeExecutor() external;\n\n /// @notice Re-assigns multiple providers to other executors\n /// @dev Executors must re-assign all providers before being able to unstake\n /// @param _providers List of providers to re-assign\n /// @param _newExecutor Address of new executor to assign providers to\n function multiReassignProviders(address[] calldata _providers, address _newExecutor)\n external;\n\n\n /// @notice Withdraw excess Execur Stake\n /// @dev Can only be called if executor is isExecutorMinStaked\n /// @param _withdrawAmount Amount to withdraw\n /// @return Amount that was actually withdrawn\n function withdrawExcessExecutorStake(uint256 _withdrawAmount) external returns(uint256);\n\n}\n"
},
"contracts/gelato_actions/transfer/ActionTransfer.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoActionsStandardFull} from \"../GelatoActionsStandardFull.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {Address} from \"../../external/Address.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\n/// @dev This action is for user proxies that store funds.\ncontract ActionTransfer is GelatoActionsStandardFull {\n // using SafeERC20 for IERC20; <- internal library methods vs. try/catch\n using Address for address payable;\n using SafeERC20 for IERC20;\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n function getActionData(address _sendToken, uint256 _sendAmount, address _destination)\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.action.selector,\n _sendToken,\n _sendAmount,\n _destination\n );\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_IN_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n // ======= ACTION IMPLEMENTATION DETAILS =========\n /// @dev Always use this function for encoding _actionData off-chain\n /// Will be called by GelatoActionPipeline if Action.dataFlow.None\n function action(address sendToken, uint256 sendAmount, address destination)\n public\n virtual\n delegatecallOnly(\"ActionTransfer.action\")\n {\n if (sendToken != ETH_ADDRESS) {\n IERC20 sendERC20 = IERC20(sendToken);\n sendERC20.safeTransfer(destination, sendAmount, \"ActionTransfer.action:\");\n emit LogOneWay(address(this), sendToken, sendAmount, destination);\n } else {\n payable(destination).sendValue(sendAmount);\n }\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n address destination = abi.decode(_actionData[68:100], (address));\n action(sendToken, sendAmount, destination);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address sendToken, uint256 sendAmount, address destination) = abi.decode(\n _actionData[4:],\n (address,uint256,address)\n );\n action(sendToken, sendAmount, destination);\n return abi.encode(sendToken, sendAmount);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n address destination = abi.decode(_actionData[68:100], (address));\n action(sendToken, sendAmount, destination);\n return abi.encode(sendToken, sendAmount);\n }\n\n // ===== ACTION TERMS CHECK ========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address _userProxy,\n bytes calldata _actionData,\n DataFlow _dataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory)\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionTransfer: invalid action selector\";\n\n if (_dataFlow == DataFlow.In || _dataFlow == DataFlow.InAndOut)\n return \"ActionTransfer: termsOk check invalidated by inbound DataFlow\";\n\n (address sendToken, uint256 sendAmount) = abi.decode(\n _actionData[4:68],\n (address,uint256)\n );\n\n if (sendToken == ETH_ADDRESS) {\n if (_userProxy.balance < sendAmount)\n return \"ActionTransfer: NotOkUserProxyETHBalance\";\n } else {\n try IERC20(sendToken).balanceOf(_userProxy) returns(uint256 sendTokenBalance) {\n if (sendTokenBalance < sendAmount)\n return \"ActionTransfer: NotOkUserProxyERC20Balance\";\n } catch {\n return \"ActionTransfer: ErrorBalanceOf\";\n }\n }\n\n // STANDARD return string to signal actionConditions Ok\n return OK;\n }\n}\n"
},
"contracts/gelato_actions/GelatoActionsStandardFull.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandard} from \"./GelatoActionsStandard.sol\";\nimport {IGelatoInFlowAction} from \"./action_pipeline_interfaces/IGelatoInFlowAction.sol\";\nimport {IGelatoOutFlowAction} from \"./action_pipeline_interfaces/IGelatoOutFlowAction.sol\";\nimport {\n IGelatoInAndOutFlowAction\n} from \"./action_pipeline_interfaces/IGelatoInAndOutFlowAction.sol\";\n\n/// @title GelatoActionsStandardFull\n/// @notice ActionStandard that inherits from all the PipeAction interfaces.\n/// @dev Inherit this to enforce implementation of all PipeAction functions.\nabstract contract GelatoActionsStandardFull is\n GelatoActionsStandard,\n IGelatoInFlowAction,\n IGelatoOutFlowAction,\n IGelatoInAndOutFlowAction\n{\n function DATA_FLOW_IN_TYPE()\n external\n pure\n virtual\n override(IGelatoInFlowAction, IGelatoInAndOutFlowAction)\n returns (bytes32);\n\n function DATA_FLOW_OUT_TYPE()\n external\n pure\n virtual\n override(IGelatoOutFlowAction, IGelatoInAndOutFlowAction)\n returns (bytes32);\n}"
},
"contracts/external/IERC20.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP. Does not include\n * the optional functions; to access them see {ERC20Detailed}.\n */\ninterface IERC20 {\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `sender` to `recipient` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);\n\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"
},
"contracts/external/SafeERC20.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"./IERC20.sol\";\nimport \"./SafeMath.sol\";\nimport \"./Address.sol\";\n\n/**\n * @title SafeERC20\n * @notice Adapted by @gitpusha from Gelato to include error strings.\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using SafeMath for uint256;\n using Address for address;\n\n function safeTransfer(IERC20 token, address to, uint256 value, string memory context)\n internal\n {\n callOptionalReturn(\n token,\n abi.encodeWithSelector(token.transfer.selector, to, value),\n context\n );\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value,\n string memory context\n )\n internal\n {\n callOptionalReturn(\n token,\n abi.encodeWithSelector(token.transferFrom.selector, from, to, value),\n context\n );\n }\n\n function safeApprove(IERC20 token, address spender, uint256 value, string memory context)\n internal\n {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n // solhint-disable-next-line max-line-length\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n string(\n abi.encodePacked(\n context, \"SafeERC20: approve from non-zero to non-zero allowance\"\n )\n )\n );\n callOptionalReturn(\n token,\n abi.encodeWithSelector(token.approve.selector, spender, value),\n context\n );\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value,\n string memory context\n )\n internal\n {\n uint256 newAllowance = token.allowance(address(this), spender).add(value);\n callOptionalReturn(\n token,\n abi.encodeWithSelector(token.approve.selector, spender, newAllowance),\n context\n );\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value,\n string memory context\n )\n internal\n {\n uint256 newAllowance = token.allowance(\n address(this),\n spender\n ).sub(\n value,\n string(abi.encodePacked(context, \"SafeERC20: decreased allowance below zero\")\n ));\n callOptionalReturn(\n token,\n abi.encodeWithSelector(token.approve.selector, spender, newAllowance),\n context\n );\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n * @param context Debugging Info for the revert message (addition to original library)\n */\n function callOptionalReturn(IERC20 token, bytes memory data, string memory context)\n private\n {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves.\n\n // A Solidity high level call has three parts:\n // 1. The target address is checked to verify it contains contract code\n // 2. The call itself is made, and success asserted\n // 3. The return value is decoded, which in turn checks the size of the returned data.\n // solhint-disable-next-line max-line-length\n require(\n address(token).isContract(),\n string(abi.encodePacked(context, \"SafeERC20: call to non-contract\"))\n );\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = address(token).call(data);\n require(\n success, string(abi.encodePacked(context, \"SafeERC20: low-level call failed\"))\n );\n\n if (returndata.length > 0) { // Return data is optional\n // solhint-disable-next-line max-line-length\n require(\n abi.decode(returndata, (bool)),\n string(\n abi.encodePacked(context, \"SafeERC20: ERC20 operation did not succeed\")\n )\n );\n }\n }\n}\n"
},
"contracts/mocks/gelato_actions/one-off/Gnosis/MockBatchExchange.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandard} from \"../../../../gelato_actions/GelatoActionsStandard.sol\";\nimport {SafeERC20} from \"../../../../external/SafeERC20.sol\";\nimport {IERC20} from \"../../../../external/IERC20.sol\";\n\ncontract MockBatchExchange {\n\n using SafeERC20 for IERC20;\n\n event LogWithdrawRequest();\n event LogCounter();\n\n mapping(address => uint256) public withdrawAmounts;\n mapping(address => bool) public validWithdrawRequests;\n\n uint256 public counter;\n\n function withdraw(address _proxyAddress, address _token)\n public\n {\n IERC20 token = IERC20(_token);\n uint256 withdrawAmount = withdrawAmounts[_token];\n token.safeTransfer(_proxyAddress, withdrawAmount, \"MockBatchExchange.withdraw\");\n }\n\n function setWithdrawAmount(address _token, uint256 _withdrawAmount)\n public\n {\n IERC20 token = IERC20(_token);\n require(\n token.balanceOf(address(this)) >= _withdrawAmount,\n \"MockBatchExchange: Insufficient Token balance\"\n );\n withdrawAmounts[_token] = _withdrawAmount;\n }\n\n function hasValidWithdrawRequest(address _proxyAddress, address)\n view\n public\n returns(bool)\n {\n if (validWithdrawRequests[_proxyAddress]) return true;\n }\n\n function setValidWithdrawRequest(address _proxyAddress)\n public\n {\n validWithdrawRequests[_proxyAddress] = true;\n emit LogWithdrawRequest();\n counter++;\n if(counter == 1 ) emit LogCounter();\n }\n\n // buyTokenId, sellTokenId, withdrawBatchId, _buyAmount, sellAmount\n function placeOrder(uint16 buyToken, uint16 sellToken, uint32 validUntil, uint128 buyAmount, uint128 sellAmount)\n public\n returns (uint256)\n {\n\n }\n\n function deposit(address _sellToken, uint128 _sellAmount)\n public\n {\n IERC20 sellToken = IERC20(_sellToken);\n sellToken.safeTransferFrom(\n msg.sender, address(this), _sellAmount, \"MockBatchExchange.deposit:\"\n );\n }\n\n function requestFutureWithdraw(address token, uint256 amount, uint32 batchId)\n public\n {\n }\n\n function tokenAddressToIdMap(address _token)\n public\n view\n returns(uint16 test)\n {\n\n }\n\n\n}\n"
},
"contracts/gelato_conditions/price/kyber/ConditionKyberRateStateful.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoStatefulConditionsStandard} from \"../../GelatoStatefulConditionsStandard.sol\";\nimport {IKyberNetworkProxy} from \"../../../dapp_interfaces/kyber/IKyberNetworkProxy.sol\";\nimport {SafeMath} from \"../../../external/SafeMath.sol\";\nimport {IERC20} from \"../../../external/IERC20.sol\";\nimport {IGelatoCore} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract ConditionKyberRateStateful is GelatoStatefulConditionsStandard {\n using SafeMath for uint256;\n\n IKyberNetworkProxy public immutable KYBER;\n\n // userProxy => taskReceipt.id => refPrice\n mapping(address => mapping(uint256 => uint256)) public refRate;\n\n constructor(IKyberNetworkProxy _kyberNetworkProxy, IGelatoCore _gelatoCore)\n public\n GelatoStatefulConditionsStandard(_gelatoCore)\n {\n KYBER = _kyberNetworkProxy;\n }\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(\n address _userProxy,\n address _sendToken,\n uint256 _sendAmount,\n address _receiveToken,\n bool _greaterElseSmaller\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.checkRefKyberRate.selector,\n uint256(0), // taskReceiptId placeholder\n _userProxy,\n _sendToken,\n _sendAmount,\n _receiveToken,\n _greaterElseSmaller\n );\n }\n\n // STANDARD Interface\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256 _taskReceiptId, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n (address userProxy,\n address sendToken,\n uint256 sendAmount,\n address receiveToken,\n bool greaterElseSmaller\n ) = abi.decode(\n _conditionData[36:], // slice out selector & taskReceiptId\n (address,address,uint256,address,bool)\n );\n return checkRefKyberRate(\n _taskReceiptId, userProxy, sendToken, sendAmount, receiveToken, greaterElseSmaller\n );\n }\n\n // Specific Implementation\n function checkRefKyberRate(\n uint256 _taskReceiptId,\n address _userProxy,\n address _sendToken,\n uint256 _sendAmount,\n address _receiveToken,\n bool _greaterElseSmaller\n )\n public\n view\n virtual\n returns(string memory)\n {\n uint256 currentRefRate = refRate[_userProxy][_taskReceiptId];\n try KYBER.getExpectedRate(_sendToken, _receiveToken, _sendAmount)\n returns(uint256 expectedRate, uint256)\n {\n if (_greaterElseSmaller) { // greaterThan\n if (expectedRate >= currentRefRate) return OK;\n return \"NotOkKyberExpectedRateIsNotGreaterThanRefRate\";\n } else { // smallerThan\n if (expectedRate <= currentRefRate) return OK;\n return \"NotOkKyberExpectedRateIsNotSmallerThanRefRate\";\n }\n } catch {\n return \"KyberGetExpectedRateError\";\n }\n }\n\n /// @dev This function should be called via the userProxy of a Gelato Task as part\n /// of the Task.actions, if the Condition state should be updated after the task.\n /// @param _rateDelta The change in price after which this condition should return for a given taskId\n /// @param _idDelta Default to 0. If you submit multiple tasks in one action, this can help\n // customize which taskId the state should be allocated to\n function setRefRate(\n address _sendToken,\n uint256 _sendAmount,\n address _receiveToken,\n bool _greaterElseSmaller,\n uint256 _rateDelta,\n uint256 _idDelta\n )\n external\n {\n uint256 taskReceiptId = _getIdOfNextTaskInCycle() + _idDelta;\n try KYBER.getExpectedRate(_sendToken, _receiveToken, _sendAmount)\n returns(uint256 expectedRate, uint256)\n {\n if (_greaterElseSmaller) {\n refRate[msg.sender][taskReceiptId] = expectedRate.add(_rateDelta);\n } else {\n refRate[msg.sender][taskReceiptId] = expectedRate.sub(\n _rateDelta,\n \"ConditionKyberRateStateful.setRefRate: Underflow\"\n );\n }\n } catch {\n revert(\"ConditionKyberRateStateful.setRefRate: KyberGetExpectedRateError\");\n }\n }\n\n function getKyberRate(address _sendToken, uint256 _sendAmount, address _receiveToken)\n external\n view\n returns(uint256)\n {\n try KYBER.getExpectedRate(_sendToken, _receiveToken, _sendAmount)\n returns(uint256 expectedRate, uint256)\n {\n return expectedRate;\n } catch {\n revert(\"ConditionKyberRateStateful.setRefRate: KyberGetExpectedRateError\");\n }\n }\n}"
},
"contracts/dapp_interfaces/kyber/IKyberNetworkProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\n/// @title IKyberNetworkProxy\n/// @notice Interface to the KyberNetworkProxy contract.\n/// The KyberNetworkProxy contract's role is to facilitate two main functionalities:\n/// 1) return the expected exchange rate, and 2) to execute a trade.\n/// @dev https://developer.kyber.network/docs/API_ABI-KyberNetworkProxy/\ninterface IKyberNetworkProxy {\n /**\n * @dev Makes a trade between src and dest token and send dest tokens to destAddress\n * @param src source ERC20 token contract address\n * @param srcAmount source ERC20 token amount in its token decimals\n * @param dest destination ERC20 token contract address\n * @param destAddress recipient address for destination ERC20 token\n * @param maxDestAmount limit on the amount of destination tokens\n * @param minConversionRate minimum conversion rate; trade is canceled if actual rate is lower\n * @param walletId wallet address to send part of the fees to\n * @return Amount of actual destination tokens\n * @notice srcAmount | maxDestAmount These amounts should be in the source and\n destination token decimals respectively. For example, if the user wants to swap\n from / to 10 POWR,which has 6 decimals, it would be 10 * (10 ** 6) = 10000000\n * @notice maxDestAmount should not be 0. Set it to an arbitarily large amount\n if you want all source tokens to be converted.\n * @notice minConversionRate: This rate is independent of the source and\n destination token decimals. To calculate this rate, take yourRate * 10**18.\n For example, even though ZIL has 12 token decimals, if we want the minimum\n conversion rate to be 1 ZIL = 0.00017 ETH, then\n minConversionRate = 0.00017 * (10 ** 18).\n * @notice walletId: If you are part of our fee sharing program, this will be\n your registered wallet address. Set it as 0 if you are not a participant.\n * @notice Since ETH is not an ERC20 token, we use\n 0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee as a proxy address to represent it.\n * @notice If src is ETH, then you also need to send ether along with your call.\n * @notice There is a minimum trading value of 1000 wei tokens.\n Anything fewer is considered as 0.\n */\n function trade(\n address src,\n uint256 srcAmount,\n address dest,\n address destAddress,\n uint256 maxDestAmount,\n uint256 minConversionRate,\n address walletId\n )\n external\n payable\n returns (uint256);\n\n /**\n * @dev Get the expected exchange rate.\n * @param src source ERC20 token contract address\n * @param dest destination ERC20 token contract address\n * @param srcQty wei amount of source ERC20 token\n * @return The expected exchange rate and slippage rate.\n * @notice Returned values are in precision values (10**18)\n To understand what this rate means, divide the obtained value by 10**18\n (tA, tB,)\n */\n function getExpectedRate(address src, address dest, uint256 srcQty)\n external\n view\n returns (uint256, uint256);\n}\n"
},
"contracts/gelato_conditions/price/kyber/ConditionKyberRate.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoConditionsStandard} from \"../../GelatoConditionsStandard.sol\";\nimport {IKyberNetworkProxy} from \"../../../dapp_interfaces/kyber/IKyberNetworkProxy.sol\";\nimport {SafeMath} from \"../../../external/SafeMath.sol\";\n\ncontract ConditionKyberRate is GelatoConditionsStandard {\n using SafeMath for uint256;\n\n IKyberNetworkProxy public immutable KYBER;\n constructor(IKyberNetworkProxy _kyberProxy) public { KYBER = _kyberProxy; }\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(\n address _src,\n uint256 _srcAmt,\n address _dest,\n uint256 _refRate,\n bool _greaterElseSmaller\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.checkRate.selector,\n _src,\n _srcAmt,\n _dest,\n _refRate,\n _greaterElseSmaller\n );\n }\n\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n (address src,\n uint256 srcAmt,\n address dest,\n uint256 refRate,\n bool greaterElseSmaller) = abi.decode(\n _conditionData[4:],\n (address,uint256,address,uint256,bool)\n );\n return checkRate(src, srcAmt, dest, refRate, greaterElseSmaller);\n }\n\n // Specific Implementation\n function checkRate(\n address _src,\n uint256 _srcAmt,\n address _dest,\n uint256 _refRate,\n bool _greaterElseSmaller\n )\n public\n view\n virtual\n returns(string memory)\n {\n try KYBER.getExpectedRate(_src, _dest, _srcAmt)\n returns(uint256 expectedRate, uint256)\n {\n if (_greaterElseSmaller) { // greaterThan\n if (expectedRate >= _refRate) return OK;\n return \"NotOkKyberExpectedRateIsNotGreaterThanRefRate\";\n } else { // smallerThan\n if (expectedRate <= _refRate) return OK;\n return \"NotOkKyberExpectedRateIsNotSmallerThanRefRate\";\n }\n } catch {\n return \"KyberGetExpectedRateError\";\n }\n }\n}"
},
"contracts/mocks/gelato_conditions/MockConditionDummyRevert.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoConditionsStandard} from \"../../gelato_conditions/GelatoConditionsStandard.sol\";\n\ncontract MockConditionDummyRevert is GelatoConditionsStandard {\n // STANDARD interface\n function ok(uint256, bytes calldata _revertCheckData, uint256)\n external\n view\n virtual\n override\n returns(string memory)\n {\n bool returnOk = abi.decode(_revertCheckData, (bool));\n return revertCheck(returnOk);\n }\n\n function revertCheck(bool _returnOk) public pure virtual returns(string memory) {\n if (_returnOk) return OK;\n revert(\"MockConditionDummyRevert.ok: test revert\");\n }\n}"
},
"contracts/mocks/gelato_conditions/MockConditionDummy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoConditionsStandard} from \"../../gelato_conditions/GelatoConditionsStandard.sol\";\n\ncontract MockConditionDummy is GelatoConditionsStandard {\n // STANDARD interface\n function ok(uint256, bytes calldata _dummyCheckData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n bool returnOk = abi.decode(_dummyCheckData, (bool));\n return dummyCheck(returnOk);\n }\n\n function dummyCheck(bool _returnOk) public pure virtual returns(string memory returnString) {\n _returnOk ? returnString = OK : returnString = \"NotOk\";\n }\n}"
},
"contracts/gelato_conditions/gnosis/ConditionBatchExchangeFundsWithdrawable.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"../GelatoConditionsStandard.sol\";\nimport \"../../dapp_interfaces/gnosis/IBatchExchange.sol\";\n\ncontract ConditionBatchExchangeFundsWithdrawable is GelatoConditionsStandard {\n\n address public immutable batchExchangeAddress;\n constructor(address _batchExchange) public { batchExchangeAddress = _batchExchange; }\n\n function ok(uint256, bytes calldata _withdrawableCheckData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n (address proxy, address sellToken, address buyToken) = abi.decode(\n _withdrawableCheckData,\n (address,address,address)\n );\n return withdrawableCheck(proxy, sellToken, buyToken);\n }\n\n function withdrawableCheck(address _proxy, address _sellToken, address _buyToken)\n public\n view\n virtual\n returns(string memory) // executable?\n {\n (bool sellTokenWithdrawable, bool buyTokenWithdrawable) = getConditionValue(\n _proxy,\n _sellToken,\n _buyToken\n );\n if (!sellTokenWithdrawable) return \"SellTokenNotWithdrawable\";\n if (!buyTokenWithdrawable) return \"BuyTokenNotWithdrawable\";\n return OK;\n }\n\n function getConditionValue(\n address _proxy,\n address _sellToken,\n address _buyToken\n )\n public\n view\n returns(bool sellTokenWithdrawable, bool buyTokenWithdrawable)\n {\n IBatchExchange batchExchange = IBatchExchange(batchExchangeAddress);\n sellTokenWithdrawable = batchExchange.hasValidWithdrawRequest(_proxy, _sellToken);\n buyTokenWithdrawable = batchExchange.hasValidWithdrawRequest(_proxy, _buyToken);\n }\n}"
},
"contracts/gelato_conditions/eth_utils/eth_time/ConditionTime.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoConditionsStandard} from \"../../GelatoConditionsStandard.sol\";\n\ncontract ConditionTime is GelatoConditionsStandard {\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(uint256 _timestamp)\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encode(_timestamp);\n }\n\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n uint256 timestamp = abi.decode(_conditionData, (uint256));\n return timeCheck(timestamp);\n }\n\n // Specific implementation\n function timeCheck(uint256 _timestamp) public view virtual returns(string memory) {\n if (_timestamp <= block.timestamp) return OK;\n return \"NotOkTimestampDidNotPass\";\n }\n}"
},
"contracts/gelato_conditions/eth_utils/eth_time/ConditionTimeStateful.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoStatefulConditionsStandard} from \"../../GelatoStatefulConditionsStandard.sol\";\nimport {SafeMath} from \"../../../external/SafeMath.sol\";\nimport {IGelatoCore} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IERC20} from \"../../../external/IERC20.sol\";\n\ncontract ConditionTimeStateful is GelatoStatefulConditionsStandard {\n\n using SafeMath for uint256;\n\n // userProxy => taskReceiptId => refTime\n mapping(address => mapping(uint256 => uint256)) public refTime;\n\n constructor(IGelatoCore _gelatoCore)\n GelatoStatefulConditionsStandard(_gelatoCore)\n public\n {}\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(address _userProxy)\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(this.checkRefTime.selector, uint256(0), _userProxy);\n }\n\n // STANDARD interface\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256 _taskReceiptId, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n address userProxy = abi.decode(_conditionData[36:], (address));\n return checkRefTime(_taskReceiptId, userProxy);\n }\n\n // Specific Implementation\n /// @dev Abi encode these parameter inputs. Use a placeholder for _taskReceiptId.\n /// @param _taskReceiptId Will be stripped from encoded data and replaced by\n /// the value passed in from GelatoCore.\n function checkRefTime(uint256 _taskReceiptId, address _userProxy)\n public\n view\n virtual\n returns(string memory)\n {\n uint256 _refTime = refTime[_userProxy][_taskReceiptId];\n if (_refTime <= block.timestamp) return OK;\n return \"NotOkTimestampDidNotPass\";\n }\n\n /// @dev This function should be called via the userProxy of a Gelato Task as part\n /// of the Task.actions, if the Condition state should be updated after the task.\n /// This is for Task Cycles/Chains and we fetch the TaskReceipt.id of the\n // next Task that will be auto-submitted by GelatoCore in the same exec Task transaction.\n /// @param _timeDelta The time after which this condition should return for a given taskId\n /// @param _idDelta Default to 0. If you submit multiple tasks in one action, this can help\n // customize which taskId the state should be allocated to\n function setRefTime(uint256 _timeDelta, uint256 _idDelta) external {\n uint256 currentTime = block.timestamp;\n uint256 newRefTime = currentTime + _timeDelta;\n refTime[msg.sender][_getIdOfNextTaskInCycle() + _idDelta] = newRefTime;\n }\n}\n"
},
"contracts/gelato_conditions/balances/ConditionBalanceStateful.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoStatefulConditionsStandard} from \"../GelatoStatefulConditionsStandard.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\nimport {IGelatoCore} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\n\n\ncontract ConditionBalanceStateful is GelatoStatefulConditionsStandard {\n\n using SafeMath for uint256;\n\n // userProxy => taskReceiptId => refBalance\n mapping(address => mapping(uint256 => uint256)) public refBalance;\n\n constructor(IGelatoCore _gelatoCore)\n GelatoStatefulConditionsStandard(_gelatoCore)\n public\n {}\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(\n address _userProxy,\n address _account,\n address _token,\n bool _greaterElseSmaller\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.checkRefBalance.selector,\n uint256(0), // taskReceiptId placeholder\n _userProxy,\n _account,\n _token,\n _greaterElseSmaller\n );\n }\n\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256 _taskReceiptId, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n (address _userProxy,\n address _account,\n address _token,\n bool _greaterElseSmaller) = abi.decode(\n _conditionData[36:], // slice out selector and _taskReceiptId\n (address,address,address,bool)\n );\n return checkRefBalance(\n _taskReceiptId, _userProxy, _account, _token, _greaterElseSmaller\n );\n }\n\n // Specific Implementation\n /// @dev Abi encode these parameter inputs. Use a placeholder for _taskReceiptId.\n /// @param _taskReceiptId Will be stripped from encoded data and replaced by\n /// the value passed in from GelatoCore.\n function checkRefBalance(\n uint256 _taskReceiptId,\n address _userProxy,\n address _account,\n address _token,\n bool _greaterElseSmaller\n )\n public\n view\n virtual\n returns(string memory)\n {\n uint256 _refBalance = refBalance[_userProxy][_taskReceiptId];\n // ETH balances\n if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {\n if (_greaterElseSmaller) { // greaterThan\n if (_account.balance >= _refBalance) return OK;\n return \"NotOkETHBalanceIsNotGreaterThanRefBalance\";\n } else { // smallerThan\n if (_account.balance <= _refBalance) return OK;\n return \"NotOkETHBalanceIsNotSmallerThanRefBalance\";\n }\n } else {\n // ERC20 balances\n IERC20 erc20 = IERC20(_token);\n try erc20.balanceOf(_account) returns (uint256 erc20Balance) {\n if (_greaterElseSmaller) { // greaterThan\n if (erc20Balance >= _refBalance) return OK;\n return \"NotOkERC20BalanceIsNotGreaterThanRefBalance\";\n } else { // smallerThan\n if (erc20Balance <= _refBalance) return OK;\n return \"NotOkERC20BalanceIsNotSmallerThanRefBalance\";\n }\n } catch {\n return \"ERC20Error\";\n }\n }\n }\n\n /// @dev This function should be called via the userProxy of a Gelato Task as part\n /// of the Task.actions, if the Condition state should be updated after the task.\n /// This is for Task Cycles/Chains and we fetch the TaskReceipt.id of the\n // next Task that will be auto-submitted by GelatoCore in the same exec Task transaction.\n /// @param _balanceDelta The change in balance after which this condition should return for a given taskId\n /// @param _idDelta Default to 0. If you submit multiple tasks in one action, this can help\n // customize which taskId the state should be allocated to\n function setRefBalance(\n address _account,\n address _token,\n int256 _balanceDelta,\n uint256 _idDelta\n )\n external\n {\n uint256 currentBalanceOfAccount;\n uint256 newRefBalance;\n if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) // ETH\n currentBalanceOfAccount = _account.balance;\n else currentBalanceOfAccount = IERC20(_token).balanceOf(_account);\n require(\n int256(currentBalanceOfAccount) + _balanceDelta >= 0,\n \"ConditionBalanceStateful.setRefBalanceDelta: underflow\"\n );\n newRefBalance = uint256(int256(currentBalanceOfAccount) + _balanceDelta);\n refBalance[msg.sender][_getIdOfNextTaskInCycle() + _idDelta] = newRefBalance;\n }\n}"
},
"contracts/gelato_conditions/balances/ConditionBalance.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoConditionsStandard} from \"../GelatoConditionsStandard.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\n\ncontract ConditionBalance is GelatoConditionsStandard {\n\n /// @dev use this function to encode the data off-chain for the condition data field\n function getConditionData(\n address _account,\n address _token,\n uint256 _refBalance,\n bool _greaterElseSmaller\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.balanceCheck.selector,\n _account,\n _token,\n _refBalance,\n _greaterElseSmaller\n );\n }\n\n /// @param _conditionData The encoded data from getConditionData()\n function ok(uint256, bytes calldata _conditionData, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n (address _account,\n address _token,\n uint256 _refBalance,\n bool _greaterElseSmaller) = abi.decode(\n _conditionData[4:],\n (address,address,uint256,bool)\n );\n return balanceCheck(_account, _token, _refBalance, _greaterElseSmaller);\n }\n\n // Specific Implementation\n function balanceCheck(\n address _account,\n address _token,\n uint256 _refBalance,\n bool _greaterElseSmaller\n )\n public\n view\n virtual\n returns(string memory)\n {\n // ETH balances\n if (_token == 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE) {\n if (_greaterElseSmaller) { // greaterThan\n if (_account.balance >= _refBalance) return OK;\n return \"NotOkETHBalanceIsNotGreaterThanRefBalance\";\n } else { // smallerThan\n if (_account.balance <= _refBalance) return OK;\n return \"NotOkETHBalanceIsNotSmallerThanRefBalance\";\n }\n } else {\n // ERC20 balances\n IERC20 erc20 = IERC20(_token);\n try erc20.balanceOf(_account) returns (uint256 erc20Balance) {\n if (_greaterElseSmaller) { // greaterThan\n if (erc20Balance >= _refBalance) return OK;\n return \"NotOkERC20BalanceIsNotGreaterThanRefBalance\";\n } else { // smallerThan\n if (erc20Balance <= _refBalance) return OK;\n return \"NotOkERC20BalanceIsNotSmallerThanRefBalance\";\n }\n } catch {\n return \"ERC20Error\";\n }\n }\n }\n}"
},
"contracts/gelato_actions/kyber/ActionKyberTrade.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandardFull} from \"../GelatoActionsStandardFull.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {IKyberNetworkProxy} from \"../../dapp_interfaces/kyber/IKyberNetworkProxy.sol\";\n\ncontract ActionKyberTrade is GelatoActionsStandardFull {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n IKyberNetworkProxy public immutable KYBER;\n\n constructor(IKyberNetworkProxy _kyberNetworkProxy) public {\n KYBER =_kyberNetworkProxy;\n }\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n function getActionData(\n address _origin,\n address _sendToken, // ERC20 or ETH (symbol)\n uint256 _sendAmount,\n address _receiveToken, // ERC20 or ETH (symbol)\n address _receiver\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.action.selector,\n _origin,\n _sendToken,\n _sendAmount,\n _receiveToken,\n _receiver\n );\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_IN_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n function action(\n address _origin,\n address _sendToken, // ERC20 or ETH (symbol)\n uint256 _sendAmount,\n address _receiveToken, // ERC20 or ETH (symbol)\n address _receiver\n )\n public\n virtual\n delegatecallOnly(\"ActionKyberTrade.action\")\n returns (uint256 receiveAmount)\n {\n address receiver = _receiver == address(0) ? address(this) : _receiver;\n\n if (_sendToken == ETH_ADDRESS) {\n try KYBER.trade{value: _sendAmount}(\n _sendToken,\n _sendAmount,\n _receiveToken,\n receiver,\n type(uint256).max, // maxDestAmount\n 0, // minConversionRate (if price condition, limit order still possible)\n 0xe1F076849B781b1395Fd332dC1758Dbc129be6EC // fee-sharing: gelato-node\n )\n returns(uint256 receiveAmt)\n {\n receiveAmount = receiveAmt;\n } catch {\n revert(\"ActionKyberTrade.action: trade with ETH Error\");\n }\n } else {\n IERC20 sendERC20 = IERC20(_sendToken);\n\n // origin funds lightweight UserProxy\n if (_origin != address(0) && _origin != address(this)) {\n sendERC20.safeTransferFrom(\n _origin, address(this), _sendAmount, \"ActionKyberTrade.action:\"\n );\n }\n\n // UserProxy approves KyberNetworkProxy\n sendERC20.safeIncreaseAllowance(\n address(KYBER), _sendAmount, \"ActionKyberTrade.action:\"\n );\n\n try KYBER.trade(\n _sendToken,\n _sendAmount,\n _receiveToken,\n receiver,\n type(uint256).max, // maxDestAmount\n 0, // minConversionRate (if price condition, limit order still possible)\n 0xe1F076849B781b1395Fd332dC1758Dbc129be6EC // fee-sharing: gelato-node\n )\n returns(uint256 receiveAmt)\n {\n receiveAmount = receiveAmt;\n } catch {\n revert(\"ActionKyberTrade.action: trade with ERC20 Error\");\n }\n }\n\n emit LogTwoWay(\n _origin, // origin\n _sendToken,\n _sendAmount,\n address(KYBER), // destination\n _receiveToken,\n receiveAmount,\n receiver\n );\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n address origin = abi.decode(_actionData[4:36], (address));\n (address receiveToken, address receiver) = abi.decode(\n _actionData[100:],\n (address,address)\n );\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n action(origin, sendToken, sendAmount, receiveToken, receiver);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address origin, // 4:36\n address sendToken, // 36:68\n uint256 sendAmount, // 68:100\n address receiveToken, // 100:132\n address receiver /* 132:164 */) = abi.decode(\n _actionData[4:], // 0:4 == selector\n (address,address,uint256,address,address)\n );\n uint256 receiveAmount = action(origin, sendToken, sendAmount, receiveToken, receiver);\n return abi.encode(receiveToken, receiveAmount);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n address origin = abi.decode(_actionData[4:36], (address));\n (address receiveToken, address receiver) = abi.decode(\n _actionData[100:],\n (address,address)\n );\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n uint256 receiveAmount = action(origin, sendToken, sendAmount, receiveToken, receiver);\n return abi.encode(receiveToken, receiveAmount);\n }\n\n // ====== ACTION TERMS CHECK ==========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address _userProxy,\n bytes calldata _actionData,\n DataFlow _dataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory)\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionKyberTrade: invalid action selector\";\n\n if (_dataFlow == DataFlow.In || _dataFlow == DataFlow.InAndOut)\n return \"ActionKyberTrade: termsOk check invalidated by inbound DataFlow\";\n\n (address origin, // 4:36\n address sendToken, // 36:68\n uint256 sendAmount, // 68:100\n /*address receiveToken*/, // 100:132\n address receiver) = abi.decode(\n _actionData[4:], // 0:4 == selector\n (address,address,uint256,address,address)\n );\n\n // Safety for the next Action that consumes data from this Action\n if (_dataFlow == DataFlow.Out && _userProxy != receiver && address(0) != receiver)\n return \"ActionKyberTrade: UserProxy must be receiver if DataFlow.Out\";\n\n if (sendToken == ETH_ADDRESS) {\n if (origin != _userProxy && origin != address(0))\n return \"ActionKyberTrade: MustHaveUserProxyOrZeroAsOriginForETHTrade\";\n\n if (_userProxy.balance < sendAmount)\n return \"ActionKyberTrade: NotOkUserProxyETHBalance\";\n } else {\n IERC20 sendERC20 = IERC20(sendToken);\n\n // UserProxy is prefunded\n if (origin == _userProxy || origin == address(0)) {\n try sendERC20.balanceOf(_userProxy) returns(uint256 proxySendTokenBalance) {\n if (proxySendTokenBalance < sendAmount)\n return \"ActionKyberTrade: NotOkUserProxySendTokenBalance\";\n } catch {\n return \"ActionKyberTrade: ErrorBalanceOf-1\";\n }\n } else {\n // UserProxy is not prefunded\n try sendERC20.balanceOf(origin) returns(uint256 originSendTokenBalance) {\n if (originSendTokenBalance < sendAmount)\n return \"ActionKyberTrade: NotOkOriginSendTokenBalance\";\n } catch {\n return \"ActionKyberTrade: ErrorBalanceOf-2\";\n }\n\n try sendERC20.allowance(origin, _userProxy)\n returns(uint256 userProxySendTokenAllowance)\n {\n if (userProxySendTokenAllowance < sendAmount)\n return \"ActionKyberTrade: NotOkUserProxySendTokenAllowance\";\n } catch {\n return \"ActionKyberTrade: ErrorAllowance\";\n }\n }\n }\n\n // Make sure Trading Pair is valid\n // @DEV we don't do this as this check is very expensive\n // However, by chaining another action that inspects this data before this\n // one, the same check can likely be made in a cheaper way. E.g.\n // a Provider Action that inspects whether sendToken/receiveToken is\n // on a custom whitelist.\n // try KYBER.getExpectedRate(sendToken, receiveToken, sendAmount)\n // returns (uint256 expectedRate, uint256)\n // {\n // if (expectedRate == 0) return \"ActionKyberTrade:noReserve\";\n // } catch {\n // return \"ActionKyberTrade:getExpectedRate-Error\";\n // }\n\n // STANDARD return string to signal actionConditions Ok\n return OK;\n }\n}\n"
},
"contracts/gelato_actions/uniswap/ActionUniswapTrade.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandardFull} from \"../GelatoActionsStandardFull.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {IUniswapExchange} from \"../../dapp_interfaces/uniswap/IUniswapExchange.sol\";\nimport {IUniswapFactory} from \"../../dapp_interfaces/uniswap/IUniswapFactory.sol\";\n\ncontract ActionUniswapTrade is GelatoActionsStandardFull {\n using SafeMath for uint256;\n using SafeERC20 for IERC20;\n\n IUniswapFactory public immutable UNI_FACTORY;\n\n constructor(IUniswapFactory _uniswapFactory) public {\n UNI_FACTORY =_uniswapFactory;\n }\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n function getActionData(\n address _origin,\n address _sendToken, // exchange\n uint256 _sendAmount, // tokens_sold\n address _receiveToken, // token_addr\n address _receiver\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.action.selector,\n _origin,\n _sendToken,\n _sendAmount,\n _receiveToken,\n _receiver\n );\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_IN_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n // ======= ACTION IMPLEMENTATION DETAILS =========\n /// @dev Always use this function for encoding _actionData off-chain\n /// Will be called by GelatoActionPipeline if Action.dataFlow.None\n function action(\n address _origin,\n address _sendToken, // exchange\n uint256 _sendAmount, // tokens_sold\n address _receiveToken, // token_addr\n address _receiver\n )\n public\n virtual\n delegatecallOnly(\"ActionUniswapTrade.action\")\n returns (uint256 receiveAmount)\n {\n address receiver = _receiver == address(0) ? address(this) : _receiver;\n IUniswapExchange sendTokenExchange;\n\n if (_sendToken == ETH_ADDRESS) {\n IUniswapExchange receiveTokenExchange = UNI_FACTORY.getExchange(\n IERC20(_receiveToken)\n );\n if (receiveTokenExchange != IUniswapExchange(0)) {\n // Swap ETH => ERC20\n try receiveTokenExchange.ethToTokenTransferInput{value: _sendAmount}(\n 1,\n block.timestamp,\n receiver\n )\n returns (uint256 receivedTokens)\n {\n receiveAmount = receivedTokens;\n } catch {\n revert(\"ActionUniswapTrade.action: ethToTokenTransferInput\");\n }\n } else {\n revert(\"ActionUniswapTrade.action: Invalid ReceiveTokenExchange-1\");\n }\n } else {\n IERC20 sendERC20 = IERC20(_sendToken);\n sendTokenExchange = UNI_FACTORY.getExchange(IERC20(sendERC20));\n\n if (sendTokenExchange != IUniswapExchange(0)) {\n\n // origin funds lightweight UserProxy\n if (_origin != address(0) && _origin != address(this)) {\n sendERC20.safeTransferFrom(\n _origin, address(this), _sendAmount, \"ActionUniswapTrade.action:\"\n );\n }\n\n // UserProxy approves Uniswap\n sendERC20.safeIncreaseAllowance(\n address(sendTokenExchange), _sendAmount, \"ActionUniswapTrade.action:\"\n );\n\n if (_receiveToken == ETH_ADDRESS) {\n // swap ERC20 => ETH\n try sendTokenExchange.tokenToEthTransferInput(\n _sendAmount,\n 1,\n block.timestamp,\n receiver\n )\n returns (uint256 receivedETH)\n {\n receiveAmount = receivedETH;\n } catch {\n revert(\"ActionUniswapTrade.action: tokenToEthTransferInput\");\n }\n } else {\n IUniswapExchange receiveTokenExchange = UNI_FACTORY.getExchange(\n IERC20(_receiveToken)\n );\n if (receiveTokenExchange != IUniswapExchange(0)) {\n try sendTokenExchange.tokenToTokenTransferInput(\n _sendAmount,\n 1,\n 1,\n block.timestamp,\n receiver,\n address(_receiveToken)\n )\n returns (uint256 receivedTokens)\n {\n receiveAmount = receivedTokens;\n } catch {\n revert(\"ActionUniswapTrade.action: tokenToTokenTransferInput\");\n }\n } else {\n revert(\"ActionUniswapTrade.action: Invalid ReceiveTokenExchange-2\");\n }\n }\n } else {\n revert(\"ActionUniswapTrade: Invalid SendTokenExchange\");\n }\n }\n\n emit LogTwoWay(\n _origin, // origin\n _sendToken,\n _sendAmount,\n address(sendTokenExchange), // destination\n _receiveToken,\n receiveAmount,\n receiver\n );\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n address origin = abi.decode(_actionData[4:36], (address));\n (address receiveToken, address receiver) = abi.decode(\n _actionData[100:],\n (address,address)\n );\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n action(origin, sendToken, sendAmount, receiveToken, receiver);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address origin, // 4:36\n address sendToken, // 36:68\n uint256 sendAmount, // 68:100\n address receiveToken, // 100:132\n address receiver /* 132:164 */) = abi.decode(\n _actionData[4:], // 0:4 == selector\n (address,address,uint256,address,address)\n );\n uint256 receiveAmount = action(origin, sendToken, sendAmount, receiveToken, receiver);\n return abi.encode(receiveToken, receiveAmount);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n address origin = abi.decode(_actionData[4:36], (address));\n (address receiveToken, address receiver) = abi.decode(\n _actionData[100:],\n (address,address)\n );\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n uint256 receiveAmount = action(origin, sendToken, sendAmount, receiveToken, receiver);\n return abi.encode(receiveToken, receiveAmount);\n }\n\n // ======= ACTION TERMS CHECK =========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address _userProxy,\n bytes calldata _actionData,\n DataFlow _dataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory)\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionUniswapTrade: invalid action selector\";\n\n if (_dataFlow == DataFlow.In || _dataFlow == DataFlow.InAndOut)\n return \"ActionUniswapTrade: termsOk check invalidated by inbound DataFlow\";\n\n (address origin, // 4:36\n address sendToken, // 36:68\n uint256 sendAmount, // 68:100\n address receiveToken, // 100:132\n /*address receiver*/) = abi.decode(\n _actionData[4:], // 0:4 == selector\n (address,address,uint256,address,address)\n );\n\n // Safety for the next Action that consumes data from this Action\n if (\n _dataFlow == DataFlow.Out &&\n _userProxy != abi.decode(_actionData[132:164], (address)) && // receiver\n address(0) != abi.decode(_actionData[132:164], (address)) // receiver\n )\n return \"ActionUniswapTrade: UserProxy must be receiver if DataFlow.Out\";\n\n if (sendToken == ETH_ADDRESS) {\n IERC20 receiveERC20 = IERC20(receiveToken);\n IUniswapExchange receiveTokenExchange = UNI_FACTORY.getExchange(receiveERC20);\n if (receiveTokenExchange == IUniswapExchange(0))\n return \"ActionUniswapTrade: receiveTokenExchangeDoesNotExist-1\";\n\n if (origin != _userProxy && origin != address(0))\n return \"ActionUniswapTrade: MustHaveUserProxyOrZeroAsOriginForETHTrade\";\n if (_userProxy.balance < sendAmount)\n return \"ActionUniswapTrade: NotOkUserProxyETHBalance\";\n } else {\n IERC20 sendERC20 = IERC20(sendToken);\n\n // Make sure sendToken-receiveToken Pair is valid\n IUniswapExchange sendTokenExchange = UNI_FACTORY.getExchange(sendERC20);\n if (sendTokenExchange == IUniswapExchange(0))\n return \"ActionUniswapTrade: sendTokenExchangeDoesNotExist\";\n if (receiveToken != ETH_ADDRESS) {\n IERC20 receiveERC20 = IERC20(receiveToken);\n IUniswapExchange receiveTokenExchange = UNI_FACTORY.getExchange(receiveERC20);\n if (receiveTokenExchange == IUniswapExchange(0))\n return \"ActionUniswapTrade: receiveTokenExchangeDoesNotExist-2\";\n }\n\n // UserProxy is prefunded\n if (origin == _userProxy || origin == address(0)) {\n try sendERC20.balanceOf(_userProxy) returns(uint256 proxySendTokenBalance) {\n if (proxySendTokenBalance < sendAmount)\n return \"ActionUniswapTrade: NotOkUserProxySendTokenBalance\";\n } catch {\n return \"ActionUniswapTrade: ErrorBalanceOf-1\";\n }\n } else {\n // UserProxy is not prefunded\n try sendERC20.balanceOf(origin) returns(uint256 originSendTokenBalance) {\n if (originSendTokenBalance < sendAmount)\n return \"ActionUniswapTrade: NotOkOriginSendTokenBalance\";\n } catch {\n return \"ActionUniswapTrade: ErrorBalanceOf-2\";\n }\n\n try sendERC20.allowance(origin, _userProxy)\n returns(uint256 userProxySendTokenAllowance)\n {\n if (userProxySendTokenAllowance < sendAmount)\n return \"ActionUniswapTrade: NotOkUserProxySendTokenAllowance\";\n } catch {\n return \"ActionUniswapTrade: ErrorAllowance\";\n }\n }\n }\n\n // STANDARD return string to signal actionConditions Ok\n return OK;\n }\n}\n"
},
"contracts/dapp_interfaces/uniswap/IUniswapExchange.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"../../external/IERC20.sol\";\n\ninterface IUniswapExchange {\n function getEthToTokenInputPrice(uint256 ethSold)\n external\n view\n returns (uint256 tokensBought);\n\n function getTokenToEthOutputPrice(uint256 ethbought)\n external\n view\n returns (uint256 tokensToBeSold);\n\n function getTokenToEthInputPrice(uint256 tokensSold)\n external\n view\n returns (uint256 ethBought);\n\n function ethToTokenSwapInput(uint256 MintTokens, uint256 deadline)\n external\n payable\n returns (uint256 tokensBought);\n\n function ethToTokenSwapOutput(uint256 tokens_bought, uint256 deadline)\n external\n payable\n returns (uint256 tokensSold);\n\n function ethToTokenTransferInput(\n uint256 MintTokens,\n uint256 deadline,\n address recipient\n ) external payable returns (uint256 tokensBought);\n\n function tokenToEthSwapInput(\n uint256 tokens_sold,\n uint256 min_eth,\n uint256 deadline\n ) external returns (uint256);\n\n function tokenToEthSwapOutput(\n uint256 eth_bought,\n uint256 max_tokens,\n uint256 deadline\n ) external returns (uint256);\n\n function tokenToTokenSwapInput(\n uint256 tokensSold,\n uint256 MintTokensBought,\n uint256 minEthBought,\n uint256 deadline,\n address tokenAddr\n ) external returns (uint256 tokensBought);\n\n function tokenToEthTransferInput(\n uint256 tokens_sold,\n uint256 min_eth,\n uint256 deadline,\n address recipient\n ) external returns (uint256);\n\n function tokenToTokenTransferInput(\n uint256 tokens_sold,\n uint256 min_tokens_bought,\n uint256 min_eth_bought,\n uint256 deadline,\n address recipient,\n address token_addr\n ) external returns (uint256);\n\n}\n"
},
"contracts/dapp_interfaces/uniswap/IUniswapFactory.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"./IUniswapExchange.sol\";\n\ninterface IUniswapFactory {\n function getExchange(IERC20 token)\n external\n view\n returns (IUniswapExchange exchange);\n}\n"
},
"contracts/gelato_actions/transfer/ActionERC20TransferFrom.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoActionsStandardFull} from \"../GelatoActionsStandardFull.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {Address} from \"../../external/Address.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\n\ncontract ActionERC20TransferFrom is GelatoActionsStandardFull {\n // using SafeERC20 for IERC20; <- internal library methods vs. try/catch\n using Address for address;\n using SafeERC20 for IERC20;\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n /// Use \"address _sendToken\" for Human Readable ABI.\n function getActionData(\n address _user,\n IERC20 _sendToken,\n uint256 _sendAmount,\n address _destination\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.action.selector,\n _user,\n _sendToken,\n _sendAmount,\n _destination\n );\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_IN_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n // ======= ACTION IMPLEMENTATION DETAILS =========\n /// @dev Always use this function for encoding _actionData off-chain\n /// Will be called by GelatoActionPipeline if Action.dataFlow.None\n /// Use \"address _sendToken\" for Human Readable ABI.\n function action(\n address _user,\n IERC20 _sendToken,\n uint256 _sendAmount,\n address _destination\n )\n public\n virtual\n delegatecallOnly(\"ActionERC20TransferFrom.action\")\n {\n _sendToken.safeTransferFrom(\n _user, _destination, _sendAmount, \"ActionERC20TransferFrom.action:\"\n );\n emit LogOneWay(_user, address(_sendToken), _sendAmount, _destination);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n address user = abi.decode(_actionData[4:36], (address));\n address destination = abi.decode(_actionData[100:132], (address));\n (IERC20 sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (IERC20,uint256));\n action(user, sendToken, sendAmount, destination);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address user,\n IERC20 sendToken,\n uint256 sendAmount,\n address destination) = abi.decode(\n _actionData[4:],\n (address,IERC20,uint256,address)\n );\n action(user, sendToken, sendAmount, destination);\n return abi.encode(sendToken, sendAmount);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n address user = abi.decode(_actionData[4:36], (address));\n address destination = abi.decode(_actionData[100:132], (address));\n (IERC20 sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (IERC20,uint256));\n action(user, sendToken, sendAmount, destination);\n return abi.encode(sendToken, sendAmount);\n }\n\n // ======= ACTION TERMS CHECK =========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address _userProxy,\n bytes calldata _actionData,\n DataFlow _dataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory)\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionERC20TransferFrom: invalid action selector\";\n\n if (_dataFlow == DataFlow.In || _dataFlow == DataFlow.InAndOut)\n return \"ActionERC20TransferFrom: termsOk check invalidated by inbound DataFlow\";\n\n (address user, IERC20 sendToken, uint256 sendAmount, ) = abi.decode(\n _actionData[4:],\n (address,IERC20,uint256,address)\n );\n\n try sendToken.balanceOf(user) returns(uint256 sendERC20Balance) {\n if (sendERC20Balance < sendAmount)\n return \"ActionERC20TransferFrom: NotOkUserSendTokenBalance\";\n } catch {\n return \"ActionERC20TransferFrom: ErrorBalanceOf\";\n }\n\n try sendToken.allowance(user, _userProxy) returns(uint256 allowance) {\n if (allowance < sendAmount)\n return \"ActionERC20TransferFrom: NotOkUserProxySendTokenAllowance\";\n } catch {\n return \"ActionERC20TransferFrom: ErrorAllowance\";\n }\n\n return OK;\n }\n}\n"
},
"contracts/gelato_actions/provider/ActionFeeHandler.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoActionsStandardFull} from \"../GelatoActionsStandardFull.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {Address} from \"../../external/Address.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\nimport {Ownable} from \"../../external/Ownable.sol\";\n\ncontract ActionFeeHandler is GelatoActionsStandardFull {\n // using SafeERC20 for IERC20; <- internal library methods vs. try/catch\n using Address for address payable;\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n address payable public immutable provider;\n FeeHandlerFactory public immutable feeHandlerFactory;\n uint256 public immutable feeNum;\n uint256 public immutable feeDen;\n\n constructor(\n address payable _provider,\n FeeHandlerFactory _feeHandlerFactory,\n uint256 _num,\n uint256 _den\n )\n public\n {\n require(_num <= _den, \"ActionFeeHandler.constructor: _num greater than _den\");\n provider = _provider;\n feeHandlerFactory = _feeHandlerFactory;\n feeNum = _num;\n feeDen = _den;\n }\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n function getActionData(address _sendToken, uint256 _sendAmount, address _feePayer)\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(this.action.selector, _sendToken, _sendAmount, _feePayer);\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_IN_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n function isTokenWhitelisted(address _token) public view returns(bool) {\n return feeHandlerFactory.isWhitelistedToken(provider, _token);\n }\n\n // ======= ACTION IMPLEMENTATION DETAILS =========\n /// @dev Use this function for encoding off-chain. DelegatecallOnly!\n function action(address _sendToken, uint256 _sendAmount, address _feePayer)\n public\n virtual\n delegatecallOnly(\"ActionFeeHandler.action\")\n returns (uint256 sendAmountAfterFee)\n {\n uint256 fee = _sendAmount.mul(feeNum).sub(1) / feeDen + 1;\n if (address(this) == _feePayer) {\n if (_sendToken == ETH_ADDRESS) provider.sendValue(fee);\n else IERC20(_sendToken).safeTransfer(provider, fee, \"ActionFeeHandler.action:\");\n } else {\n IERC20(_sendToken).safeTransferFrom(\n _feePayer, provider, fee, \"ActionFeeHandler.action:\"\n );\n }\n sendAmountAfterFee = _sendAmount.sub(fee);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n address feePayer = abi.decode(_actionData[68:], (address));\n action(sendToken, sendAmount, feePayer);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address sendToken, uint256 sendAmount, address feePayer) = abi.decode(\n _actionData[4:],\n (address,uint256,address)\n );\n uint256 sendAmountAfterFee = action(sendToken, sendAmount, feePayer);\n return abi.encode(sendToken, sendAmountAfterFee);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address sendToken, uint256 sendAmount) = abi.decode(_inFlowData, (address,uint256));\n address feePayer = abi.decode(_actionData[68:], (address));\n uint256 sendAmountAfterFee = action(sendToken, sendAmount, feePayer);\n return abi.encode(sendToken, sendAmountAfterFee);\n }\n\n // ======= ACTION TERMS CHECK =========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address _userProxy,\n bytes calldata _actionData,\n DataFlow _dataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory)\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionFeeHandler: invalid action selector\";\n\n if (_dataFlow == DataFlow.In || _dataFlow == DataFlow.InAndOut)\n return \"ActionFeeHandler: termsOk check invalidated by inbound DataFlow\";\n\n (address sendToken, uint256 sendAmount, address feePayer) = abi.decode(\n _actionData[4:],\n (address,uint256,address)\n );\n\n if (sendAmount == 0)\n return \"ActionFeeHandler: Insufficient sendAmount\";\n\n if (!isTokenWhitelisted(sendToken))\n return \"ActionFeeHandler: Token not whitelisted for fee\";\n\n IERC20 sendERC20 = IERC20(sendToken);\n\n if (_userProxy == feePayer) {\n if (sendToken == ETH_ADDRESS) {\n if (_userProxy.balance < sendAmount)\n return \"ActionFeeHandler: NotOkUserProxyETHBalance\";\n } else {\n try sendERC20.balanceOf(_userProxy) returns (uint256 balance) {\n\n if (balance < sendAmount)\n return \"ActionFeeHandler: NotOkUserProxySendTokenBalance\";\n } catch {\n return \"ActionFeeHandler: ErrorBalanceOf\";\n }\n }\n } else {\n if (sendToken == ETH_ADDRESS)\n return \"ActionFeeHandler: CannotTransferFromETH\";\n try sendERC20.balanceOf(feePayer) returns (uint256 balance) {\n if (balance < sendAmount)\n return \"ActionFeeHandler: NotOkFeePayerSendTokenBalance\";\n } catch {\n return \"ActionFeeHandler: ErrorBalanceOf\";\n }\n try sendERC20.allowance(feePayer, _userProxy) returns (uint256 allowance) {\n if (allowance < sendAmount)\n return \"ActionFeeHandler: NotOkFeePayerSendTokenAllowance\";\n } catch {\n return \"ActionFeeHandler: ErrorAllowance\";\n }\n }\n\n return OK;\n }\n}\n\ncontract FeeHandlerFactory {\n\n event Created(\n address indexed provider,\n ActionFeeHandler indexed feeHandler,\n uint256 indexed num\n );\n\n // Denominator => For a fee of 1% => Input num = 100, as 100 / 10.000 = 0.01 == 1%\n uint256 public constant DEN = 10000;\n\n // provider => num => ActionFeeHandler\n mapping(address => mapping(uint256 => ActionFeeHandler)) public feeHandlerByProviderAndNum;\n mapping(address => ActionFeeHandler[]) public feeHandlersByProvider;\n mapping(address => mapping(address => bool)) public isWhitelistedToken;\n\n /// @notice Deploys a new feeHandler instance\n /// @dev Input _num = 100 for 1% fee, _num = 50 for 0.5% fee, etc\n function create(uint256 _num) public returns (ActionFeeHandler feeHandler) {\n require(\n feeHandlerByProviderAndNum[msg.sender][_num] == ActionFeeHandler(0),\n \"FeeHandlerFactory.create: already deployed\"\n );\n require(_num <= DEN, \"FeeHandlerFactory.create: num greater than DEN\");\n feeHandler = new ActionFeeHandler(msg.sender, this, _num, DEN);\n feeHandlerByProviderAndNum[msg.sender][_num] = feeHandler;\n feeHandlersByProvider[msg.sender].push(feeHandler);\n emit Created(msg.sender, feeHandler, _num);\n }\n\n // Provider Token whitelist\n function addTokensToWhitelist(address[] calldata _tokens) external {\n for (uint i; i < _tokens.length; i++) {\n isWhitelistedToken[msg.sender][_tokens[i]] = true;\n }\n }\n\n function removeTokensFromWhitelist(address[] calldata _tokens) external {\n for (uint i; i < _tokens.length; i++) {\n isWhitelistedToken[msg.sender][_tokens[i]] = false;\n }\n }\n}\n"
},
"contracts/gelato_core/GelatoGasPriceOracle.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport \"./interfaces/IGelatoGasPriceOracle.sol\";\nimport \"../external/Ownable.sol\";\n\ncontract GelatoGasPriceOracle is IGelatoGasPriceOracle, Ownable {\n\n address public override oracle;\n\n // This gasPrice is pulled into GelatoCore.exec() via GelatoSysAdmin._getGelatoGasPrice()\n uint256 private gasPrice;\n\n constructor(uint256 _gasPrice) public {\n setOracle(msg.sender);\n setGasPrice(_gasPrice);\n }\n\n modifier onlyOracle {\n require(msg.sender == oracle, \"GelatoGasPriceOracle.onlyOracle\");\n _;\n }\n\n function setOracle(address _newOracle) public override onlyOwner {\n emit LogOracleSet(oracle, _newOracle);\n oracle = _newOracle;\n }\n\n function setGasPrice(uint256 _newGasPrice) public override onlyOracle {\n emit LogGasPriceSet(gasPrice, _newGasPrice);\n gasPrice = _newGasPrice;\n }\n\n function latestAnswer() view external override returns(int256) {\n return int256(gasPrice);\n }\n}\n"
},
"contracts/gelato_core/interfaces/IGelatoGasPriceOracle.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\ninterface IGelatoGasPriceOracle {\n // Owner\n event LogOracleSet(address indexed oldOracle, address indexed newOracle);\n\n // Oracle\n event LogGasPriceSet(uint256 indexed oldGasPrice, uint256 indexed newGasPrice);\n\n // Owner\n\n /// @notice Set new address that can set the gas price\n /// @dev Only callable by owner\n /// @param _newOracle Address of new oracle admin\n function setOracle(address _newOracle) external;\n\n // Oracle\n\n /// @notice Set new gelato gas price\n /// @dev Only callable by oracle admin\n /// @param _newGasPrice New gas price in wei\n function setGasPrice(uint256 _newGasPrice) external;\n\n /// @notice Get address of oracle admin that can set gas prices\n /// @return Oracle Admin address\n function oracle() external view returns(address);\n\n /// @notice Get current gas price\n /// @return Gas price in wei\n function latestAnswer() external view returns(int256);\n}\n"
},
"contracts/gelato_actions/gnosis/ActionPlaceOrderBatchExchange.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoActionsStandardFull} from \"../GelatoActionsStandardFull.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\nimport {IBatchExchange} from \"../../dapp_interfaces/gnosis/IBatchExchange.sol\";\nimport {Task} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\n\n/// @title ActionPlaceOrderBatchExchange\n/// @author Luis Schliesske & Hilmar Orth\n/// @notice Gelato Action that\n/// 1) withdraws funds form user's EOA,\n/// 2) deposits on Batch Exchange,\n/// 3) Places order on batch exchange and\n// 4) requests future withdraw on batch exchange\ncontract ActionPlaceOrderBatchExchange is GelatoActionsStandardFull {\n\n using SafeERC20 for IERC20;\n using SafeMath for uint256;\n\n uint256 public constant MAX_UINT = type(uint256).max;\n uint32 public constant BATCH_TIME = 300;\n\n IBatchExchange public immutable batchExchange;\n\n constructor(IBatchExchange _batchExchange) public { batchExchange = _batchExchange; }\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n /// Use \"address _sellToken\" and \"address _buyToken\" for Human Readable ABI.\n function getActionData(\n address _origin,\n address _sellToken,\n uint128 _sellAmount,\n address _buyToken,\n uint128 _buyAmount,\n uint32 _batchDuration\n )\n public\n pure\n virtual\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.action.selector,\n _origin,\n _sellToken,\n _sellAmount,\n _buyToken,\n _buyAmount,\n _batchDuration\n );\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_IN_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n // ======= ACTION IMPLEMENTATION DETAILS =========\n /// @notice Place order on Batch Exchange and request future withdraw for buy/sell token\n /// @dev Use \"address _sellToken\" and \"address _buyToken\" for Human Readable ABI.\n /// @param _sellToken ERC20 Token to sell on Batch Exchange\n /// @param _sellAmount Amount to sell\n /// @param _buyToken ERC20 Token to buy on Batch Exchange\n /// @param _buyAmount Amount to receive (at least)\n /// @param _batchDuration After how many batches funds should be\n function action(\n address _origin,\n address _sellToken,\n uint128 _sellAmount,\n address _buyToken,\n uint128 _buyAmount,\n uint32 _batchDuration\n )\n public\n virtual\n delegatecallOnly(\"ActionPlaceOrderBatchExchange.action\")\n {\n IERC20 sellToken = IERC20(_sellToken);\n\n // 1. Get current batch id\n uint32 withdrawBatchId = uint32(block.timestamp / BATCH_TIME) + _batchDuration;\n\n // 2. Optional: If light proxy, transfer from funds to proxy\n if (_origin != address(0) && _origin != address(this)) {\n sellToken.safeTransferFrom(\n _origin,\n address(this),\n _sellAmount,\n \"ActionPlaceOrderBatchExchange.action:\"\n );\n }\n\n // 3. Fetch token Ids for sell & buy token on Batch Exchange\n uint16 sellTokenId = batchExchange.tokenAddressToIdMap(_sellToken);\n uint16 buyTokenId = batchExchange.tokenAddressToIdMap(_buyToken);\n\n // 4. Approve _sellToken to BatchExchange Contract\n sellToken.safeIncreaseAllowance(\n address(batchExchange),\n _sellAmount,\n \"ActionPlaceOrderBatchExchange.action:\"\n );\n\n // 5. Deposit _sellAmount on BatchExchange\n try batchExchange.deposit(address(_sellToken), _sellAmount) {\n } catch {\n revert(\"ActionPlaceOrderBatchExchange.deposit _sellToken failed\");\n }\n\n // 6. Place Order on Batch Exchange\n // uint16 buyToken, uint16 sellToken, uint32 validUntil, uint128 buyAmount, uint128 _sellAmount\n try batchExchange.placeOrder(\n buyTokenId,\n sellTokenId,\n withdrawBatchId,\n _buyAmount,\n _sellAmount\n ) {\n } catch {\n revert(\"ActionPlaceOrderBatchExchange.placeOrderfailed\");\n }\n\n // 7. First check if we have a valid future withdraw request for the selltoken\n uint256 sellTokenWithdrawAmount = uint256(_sellAmount);\n try batchExchange.getPendingWithdraw(address(this), _sellToken)\n returns(uint256 reqWithdrawAmount, uint32 requestedBatchId)\n {\n // Check if the withdraw request is not in the past\n if (requestedBatchId >= uint32(block.timestamp / BATCH_TIME)) {\n // If we requested a max_uint withdraw, the withdraw amount will not change\n if (reqWithdrawAmount == MAX_UINT)\n sellTokenWithdrawAmount = reqWithdrawAmount;\n // If not, we add the previous amount to the new one\n else\n sellTokenWithdrawAmount = sellTokenWithdrawAmount.add(reqWithdrawAmount);\n }\n } catch {\n revert(\"ActionPlaceOrderBatchExchange.getPendingWithdraw _sellToken failed\");\n }\n\n // 8. Request future withdraw on Batch Exchange for sellToken\n try batchExchange.requestFutureWithdraw(_sellToken, sellTokenWithdrawAmount, withdrawBatchId) {\n } catch {\n revert(\"ActionPlaceOrderBatchExchange.requestFutureWithdraw _sellToken failed\");\n }\n\n // 9. Request future withdraw on Batch Exchange for buyToken\n // @DEV using MAX_UINT as we don't know in advance how much buyToken we will get\n try batchExchange.requestFutureWithdraw(_buyToken, MAX_UINT, withdrawBatchId) {\n } catch {\n revert(\"ActionPlaceOrderBatchExchange.requestFutureWithdraw _buyToken failed\");\n }\n\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n (address sellToken, uint128 sellAmount) = _handleInFlowData(_inFlowData);\n (address origin,\n address buyToken,\n uint128 buyAmount,\n uint32 batchDuration) = _extractReusableActionData(_actionData);\n\n action(origin, sellToken, sellAmount, buyToken, buyAmount, batchDuration);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address origin,\n address sellToken,\n uint128 sellAmount,\n address buyToken,\n uint128 buyAmount,\n uint32 batchDuration) = abi.decode(\n _actionData[4:],\n (address,address,uint128,address,uint128,uint32)\n );\n action(origin, sellToken, sellAmount, buyToken, buyAmount, batchDuration);\n return abi.encode(sellToken, sellAmount);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address sellToken, uint128 sellAmount) = _handleInFlowData(_inFlowData);\n (address origin,\n address buyToken,\n uint128 buyAmount,\n uint32 batchDuration) = _extractReusableActionData(_actionData);\n\n action(origin, sellToken, sellAmount, buyToken, buyAmount, batchDuration);\n\n return abi.encode(sellToken, sellAmount);\n }\n\n // ======= ACTION TERMS CHECK =========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address _userProxy,\n bytes calldata _actionData,\n DataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory) // actionCondition\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionPlaceOrderBatchExchange: invalid action selector\";\n\n (address origin, address _sellToken, uint128 sellAmount, address buyToken) = abi.decode(\n _actionData[4:132],\n (address,address,uint128,address)\n );\n\n IERC20 sellToken = IERC20(_sellToken);\n\n if (origin == address(0) || origin == _userProxy) {\n try sellToken.balanceOf(_userProxy) returns(uint256 proxySendTokenBalance) {\n if (proxySendTokenBalance < sellAmount)\n return \"ActionPlaceOrderBatchExchange: NotOkUserProxySendTokenBalance\";\n } catch {\n return \"ActionPlaceOrderBatchExchange: ErrorBalanceOf-1\";\n }\n } else {\n try sellToken.balanceOf(origin) returns(uint256 originSendTokenBalance) {\n if (originSendTokenBalance < sellAmount)\n return \"ActionPlaceOrderBatchExchange: NotOkOriginSendTokenBalance\";\n } catch {\n return \"ActionPlaceOrderBatchExchange: ErrorBalanceOf-2\";\n }\n\n try sellToken.allowance(origin, _userProxy)\n returns(uint256 userProxySendTokenAllowance)\n {\n if (userProxySendTokenAllowance < sellAmount)\n return \"ActionPlaceOrderBatchExchange: NotOkUserProxySendTokenAllowance\";\n } catch {\n return \"ActionPlaceOrderBatchExchange: ErrorAllowance\";\n }\n }\n\n uint32 currentBatchId = uint32(block.timestamp / BATCH_TIME);\n\n try batchExchange.getPendingWithdraw(_userProxy, _sellToken)\n returns(uint256, uint32 requestedBatchId)\n {\n // Check if the withdraw request is valid => we need the withdraw to exec first\n if (requestedBatchId != 0 && requestedBatchId < currentBatchId) {\n return \"ActionPlaceOrderBatchExchange WaitUntilPreviousBatchWasWithdrawn sellToken\";\n }\n } catch {\n return \"ActionPlaceOrderBatchExchange getPendingWithdraw failed sellToken\";\n }\n\n try batchExchange.getPendingWithdraw(_userProxy, buyToken)\n returns(uint256, uint32 requestedBatchId)\n {\n // Check if the withdraw request is valid => we need the withdraw to exec first\n if (requestedBatchId != 0 && requestedBatchId < currentBatchId) {\n return \"ActionPlaceOrderBatchExchange WaitUntilPreviousBatchWasWithdrawn buyToken\";\n }\n } catch {\n return \"ActionPlaceOrderBatchExchange getPendingWithdraw failed buyToken\";\n }\n\n // STANDARD return string to signal actionConditions Ok\n return OK;\n }\n\n // ======= ACTION HELPERS =========\n function _handleInFlowData(bytes calldata _inFlowData)\n internal\n pure\n virtual\n returns(address sellToken, uint128 sellAmount)\n {\n uint256 sellAmount256;\n (sellToken, sellAmount256) = abi.decode(_inFlowData, (address,uint256));\n sellAmount = uint128(sellAmount256);\n require(\n sellAmount == sellAmount256,\n \"ActionPlaceOrderBatchExchange._handleInFlowData: sellAmount conversion error\"\n );\n }\n\n function _extractReusableActionData(bytes calldata _actionData)\n internal\n pure\n virtual\n returns (address origin, address buyToken, uint128 buyAmount, uint32 batchDuration)\n {\n (origin,/*sellToken*/,/*sellAmount*/, buyToken, buyAmount, batchDuration) = abi.decode(\n _actionData[4:],\n (address,address,uint128,address,uint128,uint32)\n );\n }\n}"
},
"contracts/gelato_actions/gnosis/ActionPlaceOrderBatchExchangeWithSlippage.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {ActionPlaceOrderBatchExchange} from \"./ActionPlaceOrderBatchExchange.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\nimport {IBatchExchange} from \"../../dapp_interfaces/gnosis/IBatchExchange.sol\";\nimport {Task} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IKyberNetworkProxy} from \"../../dapp_interfaces/kyber/IKyberNetworkProxy.sol\";\n\n/// @title ActionPlaceOrderBatchExchangeWithSlippage\n/// @author Luis Schliesske & Hilmar Orth\n/// @notice Gelato Action that\n/// 1) Calculates buyAmout based on inputted slippage value,\n/// 2) withdraws funds form user's EOA,\n/// 3) deposits on Batch Exchange,\n/// 4) Places order on batch exchange and\n// 5) requests future withdraw on batch exchange\ncontract ActionPlaceOrderBatchExchangeWithSlippage is ActionPlaceOrderBatchExchange {\n\n using SafeMath for uint256;\n using SafeERC20 for address;\n\n IKyberNetworkProxy public immutable KYBER;\n\n constructor(\n IBatchExchange _batchExchange,\n IKyberNetworkProxy _kyberNetworkProxy\n )\n ActionPlaceOrderBatchExchange(_batchExchange)\n public\n {\n KYBER = _kyberNetworkProxy;\n }\n\n /// @dev use this function to encode the data off-chain for the action data field\n /// Use \"address _sellToken\" and \"address _buyToken\" for Human Readable ABI.\n function getActionData(\n address _origin,\n address _sellToken,\n uint128 _sellAmount,\n address _buyToken,\n uint128 _buySlippage,\n uint32 _batchDuration\n )\n public\n pure\n virtual\n override\n returns(bytes memory)\n {\n return abi.encodeWithSelector(\n this.action.selector,\n _origin,\n _sellToken,\n _sellAmount,\n _buyToken,\n _buySlippage,\n _batchDuration\n );\n }\n\n /// @notice Place order on Batch Exchange and request future withdraw for buy/sell token\n /// @dev Use \"address _sellToken\" and \"address _buyToken\" for Human Readable ABI.\n /// @param _sellToken Token to sell on Batch Exchange\n /// @param _sellAmount Amount to sell\n /// @param _buyToken Token to buy on Batch Exchange\n /// @param _buySlippage Slippage inlcuded for the buySlippage in order placement\n /// @param _batchDuration After how many batches funds should be\n function action(\n address _origin,\n address _sellToken,\n uint128 _sellAmount,\n address _buyToken,\n uint128 _buySlippage,\n uint32 _batchDuration\n )\n public\n virtual\n override\n delegatecallOnly(\"ActionPlaceOrderBatchExchangeWithSlippage.action\")\n {\n uint128 expectedBuyAmount = getKyberBuyAmountWithSlippage(\n _sellToken,\n _buyToken,\n _sellAmount,\n _buySlippage\n );\n super.action(\n _origin, _sellToken, _sellAmount, _buyToken, expectedBuyAmount, _batchDuration\n );\n }\n\n function getKyberBuyAmountWithSlippage(\n address _sellToken,\n address _buyToken,\n uint128 _sellAmount,\n uint256 _slippage\n )\n view\n public\n returns(uint128 expectedBuyAmount128)\n {\n uint256 sellTokenDecimals = getDecimals(_sellToken);\n uint256 buyTokenDecimals = getDecimals(_buyToken);\n\n try KYBER.getExpectedRate(address(_sellToken), address(_buyToken), _sellAmount)\n returns(uint256 expectedRate, uint256)\n {\n // Returned values in kyber are in 18 decimals\n // regardless of the destination token's decimals\n uint256 expectedBuyAmount256 = expectedRate\n // * sellAmount, as kyber returns the price for 1 unit\n .mul(_sellAmount)\n // * buy decimal tokens, to convert expectedRate * sellAmount to buyToken decimals\n .mul(10 ** buyTokenDecimals)\n // / sell token decimals to account for sell token decimals of _sellAmount\n .div(10 ** sellTokenDecimals)\n // / 10**18 to account for kyber always returning with 18 decimals\n .div(1e18);\n\n // return amount minus slippage. e.g. _slippage = 5 => 5% slippage\n if(_slippage != 0) {\n expectedBuyAmount256\n = expectedBuyAmount256 - expectedBuyAmount256.mul(_slippage).div(100);\n }\n expectedBuyAmount128 = uint128(expectedBuyAmount256);\n require(\n expectedBuyAmount128 == expectedBuyAmount256,\n \"ActionPlaceOrderBatchExchangeWithSlippage.getKyberRate: uint conversion\"\n );\n } catch {\n revert(\"ActionPlaceOrderBatchExchangeWithSlippage.getKyberRate:Error\");\n }\n }\n\n function getDecimals(address _token)\n internal\n view\n returns(uint256)\n {\n (bool success, bytes memory data) = _token.staticcall{gas: 30000}(\n abi.encodeWithSignature(\"decimals()\")\n );\n\n if (!success) {\n (success, data) = _token.staticcall{gas: 30000}(\n abi.encodeWithSignature(\"DECIMALS()\")\n );\n }\n if (success) return abi.decode(data, (uint256));\n else revert(\"ActionPlaceOrderBatchExchangeWithSlippage.getDecimals:revert\");\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.In\n // => do not use for _actionData encoding\n function execWithDataFlowIn(bytes calldata _actionData, bytes calldata _inFlowData)\n external\n payable\n virtual\n override\n {\n (address sellToken, uint128 sellAmount) = _handleInFlowData(_inFlowData);\n (address origin,\n address buyToken,\n uint128 buySlippage,\n uint32 batchDuration) = _extractReusableActionData(_actionData);\n\n action(origin, sellToken, sellAmount, buyToken, buySlippage, batchDuration);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address origin,\n address sellToken,\n uint128 sellAmount,\n address buyToken,\n uint128 buySlippage,\n uint32 batchDuration) = abi.decode(\n _actionData[4:],\n (address,address,uint128,address,uint128,uint32)\n );\n action(origin, sellToken, sellAmount, buyToken, buySlippage, batchDuration);\n return abi.encode(sellToken, sellAmount);\n }\n\n /// @dev Will be called by GelatoActionPipeline if Action.dataFlow.InAndOut\n // => do not use for _actionData encoding\n function execWithDataFlowInAndOut(\n bytes calldata _actionData,\n bytes calldata _inFlowData\n )\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n (address sellToken, uint128 sellAmount) = _handleInFlowData(_inFlowData);\n (address origin,\n address buyToken,\n uint128 buySlippage,\n uint32 batchDuration) = _extractReusableActionData(_actionData);\n\n action(origin, sellToken, sellAmount, buyToken, buySlippage, batchDuration);\n\n return abi.encode(sellToken, sellAmount);\n }\n\n // ======= ACTION HELPERS =========\n function _handleInFlowData(bytes calldata _inFlowData)\n internal\n pure\n virtual\n override\n returns(address sellToken, uint128 sellAmount)\n {\n uint256 sellAmount256;\n (sellToken, sellAmount256) = abi.decode(_inFlowData, (address,uint256));\n sellAmount = uint128(sellAmount256);\n require(\n sellAmount == sellAmount256,\n \"ActionPlaceOrderBatchExchange._handleInFlowData: sellAmount conversion error\"\n );\n }\n\n function _extractReusableActionData(bytes calldata _actionData)\n internal\n pure\n virtual\n override\n returns (address origin, address buyToken, uint128 buySlippage, uint32 batchDuration)\n {\n (origin,/*sellToken*/,/*sellAmount*/, buyToken, buySlippage, batchDuration) = abi.decode(\n _actionData[4:],\n (address,address,uint128,address,uint128,uint32)\n );\n }\n}"
},
"contracts/gelato_actions/gnosis/ActionWithdrawBatchExchange.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandard} from \"../GelatoActionsStandard.sol\";\nimport {\n IGelatoOutFlowAction\n} from \"../action_pipeline_interfaces/IGelatoOutFlowAction.sol\";\nimport {DataFlow} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {IERC20} from \"../../external/IERC20.sol\";\nimport {IBatchExchange} from \"../../dapp_interfaces/gnosis/IBatchExchange.sol\";\nimport {GelatoBytes} from \"../../libraries/GelatoBytes.sol\";\nimport {SafeERC20} from \"../../external/SafeERC20.sol\";\nimport {SafeMath} from \"../../external/SafeMath.sol\";\n\n/// @title ActionWithdrawBatchExchange\n/// @author Luis Schliesske & Hilmar Orth\n/// @notice Gelato Action that withdraws funds from BatchExchange and returns withdrawamount\n/// @dev Can be used in a GelatoActionPipeline as OutFlowAction.\ncontract ActionWithdrawBatchExchange is GelatoActionsStandard, IGelatoOutFlowAction {\n\n using SafeMath for uint256;\n using SafeERC20 for address;\n\n IBatchExchange public immutable batchExchange;\n\n constructor(IBatchExchange _batchExchange) public { batchExchange = _batchExchange; }\n\n // ======= DEV HELPERS =========\n /// @dev use this function to encode the data off-chain for the action data field\n /// Human Readable ABI: [\"function getActionData(address _token)\"]\n function getActionData(IERC20 _token)\n public\n pure\n returns(bytes memory)\n {\n return abi.encodeWithSelector(this.action.selector, _token);\n }\n\n /// @dev Used by GelatoActionPipeline.isValid()\n function DATA_FLOW_OUT_TYPE() public pure virtual override returns (bytes32) {\n return keccak256(\"TOKEN,UINT256\");\n }\n\n // ======= ACTION IMPLEMENTATION DETAILS =========\n /// @notice Withdraw token from Batch Exchange\n /// @dev delegatecallOnly\n /// Human Readable ABI: [\"function action(address _token)\"]\n /// @param _token Token to withdraw from Batch Exchange\n function action(address _token)\n public\n virtual\n delegatecallOnly(\"ActionWithdrawBatchExchange.action\")\n returns (uint256 withdrawAmount)\n {\n IERC20 token = IERC20(_token);\n uint256 preTokenBalance = token.balanceOf(address(this));\n\n try batchExchange.withdraw(address(this), _token) {\n uint256 postTokenBalance = token.balanceOf(address(this));\n if (postTokenBalance > preTokenBalance)\n withdrawAmount = postTokenBalance - preTokenBalance;\n } catch {\n revert(\"ActionWithdrawBatchExchange.withdraw _token failed\");\n }\n }\n\n ///@dev Will be called by GelatoActionPipeline if Action.dataFlow.Out\n // => do not use for _actionData encoding\n function execWithDataFlowOut(bytes calldata _actionData)\n external\n payable\n virtual\n override\n returns (bytes memory)\n {\n address token = abi.decode(_actionData[4:], (address));\n uint256 withdrawAmount = action(token);\n return abi.encode(token, withdrawAmount);\n }\n\n // ======= ACTION TERMS CHECK =========\n // Overriding and extending GelatoActionsStandard's function (optional)\n function termsOk(\n uint256, // taskReceipId\n address, //_userProxy,\n bytes calldata _actionData,\n DataFlow,\n uint256, // value\n uint256 // cycleId\n )\n public\n view\n virtual\n override\n returns(string memory)\n {\n if (this.action.selector != GelatoBytes.calldataSliceSelector(_actionData))\n return \"ActionWithdrawBatchExchange: invalid action selector\";\n // address token = abi.decode(_actionData[4:], (address));\n // bool tokenWithdrawable = batchExchange.hasValidWithdrawRequest(_userProxy, token);\n // if (!tokenWithdrawable)\n // return \"ActionWithdrawBatchExchange: Token not withdrawable yet\";\n return OK;\n }\n}"
},
"contracts/mocks/gelato_actions/one-off/MockActionDummyRevert.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandard} from \"../../../gelato_actions/GelatoActionsStandard.sol\";\nimport {DataFlow} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract MockActionDummyRevert is GelatoActionsStandard {\n function action(bool) public payable virtual {\n revert(\"MockActionDummyRevert.action: test revert\");\n }\n\n function termsOk(uint256, address, bytes calldata _data, DataFlow, uint256, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n bool isOk = abi.decode(_data, (bool));\n if (isOk) return OK;\n revert(\"MockActionDummyOutOfGas.termsOk\");\n }\n}\n"
},
"contracts/mocks/gelato_actions/one-off/MockActionDummyOutOfGas.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandard} from \"../../../gelato_actions/GelatoActionsStandard.sol\";\nimport {DataFlow} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract MockActionDummyOutOfGas is GelatoActionsStandard {\n\n uint256 public overflowVar;\n\n function action(bool) public payable virtual {\n assert(false);\n }\n\n function placeholder() public pure {\n assert(false);\n }\n\n function termsOk(uint256, address, bytes calldata _data, DataFlow, uint256, uint256)\n public\n view\n virtual\n override\n returns(string memory)\n {\n (bool isOk) = abi.decode(_data, (bool));\n bool _;\n bytes memory __;\n (_, __) = address(this).staticcall(abi.encodePacked(this.placeholder.selector));\n if (isOk) return OK;\n revert(\"MockActionDummyOutOfGas.termsOk\");\n }\n}\n"
},
"contracts/mocks/gelato_actions/one-off/MockActionDummy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {GelatoActionsStandard} from \"../../../gelato_actions/GelatoActionsStandard.sol\";\nimport {DataFlow} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract MockActionDummy is GelatoActionsStandard {\n event LogAction(bool falseOrTrue);\n\n function action(bool _falseOrTrue) public payable virtual {\n emit LogAction(_falseOrTrue);\n }\n\n function termsOk(uint256, address, bytes calldata _data, DataFlow, uint256, uint256)\n external\n view\n virtual\n override\n returns(string memory)\n {\n bool isOk = abi.decode(_data[4:], (bool));\n if (isOk) return OK;\n return \"NotOk\";\n }\n}\n"
},
"contracts/gelato_core/GelatoCore.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoCore, Provider, Task, TaskReceipt} from \"./interfaces/IGelatoCore.sol\";\nimport {GelatoExecutors} from \"./GelatoExecutors.sol\";\nimport {GelatoBytes} from \"../libraries/GelatoBytes.sol\";\nimport {GelatoTaskReceipt} from \"../libraries/GelatoTaskReceipt.sol\";\nimport {SafeMath} from \"../external/SafeMath.sol\";\nimport {IGelatoCondition} from \"../gelato_conditions/IGelatoCondition.sol\";\nimport {IGelatoAction} from \"../gelato_actions/IGelatoAction.sol\";\nimport {IGelatoProviderModule} from \"../gelato_provider_modules/IGelatoProviderModule.sol\";\n\n/// @title GelatoCore\n/// @author Luis Schliesske & Hilmar Orth\n/// @notice Task: submission, validation, execution, and cancellation\n/// @dev Find all NatSpecs inside IGelatoCore\ncontract GelatoCore is IGelatoCore, GelatoExecutors {\n\n using GelatoBytes for bytes;\n using GelatoTaskReceipt for TaskReceipt;\n using SafeMath for uint256;\n\n // Setting State Vars for GelatoSysAdmin\n constructor(GelatoSysAdminInitialState memory _) public {\n gelatoGasPriceOracle = _.gelatoGasPriceOracle;\n oracleRequestData = _.oracleRequestData;\n gelatoMaxGas = _.gelatoMaxGas;\n internalGasRequirement = _.internalGasRequirement;\n minExecutorStake = _.minExecutorStake;\n executorSuccessShare = _.executorSuccessShare;\n sysAdminSuccessShare = _.sysAdminSuccessShare;\n totalSuccessShare = _.totalSuccessShare;\n }\n\n // ================ STATE VARIABLES ======================================\n // TaskReceiptIds\n uint256 public override currentTaskReceiptId;\n // taskReceipt.id => taskReceiptHash\n mapping(uint256 => bytes32) public override taskReceiptHash;\n\n // ================ SUBMIT ==============================================\n function canSubmitTask(\n address _userProxy,\n Provider memory _provider,\n Task memory _task,\n uint256 _expiryDate\n )\n external\n view\n override\n returns(string memory)\n {\n // EXECUTOR CHECKS\n if (!isExecutorMinStaked(executorByProvider[_provider.addr]))\n return \"GelatoCore.canSubmitTask: executor not minStaked\";\n\n // ExpiryDate\n if (_expiryDate != 0)\n if (_expiryDate < block.timestamp)\n return \"GelatoCore.canSubmitTask: expiryDate\";\n\n // Check Provider details\n string memory isProvided;\n if (_userProxy == _provider.addr) {\n if (_task.selfProviderGasLimit < internalGasRequirement.mul(2))\n return \"GelatoCore.canSubmitTask:selfProviderGasLimit too low\";\n isProvided = providerModuleChecks(_userProxy, _provider, _task);\n }\n else isProvided = isTaskProvided(_userProxy, _provider, _task);\n if (!isProvided.startsWithOK())\n return string(abi.encodePacked(\"GelatoCore.canSubmitTask.isProvided:\", isProvided));\n\n // Success\n return OK;\n }\n\n function submitTask(\n Provider memory _provider,\n Task memory _task,\n uint256 _expiryDate\n )\n external\n override\n {\n Task[] memory singleTask = new Task[](1);\n singleTask[0] = _task;\n if (msg.sender == _provider.addr) _handleSelfProviderGasDefaults(singleTask);\n _storeTaskReceipt(false, msg.sender, _provider, 0, singleTask, _expiryDate, 0, 1);\n }\n\n function submitTaskCycle(\n Provider memory _provider,\n Task[] memory _tasks,\n uint256 _expiryDate,\n uint256 _cycles // how many full cycles should be submitted\n )\n external\n override\n {\n if (msg.sender == _provider.addr) _handleSelfProviderGasDefaults(_tasks);\n _storeTaskReceipt(\n true, msg.sender, _provider, 0, _tasks, _expiryDate, 0, _cycles * _tasks.length\n );\n }\n\n function submitTaskChain(\n Provider memory _provider,\n Task[] memory _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits // see IGelatoCore for explanation\n )\n external\n override\n {\n if (_sumOfRequestedTaskSubmits != 0) {\n require(\n _sumOfRequestedTaskSubmits >= _tasks.length,\n \"GelatoCore.submitTaskChain: less requested submits than tasks\"\n );\n }\n if (msg.sender == _provider.addr) _handleSelfProviderGasDefaults(_tasks);\n _storeTaskReceipt(\n true, msg.sender, _provider, 0, _tasks, _expiryDate, 0, _sumOfRequestedTaskSubmits\n );\n }\n\n function _storeTaskReceipt(\n bool _newCycle,\n address _userProxy,\n Provider memory _provider,\n uint256 _index,\n Task[] memory _tasks,\n uint256 _expiryDate,\n uint256 _cycleId,\n uint256 _submissionsLeft\n )\n private\n {\n // Increment TaskReceipt ID storage\n uint256 nextTaskReceiptId = currentTaskReceiptId + 1;\n currentTaskReceiptId = nextTaskReceiptId;\n\n // Generate new Task Receipt\n TaskReceipt memory taskReceipt = TaskReceipt({\n id: nextTaskReceiptId,\n userProxy: _userProxy, // Smart Contract Accounts ONLY\n provider: _provider,\n index: _index,\n tasks: _tasks,\n expiryDate: _expiryDate,\n cycleId: _newCycle ? nextTaskReceiptId : _cycleId,\n submissionsLeft: _submissionsLeft // 0=infinity, 1=once, X=maxTotalExecutions\n });\n\n // Hash TaskReceipt\n bytes32 hashedTaskReceipt = hashTaskReceipt(taskReceipt);\n\n // Store TaskReceipt Hash\n taskReceiptHash[taskReceipt.id] = hashedTaskReceipt;\n\n emit LogTaskSubmitted(taskReceipt.id, hashedTaskReceipt, taskReceipt);\n }\n\n // ================ CAN EXECUTE EXECUTOR API ============================\n // _gasLimit must be gelatoMaxGas for all Providers except SelfProviders.\n function canExec(TaskReceipt memory _TR, uint256 _gasLimit, uint256 _gelatoGasPrice)\n public\n view\n override\n returns(string memory)\n {\n if (!isExecutorMinStaked(executorByProvider[_TR.provider.addr]))\n return \"ExecutorNotMinStaked\";\n\n if (!isProviderLiquid(_TR.provider.addr, _gasLimit, _gelatoGasPrice))\n return \"ProviderIlliquidity\";\n\n string memory res = providerCanExec(\n _TR.userProxy,\n _TR.provider,\n _TR.task(),\n _gelatoGasPrice\n );\n if (!res.startsWithOK()) return res;\n\n bytes32 hashedTaskReceipt = hashTaskReceipt(_TR);\n if (taskReceiptHash[_TR.id] != hashedTaskReceipt) return \"InvalidTaskReceiptHash\";\n\n if (_TR.expiryDate != 0 && _TR.expiryDate <= block.timestamp)\n return \"TaskReceiptExpired\";\n\n // Optional CHECK Condition for user proxies\n if (_TR.task().conditions.length != 0) {\n for (uint i; i < _TR.task().conditions.length; i++) {\n try _TR.task().conditions[i].inst.ok(\n _TR.id,\n _TR.task().conditions[i].data,\n _TR.cycleId\n )\n returns(string memory condition)\n {\n if (!condition.startsWithOK())\n return string(abi.encodePacked(\"ConditionNotOk:\", condition));\n } catch Error(string memory error) {\n return string(abi.encodePacked(\"ConditionReverted:\", error));\n } catch {\n return \"ConditionReverted:undefined\";\n }\n }\n }\n\n // Optional CHECK Action Terms\n for (uint i; i < _TR.task().actions.length; i++) {\n // Only check termsOk if specified, else continue\n if (!_TR.task().actions[i].termsOkCheck) continue;\n\n try IGelatoAction(_TR.task().actions[i].addr).termsOk(\n _TR.id,\n _TR.userProxy,\n _TR.task().actions[i].data,\n _TR.task().actions[i].dataFlow,\n _TR.task().actions[i].value,\n _TR.cycleId\n )\n returns(string memory actionTermsOk)\n {\n if (!actionTermsOk.startsWithOK())\n return string(abi.encodePacked(\"ActionTermsNotOk:\", actionTermsOk));\n } catch Error(string memory error) {\n return string(abi.encodePacked(\"ActionReverted:\", error));\n } catch {\n return \"ActionRevertedNoMessage\";\n }\n }\n\n // Executor Validation\n if (msg.sender == address(this)) return OK;\n else if (msg.sender == executorByProvider[_TR.provider.addr]) return OK;\n else return \"InvalidExecutor\";\n }\n\n // ================ EXECUTE EXECUTOR API ============================\n enum ExecutionResult { ExecSuccess, CanExecFailed, ExecRevert }\n enum ExecutorPay { Reward, Refund }\n\n // Execution Entry Point: tx.gasprice must be greater or equal to _getGelatoGasPrice()\n function exec(TaskReceipt memory _TR) external override {\n\n // Store startGas for gas-consumption based cost and payout calcs\n uint256 startGas = gasleft();\n\n // memcopy of gelatoGasPrice, to avoid multiple storage reads\n uint256 gelatoGasPrice = _getGelatoGasPrice();\n\n // Only assigned executor can execute this function\n require(\n msg.sender == executorByProvider[_TR.provider.addr],\n \"GelatoCore.exec: Invalid Executor\"\n );\n\n // The gas stipend the executor must provide. Special case for SelfProviders.\n uint256 gasLimit\n = _TR.selfProvider() ? _TR.task().selfProviderGasLimit : gelatoMaxGas;\n\n ExecutionResult executionResult;\n string memory reason;\n\n try this.executionWrapper{\n gas: gasleft().sub(internalGasRequirement, \"GelatoCore.exec: Insufficient gas\")\n }(_TR, gasLimit, gelatoGasPrice)\n returns (ExecutionResult _executionResult, string memory _reason)\n {\n executionResult = _executionResult;\n reason = _reason;\n } catch Error(string memory error) {\n executionResult = ExecutionResult.ExecRevert;\n reason = error;\n } catch {\n // If any of the external calls in executionWrapper resulted in e.g. out of gas,\n // Executor is eligible for a Refund, but only if Executor sent gelatoMaxGas.\n executionResult = ExecutionResult.ExecRevert;\n reason = \"GelatoCore.executionWrapper:undefined\";\n }\n\n if (executionResult == ExecutionResult.ExecSuccess) {\n // END-1: SUCCESS => TaskReceipt was deleted in _exec & Reward\n (uint256 executorSuccessFee, uint256 sysAdminSuccessFee) = _processProviderPayables(\n _TR.provider.addr,\n ExecutorPay.Reward,\n startGas,\n gasLimit,\n gelatoGasPrice\n );\n emit LogExecSuccess(msg.sender, _TR.id, executorSuccessFee, sysAdminSuccessFee);\n\n } else if (executionResult == ExecutionResult.CanExecFailed) {\n // END-2: CanExecFailed => No TaskReceipt Deletion & No Refund\n emit LogCanExecFailed(msg.sender, _TR.id, reason);\n\n } else {\n // executionResult == ExecutionResult.ExecRevert\n // END-3.1: ExecReverted NO gelatoMaxGas => No TaskReceipt Deletion & No Refund\n if (startGas < gasLimit)\n emit LogExecReverted(msg.sender, _TR.id, 0, reason);\n else {\n // END-3.2: ExecReverted BUT gelatoMaxGas was used\n // => TaskReceipt Deletion (delete in _exec was reverted) & Refund\n delete taskReceiptHash[_TR.id];\n (uint256 executorRefund,) = _processProviderPayables(\n _TR.provider.addr,\n ExecutorPay.Refund,\n startGas,\n gasLimit,\n gelatoGasPrice\n );\n emit LogExecReverted(msg.sender, _TR.id, executorRefund, reason);\n }\n }\n }\n\n // Used by GelatoCore.exec(), to handle Out-Of-Gas from execution gracefully\n function executionWrapper(\n TaskReceipt memory taskReceipt,\n uint256 _gasLimit, // gelatoMaxGas or task.selfProviderGasLimit\n uint256 _gelatoGasPrice\n )\n external\n returns(ExecutionResult, string memory)\n {\n require(msg.sender == address(this), \"GelatoCore.executionWrapper:onlyGelatoCore\");\n\n // canExec()\n string memory canExecRes = canExec(taskReceipt, _gasLimit, _gelatoGasPrice);\n if (!canExecRes.startsWithOK()) return (ExecutionResult.CanExecFailed, canExecRes);\n\n // Will revert if exec failed => will be caught in exec flow\n _exec(taskReceipt);\n\n // Execution Success: Executor REWARD\n return (ExecutionResult.ExecSuccess, \"\");\n }\n\n function _exec(TaskReceipt memory _TR) private {\n // INTERACTIONS\n // execPayload and proxyReturndataCheck values read from ProviderModule\n bytes memory execPayload;\n bool proxyReturndataCheck;\n\n try IGelatoProviderModule(_TR.provider.module).execPayload(\n _TR.id,\n _TR.userProxy,\n _TR.provider.addr,\n _TR.task(),\n _TR.cycleId\n )\n returns(bytes memory _execPayload, bool _proxyReturndataCheck)\n {\n execPayload = _execPayload;\n proxyReturndataCheck = _proxyReturndataCheck;\n } catch Error(string memory _error) {\n revert(string(abi.encodePacked(\"GelatoCore._exec.execPayload:\", _error)));\n } catch {\n revert(\"GelatoCore._exec.execPayload:undefined\");\n }\n\n // To prevent single task exec reentrancy we delete hash before external call\n delete taskReceiptHash[_TR.id];\n\n // Execution via UserProxy\n (bool success, bytes memory userProxyReturndata) = _TR.userProxy.call(execPayload);\n\n // Check if actions reverts were caught by userProxy\n if (success && proxyReturndataCheck) {\n try _TR.provider.module.execRevertCheck(userProxyReturndata) {\n // success: no revert from providerModule signifies no revert found\n } catch Error(string memory _error) {\n revert(string(abi.encodePacked(\"GelatoCore._exec.execRevertCheck:\", _error)));\n } catch {\n revert(\"GelatoCore._exec.execRevertCheck:undefined\");\n }\n }\n\n // SUCCESS\n if (success) {\n // Optional: Automated Cyclic Task Submissions\n if (_TR.submissionsLeft != 1) {\n _storeTaskReceipt(\n false, // newCycle?\n _TR.userProxy,\n _TR.provider,\n _TR.nextIndex(),\n _TR.tasks,\n _TR.expiryDate,\n _TR.cycleId,\n _TR.submissionsLeft == 0 ? 0 : _TR.submissionsLeft - 1\n );\n }\n } else {\n // FAILURE: reverts, caught or uncaught in userProxy.call, were detected\n // We revert all state from _exec/userProxy.call and catch revert in exec flow\n // Caution: we also revert the deletion of taskReceiptHash.\n userProxyReturndata.revertWithErrorString(\"GelatoCore._exec:\");\n }\n }\n\n function _processProviderPayables(\n address _provider,\n ExecutorPay _payType,\n uint256 _startGas,\n uint256 _gasLimit, // gelatoMaxGas or selfProviderGasLimit\n uint256 _gelatoGasPrice\n )\n private\n returns(uint256 executorCompensation, uint256 sysAdminCompensation)\n {\n uint256 estGasUsed = _startGas - gasleft();\n\n // Provider payable Gas Refund capped at gelatoMaxGas\n // (- consecutive state writes + gas refund from deletion)\n uint256 cappedGasUsed =\n estGasUsed < _gasLimit\n ? estGasUsed + EXEC_TX_OVERHEAD\n : _gasLimit + EXEC_TX_OVERHEAD;\n\n if (_payType == ExecutorPay.Reward) {\n executorCompensation = executorSuccessFee(cappedGasUsed, _gelatoGasPrice);\n sysAdminCompensation = sysAdminSuccessFee(cappedGasUsed, _gelatoGasPrice);\n // ExecSuccess: Provider pays ExecutorSuccessFee and SysAdminSuccessFee\n providerFunds[_provider] = providerFunds[_provider].sub(\n executorCompensation.add(sysAdminCompensation),\n \"GelatoCore._processProviderPayables: providerFunds underflow\"\n );\n executorStake[msg.sender] += executorCompensation;\n sysAdminFunds += sysAdminCompensation;\n } else {\n // ExecFailure: Provider REFUNDS estimated costs to executor\n executorCompensation = cappedGasUsed.mul(_gelatoGasPrice);\n providerFunds[_provider] = providerFunds[_provider].sub(\n executorCompensation,\n \"GelatoCore._processProviderPayables: providerFunds underflow\"\n );\n executorStake[msg.sender] += executorCompensation;\n }\n }\n\n // ================ CANCEL USER / EXECUTOR API ============================\n function cancelTask(TaskReceipt memory _TR) public override {\n // Checks\n require(\n msg.sender == _TR.userProxy || msg.sender == _TR.provider.addr,\n \"GelatoCore.cancelTask: sender\"\n );\n // Effects\n bytes32 hashedTaskReceipt = hashTaskReceipt(_TR);\n require(\n hashedTaskReceipt == taskReceiptHash[_TR.id],\n \"GelatoCore.cancelTask: invalid taskReceiptHash\"\n );\n delete taskReceiptHash[_TR.id];\n emit LogTaskCancelled(_TR.id, msg.sender);\n }\n\n function multiCancelTasks(TaskReceipt[] memory _taskReceipts) external override {\n for (uint i; i < _taskReceipts.length; i++) cancelTask(_taskReceipts[i]);\n }\n\n // Helpers\n function hashTaskReceipt(TaskReceipt memory _TR) public pure override returns(bytes32) {\n return keccak256(abi.encode(_TR));\n }\n\n function _handleSelfProviderGasDefaults(Task[] memory _tasks) private view {\n for (uint256 i; i < _tasks.length; i++) {\n if (_tasks[i].selfProviderGasLimit == 0) {\n _tasks[i].selfProviderGasLimit = gelatoMaxGas;\n } else {\n require(\n _tasks[i].selfProviderGasLimit >= internalGasRequirement.mul(2),\n \"GelatoCore._handleSelfProviderGasDefaults:selfProviderGasLimit too low\"\n );\n }\n if (_tasks[i].selfProviderGasPriceCeil == 0)\n _tasks[i].selfProviderGasPriceCeil = NO_CEIL;\n }\n }\n}\n"
},
"contracts/libraries/GelatoTaskReceipt.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\n\nimport {Task, TaskReceipt} from \"../gelato_core/interfaces/IGelatoCore.sol\";\n\nlibrary GelatoTaskReceipt {\n function task(TaskReceipt memory _TR) internal pure returns(Task memory) {\n return _TR.tasks[_TR.index];\n }\n\n function nextIndex(TaskReceipt memory _TR) internal pure returns(uint256) {\n return _TR.index == _TR.tasks.length - 1 ? 0 : _TR.index + 1;\n }\n\n function selfProvider(TaskReceipt memory _TR) internal pure returns(bool) {\n return _TR.provider.addr == _TR.userProxy;\n }\n}"
},
"contracts/gelato_helpers/GelatoMultiCall.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoCore, TaskReceipt} from \"../gelato_core/interfaces/IGelatoCore.sol\";\nimport {GelatoTaskReceipt} from \"../libraries/GelatoTaskReceipt.sol\";\n\n/// @title GelatoMultiCall - Aggregate results from multiple read-only function calls on GelatoCore\n/// @author Hilmar X (inspired by Maker's Multicall)\ncontract GelatoMultiCall {\n\n using GelatoTaskReceipt for TaskReceipt;\n\n IGelatoCore public immutable gelatoCore;\n\n constructor(IGelatoCore _gelatoCore) public { gelatoCore = _gelatoCore; }\n\n struct Reponse { uint256 taskReceiptId; string response; }\n\n function multiCanExec(\n TaskReceipt[] memory _TR,\n uint256 _gelatoMaxGas,\n uint256 _gelatoGasPrice\n )\n public\n view\n returns (uint256 blockNumber, Reponse[] memory responses)\n {\n blockNumber = block.number;\n responses = new Reponse[](_TR.length);\n for(uint256 i = 0; i < _TR.length; i++) {\n try gelatoCore.canExec(_TR[i], getGasLimit(_TR[i], _gelatoMaxGas), _gelatoGasPrice)\n returns(string memory response)\n {\n responses[i] = Reponse({taskReceiptId: _TR[i].id, response: response});\n } catch {\n responses[i] = Reponse({\n taskReceiptId: _TR[i].id,\n response: \"GelatoMultiCall.multiCanExec: failed\"\n });\n }\n }\n }\n\n function getGasLimit(TaskReceipt memory _TR, uint256 _gelatoMaxGas)\n private\n pure\n returns(uint256 gasLimit)\n {\n gasLimit = _TR.selfProvider() ? _TR.task().selfProviderGasLimit : _gelatoMaxGas;\n }\n\n}"
},
"contracts/gelato_provider_modules/ds_proxy_provider/ProviderModuleDSProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {GelatoProviderModuleStandard} from \"../GelatoProviderModuleStandard.sol\";\nimport {Task} from \"../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {\n DSProxyFactory\n} from \"../../user_proxies/ds_proxy/Proxy.sol\";\nimport {\n IDSProxy\n} from \"../../user_proxies/ds_proxy/interfaces/IProxy.sol\";\nimport {DSAuthority} from \"../../user_proxies/ds_proxy/Auth.sol\";\nimport {GelatoActionPipeline} from \"../../gelato_actions/GelatoActionPipeline.sol\";\n\ncontract ProviderModuleDSProxy is GelatoProviderModuleStandard {\n\n address public immutable dsProxyFactory;\n address public immutable gelatoCore;\n GelatoActionPipeline public immutable gelatoActionPipeline;\n\n constructor(\n address _dsProxyFactory,\n address _gelatoCore,\n GelatoActionPipeline _gelatActionPipeline\n )\n public\n {\n dsProxyFactory = _dsProxyFactory;\n gelatoCore = _gelatoCore;\n gelatoActionPipeline = _gelatActionPipeline;\n }\n\n // ================= GELATO PROVIDER MODULE STANDARD ================\n function isProvided(address _userProxy, address, Task calldata)\n external\n view\n override\n returns(string memory)\n {\n // Was proxy deployed from correct factory?\n bool proxyOk = DSProxyFactory(dsProxyFactory).isProxy(\n _userProxy\n );\n if (!proxyOk) return \"ProviderModuleGelatoUserProxy.isProvided:InvalidUserProxy\";\n\n // Is gelato core whitelisted?\n DSAuthority authority = IDSProxy(_userProxy).authority();\n bool isGelatoWhitelisted = authority.canCall(gelatoCore, _userProxy, IDSProxy(_userProxy).execute.selector);\n if (!isGelatoWhitelisted) return \"ProviderModuleGelatoUserProxy.isProvided:GelatoCoreNotWhitelisted\";\n\n return OK;\n }\n\n /// @dev DS PROXY ONLY ALLOWS DELEGATE CALL for single actions, that's why we also use multisend\n function execPayload(uint256, address, address, Task calldata _task, uint256)\n external\n view\n override\n returns(bytes memory payload, bool)\n {\n // Action.Operation encoded into gelatoActionPipelinePayload and handled by GelatoActionPipeline\n bytes memory gelatoActionPipelinePayload = abi.encodeWithSelector(\n GelatoActionPipeline.execActionsAndPipeData.selector,\n _task.actions\n );\n\n // Delegate call by default\n payload = abi.encodeWithSignature(\n \"execute(address,bytes)\",\n gelatoActionPipeline, // to\n gelatoActionPipelinePayload // data\n );\n\n }\n}"
},
"contracts/user_proxies/ds_proxy/Proxy.sol": {
"content": "// proxy.sol - execute actions atomically through the proxy's identity\n\n// Copyright (C) 2017 DappHub, LLC\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity >=0.5.0;\n\nimport {DSAuth} from \"./Auth.sol\";\nimport {DSNote} from \"./Note.sol\";\n\n// DSProxy\n// Allows code execution using a persistant identity This can be very\n// useful to execute a sequence of atomic actions. Since the owner of\n// the proxy can be changed, this allows for dynamic ownership models\n// i.e. a multisig\ncontract DSProxy is DSAuth, DSNote {\n DSProxyCache public cache; // global cache for contracts\n\n constructor(address _cacheAddr) public {\n setCache(_cacheAddr);\n }\n\n fallback() external {\n }\n\n receive() external payable {\n }\n\n // use the proxy to execute calldata _data on contract _code\n function execute(bytes memory _code, bytes memory _data)\n public\n payable\n returns (address target, bytes memory response)\n {\n target = cache.read(_code);\n if (target == address(0)) {\n // deploy contract & store its address in cache\n target = cache.write(_code);\n }\n\n response = execute(target, _data);\n }\n\n function execute(address _target, bytes memory _data)\n public\n auth\n note\n payable\n returns (bytes memory response)\n {\n require(_target != address(0), \"ds-proxy-target-address-required\");\n\n // call contract in current context\n assembly {\n let succeeded := delegatecall(sub(gas(), 5000), _target, add(_data, 0x20), mload(_data), 0, 0)\n let size := returndatasize()\n\n response := mload(0x40)\n mstore(0x40, add(response, and(add(add(size, 0x20), 0x1f), not(0x1f))))\n mstore(response, size)\n returndatacopy(add(response, 0x20), 0, size)\n\n switch iszero(succeeded)\n case 1 {\n // throw if delegatecall failed\n revert(add(response, 0x20), size)\n }\n }\n }\n\n //set new cache\n function setCache(address _cacheAddr)\n public\n auth\n note\n returns (bool)\n {\n require(_cacheAddr != address(0), \"ds-proxy-cache-address-required\");\n cache = DSProxyCache(_cacheAddr); // overwrite cache\n return true;\n }\n}\n\n// DSProxyFactory\n// This factory deploys new proxy instances through build()\n// Deployed proxy addresses are logged\ncontract DSProxyFactory {\n event Created(address indexed sender, address indexed owner, address proxy, address cache);\n mapping(address=>bool) public isProxy;\n DSProxyCache public cache;\n\n constructor() public {\n cache = new DSProxyCache();\n }\n\n // deploys a new proxy instance\n // sets owner of proxy to caller\n function build() public returns (address payable proxy) {\n proxy = build(msg.sender);\n }\n\n // deploys a new proxy instance\n // sets custom owner of proxy\n function build(address owner) public returns (address payable proxy) {\n proxy = address(new DSProxy(address(cache)));\n emit Created(msg.sender, owner, address(proxy), address(cache));\n DSProxy(proxy).setOwner(owner);\n isProxy[proxy] = true;\n }\n}\n\n// DSProxyCache\n// This global cache stores addresses of contracts previously deployed\n// by a proxy. This saves gas from repeat deployment of the same\n// contracts and eliminates blockchain bloat.\n\n// By default, all proxies deployed from the same factory store\n// contracts in the same cache. The cache a proxy instance uses can be\n// changed. The cache uses the sha3 hash of a contract's bytecode to\n// lookup the address\ncontract DSProxyCache {\n mapping(bytes32 => address) cache;\n\n function read(bytes memory _code) public view returns (address) {\n bytes32 hash = keccak256(_code);\n return cache[hash];\n }\n\n function write(bytes memory _code) public returns (address target) {\n assembly {\n target := create(0, add(_code, 0x20), mload(_code))\n switch iszero(extcodesize(target))\n case 1 {\n // throw if contract failed to deploy\n revert(0, 0)\n }\n }\n bytes32 hash = keccak256(_code);\n cache[hash] = target;\n }\n}"
},
"contracts/user_proxies/ds_proxy/interfaces/IProxy.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity >=0.5.0;\n\nimport {DSAuthority} from \"../Auth.sol\";\n\ninterface IDSProxy {\n\n function execute(address _target, bytes calldata _data)\n external\n returns (bytes memory response);\n\n function authority()\n external\n view\n returns (DSAuthority);\n}"
},
"contracts/user_proxies/ds_proxy/Auth.sol": {
"content": "// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity >=0.4.23;\n\n\nabstract contract DSAuthority {\n function canCall(\n address src, address dst, bytes4 sig\n ) public view virtual returns (bool);\n}\n\ncontract DSAuthEvents {\n event LogSetAuthority (address indexed authority);\n event LogSetOwner (address indexed owner);\n}\n\ncontract DSAuth is DSAuthEvents {\n DSAuthority public authority;\n address public owner;\n\n constructor() public {\n owner = msg.sender;\n emit LogSetOwner(msg.sender);\n }\n\n function setOwner(address owner_)\n public\n auth\n {\n owner = owner_;\n emit LogSetOwner(owner);\n }\n\n function setAuthority(DSAuthority authority_)\n public\n auth\n {\n authority = authority_;\n emit LogSetAuthority(address(authority));\n }\n\n modifier auth {\n require(isAuthorized(msg.sender, msg.sig), \"ds-auth-unauthorized\");\n _;\n }\n\n function isAuthorized(address src, bytes4 sig) internal view returns (bool) {\n if (src == address(this)) {\n return true;\n } else if (src == owner) {\n return true;\n } else if (authority == DSAuthority(0)) {\n return false;\n } else {\n return authority.canCall(src, address(this), sig);\n }\n }\n}"
},
"contracts/user_proxies/ds_proxy/Note.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\n\n/// note.sol -- the `note' modifier, for logging calls as events\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see <http://www.gnu.org/licenses/>.\n\npragma solidity >=0.4.23;\n\ncontract DSNote {\n event LogNote(\n bytes4 indexed sig,\n address indexed guy,\n bytes32 indexed foo,\n bytes32 indexed bar,\n uint256 wad,\n bytes fax\n ) anonymous;\n\n modifier note {\n bytes32 foo;\n bytes32 bar;\n uint256 wad;\n\n assembly {\n foo := calldataload(4)\n bar := calldataload(36)\n wad := callvalue()\n }\n\n emit LogNote(msg.sig, msg.sender, foo, bar, wad, msg.data);\n\n _;\n }\n}"
},
"contracts/user_proxies/ds_proxy/Guard.sol": {
"content": "// guard.sol -- simple whitelist implementation of DSAuthority\n\n// Copyright (C) 2017 DappHub, LLC\n\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n\n// You should have received a copy of the GNU General Public License\n// along with this program. If not, see <http://www.gnu.org/licenses/>.\n\n// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity >=0.4.23;\n\nimport {DSAuth, DSAuthority} from \"./Auth.sol\";\n\ncontract DSGuardEvents {\n event LogPermit(\n bytes32 indexed src,\n bytes32 indexed dst,\n bytes32 indexed sig\n );\n\n event LogForbid(\n bytes32 indexed src,\n bytes32 indexed dst,\n bytes32 indexed sig\n );\n}\n\ncontract DSGuard is DSAuth, DSAuthority, DSGuardEvents {\n bytes32 constant public ANY = bytes32(uint(-1));\n\n mapping (bytes32 => mapping (bytes32 => mapping (bytes32 => bool))) acl;\n\n function canCall(\n address src_, address dst_, bytes4 sig\n ) public view override returns (bool) {\n bytes32 src = bytes32(bytes20(src_));\n bytes32 dst = bytes32(bytes20(dst_));\n\n return acl[src][dst][sig]\n || acl[src][dst][ANY]\n || acl[src][ANY][sig]\n || acl[src][ANY][ANY]\n || acl[ANY][dst][sig]\n || acl[ANY][dst][ANY]\n || acl[ANY][ANY][sig]\n || acl[ANY][ANY][ANY];\n }\n\n function permit(bytes32 src, bytes32 dst, bytes32 sig) public auth {\n acl[src][dst][sig] = true;\n emit LogPermit(src, dst, sig);\n }\n\n function forbid(bytes32 src, bytes32 dst, bytes32 sig) public auth {\n acl[src][dst][sig] = false;\n emit LogForbid(src, dst, sig);\n }\n\n function permit(address src, address dst, bytes32 sig) public {\n permit(bytes32(bytes20(src)), bytes32(bytes20(dst)), sig);\n }\n function forbid(address src, address dst, bytes32 sig) public {\n forbid(bytes32(bytes20(src)), bytes32(bytes20(dst)), sig);\n }\n\n}\n\ncontract DSGuardFactory {\n mapping (address => bool) public isGuard;\n\n function newGuard() public returns (DSGuard guard) {\n guard = new DSGuard();\n guard.setOwner(msg.sender);\n isGuard[address(guard)] = true;\n }\n}"
},
"contracts/mocks/provider_modules/gelato_user_proxy_provider/MockProviderModuleGelatoUserProxyExecRevertCheckOk.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {\n MockProviderModuleGelatoUserProxyExecRevertCheckRevert\n} from \"./MockProviderModuleGelatoUserProxyExecRevertCheckRevert.sol\";\nimport {Action} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\nimport {\n IGelatoUserProxy\n} from \"../../../user_proxies/gelato_user_proxy/interfaces/IGelatoUserProxy.sol\";\n\ncontract MockProviderModuleGelatoUserProxyExecRevertCheckOk is\n MockProviderModuleGelatoUserProxyExecRevertCheckRevert\n{\n function execRevertCheck(bytes memory)\n public\n pure\n virtual\n override\n {\n // do nothing\n }\n}"
},
"contracts/user_proxies/ds_proxy/scripts/SubmitTaskScript.sol": {
"content": "// \"SPDX-License-Identifier: UNLICENSED\"\npragma solidity ^0.6.10;\npragma experimental ABIEncoderV2;\n\nimport {IGelatoCore, Provider, Task} from \"../../../gelato_core/interfaces/IGelatoCore.sol\";\n\ncontract SubmitTaskScript {\n\n IGelatoCore public immutable gelatoCore;\n\n constructor(address _gelatoCore) public {\n gelatoCore = IGelatoCore(_gelatoCore);\n }\n\n /// @dev will be delegate called by ds_proxy\n function submitTask(Provider memory _provider, Task memory _task, uint256 _expiryDate)\n public\n {\n gelatoCore.submitTask(_provider, _task, _expiryDate);\n }\n\n /// @dev will be delegate called by ds_proxy\n function submitTaskCycle(\n Provider memory _provider,\n Task[] memory _tasks,\n uint256 _expiryDate,\n uint256 _cycles\n )\n public\n {\n gelatoCore.submitTaskCycle(_provider, _tasks, _expiryDate, _cycles);\n }\n\n /// @dev will be delegate called by ds_proxy\n function submitTaskChain(\n Provider memory _provider,\n Task[] memory _tasks,\n uint256 _expiryDate,\n uint256 _sumOfRequestedTaskSubmits\n )\n public\n {\n gelatoCore.submitTaskCycle(_provider, _tasks, _expiryDate, _sumOfRequestedTaskSubmits);\n }\n}\n"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"abi",
"evm.bytecode",
"evm.deployedBytecode",
"evm.methodIdentifiers",
"metadata",
"devdoc",
"userdoc",
"storageLayout",
"evm.gasEstimates"
],
"": ["ast"]
}
},
"metadata": {
"useLiteralContent": true
}
}
}