Gelato-automations/contracts/gelato/ProviderModuleDSA.sol
2020-10-23 16:46:29 +02:00

122 lines
4.7 KiB
Solidity

// "SPDX-License-Identifier: UNLICENSED"
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;
import {
GelatoProviderModuleStandard
} from "@gelatonetwork/core/contracts/provider_modules/GelatoProviderModuleStandard.sol";
import {
Task
} from "@gelatonetwork/core/contracts/gelato_core/interfaces/IGelatoCore.sol";
import {AccountInterface} from "../interfaces/InstaDapp.sol";
import {
ConnectGelatoProviderPayment
} from "../connectors/ConnectGelatoProviderPayment.sol";
/// @notice Gelato Provider Module for the InstaDapp DSA
/// @dev Used by Provider to sanity check any third-party Tasks they pay for
/// @author Gelato Network Team
contract ProviderModuleDSA is GelatoProviderModuleStandard {
/// @dev DSA must have gelatoCore as auth and gelatoCore is emitted as origin of cast
address public immutable gelatoCore;
/// @notice A trusted Connector to pay Provider for e.g. User's Gelato gas usage.
/// @dev Automated InstaDapp Use Cases that rely on a third-party Gelato Provider
/// to pay for automation will likely have this Connector in their spells.
address public immutable connectGelatoProviderPayment;
// TO DO: remove `public` after hardhat file import bugfix
// https://github.com/nomiclabs/hardhat/issues/916
constructor(address _gelatoCore, address _connectGelatoProviderPayment)
public
{
gelatoCore = _gelatoCore;
connectGelatoProviderPayment = _connectGelatoProviderPayment;
}
// ================= GELATO PROVIDER MODULE STANDARD ================
/// @notice Standard Gelato function for Provider's Task sanity checks
/// @dev For more Provider security we should also check:
/// - ListInterface(index.list()).accountID(_userProxy)
/// - if (shield) connectors.isStaticConnector(targets)
/// - connectors.isConnector(targets)
/// But we skip those here to save gas
/// @param _userProxy The DSA which submitted the Task
/// @return whether the Provider is pays for the Task.
function isProvided(
address _userProxy,
address,
Task calldata
) public view virtual override returns (string memory) {
try AccountInterface(_userProxy).isAuth(gelatoCore) returns (
bool gelatoCoreIsAuth
) {
if (!gelatoCoreIsAuth)
return "ProviderModuleDSA.isProvided:GelatoCoreNotAuth";
} catch Error(string memory err) {
return
string(abi.encodePacked("ProviderModuleDSA.isProvided:", err));
} catch {
return "ProviderModuleDSA.isProvided:undefined";
}
return OK;
}
/// @notice Gelato Standard Provider function to retrieve payload for the DSA
/// @dev This formats the Gelato Task into a DSA compatible payload and
/// it also inserts the _provider into the ConnectGelatoProviderPayment payload,
/// to make sure that it cannot be spoofed thus e.g. securing Provider payments.
/// @param _provider the actual Provider address verified by GelatoCore system.
/// @param _task The Task in Gelato format.
/// @return The execution payload in DSA format
/// @return bool=false because no execRevert checks must be handled on GelatoCore
/// because the DSA reverts, if a spell revert is caught during delegatecall.
function execPayload(
uint256,
address,
address _provider,
Task calldata _task,
uint256
) public view virtual override returns (bytes memory, bool) {
address[] memory targets = new address[](_task.actions.length);
for (uint256 i = 0; i < _task.actions.length; i++)
targets[i] = _task.actions[i].addr;
bytes[] memory datas = new bytes[](_task.actions.length);
for (uint256 i = 0; i < _task.actions.length; i++) {
if (_task.actions[i].addr == connectGelatoProviderPayment)
datas[i] = _replaceProvider(_provider, _task.actions[i].data);
else datas[i] = _task.actions[i].data;
}
return (
abi.encodeWithSelector(
AccountInterface.cast.selector,
targets,
datas,
gelatoCore
),
false
);
}
function _replaceProvider(address _provider, bytes calldata _data)
internal
pure
returns (bytes memory)
{
(, address token, uint256 amt, uint256 getID, uint256 setID) = abi
.decode(_data[4:], (address, address, uint256, uint256, uint256));
return
abi.encodeWithSelector(
ConnectGelatoProviderPayment.payProvider.selector,
_provider,
token,
amt,
getID,
setID
);
}
}