97 lines
2.3 KiB
Solidity
97 lines
2.3 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity 0.8.10;
|
|
|
|
import "../core/HasSignature712.sol";
|
|
import "../utils/TimeChecker.sol";
|
|
|
|
interface IToken {
|
|
function transferFrom(
|
|
address from,
|
|
address to,
|
|
uint256 amount
|
|
) external returns (bool);
|
|
|
|
function signApprove(
|
|
address spender,
|
|
uint256 amount,
|
|
uint256 startTime,
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
) external;
|
|
}
|
|
|
|
contract ExecuteRelay is HasSignature712, TimeChecker {
|
|
constructor() HasSignature712("ExecuteRelay", "1") {}
|
|
|
|
address public tokenAddress;
|
|
|
|
event MethodExecuted(
|
|
address indexed sender,
|
|
address indexed target,
|
|
bytes data,
|
|
uint256 gasUsed,
|
|
uint256 tokenAmount
|
|
);
|
|
|
|
function execute(
|
|
address sender,
|
|
address target,
|
|
uint256 value,
|
|
bytes calldata data,
|
|
uint256 startTime,
|
|
uint256 saltNonce,
|
|
bytes calldata signature
|
|
) external payable signatureValid(signature) timeValid(startTime) {
|
|
bytes32 messageHash = getMessageHash(
|
|
target,
|
|
value,
|
|
data,
|
|
startTime,
|
|
saltNonce
|
|
);
|
|
uint256 gasStart = gasleft();
|
|
checkSigner712(sender, messageHash, signature);
|
|
uint256 gasPrice = tx.gasprice;
|
|
_call(target, value, data);
|
|
uint256 gasUsed = gasStart - gasleft();
|
|
uint256 tokenAmount = gasPrice * gasUsed; // TODO:: calc real token amount
|
|
IToken(tokenAddress).signApprove(
|
|
sender,
|
|
tokenAmount,
|
|
startTime,
|
|
saltNonce,
|
|
signature
|
|
);
|
|
IToken(tokenAddress).transferFrom(sender, address(this), tokenAmount);
|
|
_useSignature(signature);
|
|
emit MethodExecuted(sender, target, data, gasUsed, tokenAmount);
|
|
}
|
|
|
|
/**
|
|
* @dev Execute an operation's call.
|
|
*
|
|
* Emits a {CallExecuted} event.
|
|
*/
|
|
function _call(address target, uint256 value, bytes calldata data) private {
|
|
(bool success, ) = target.call{value: value}(data);
|
|
require(success, "ExecuteRelay: underlying transaction reverted");
|
|
}
|
|
|
|
function getMessageHash(
|
|
address _target,
|
|
uint256 _value,
|
|
bytes calldata _data,
|
|
uint256 _startTime,
|
|
uint256 _saltNonce
|
|
) public pure returns (bytes32) {
|
|
bytes memory encoded = abi.encodePacked(
|
|
_target,
|
|
_value,
|
|
_data,
|
|
_startTime,
|
|
_saltNonce
|
|
);
|
|
return keccak256(encoded);
|
|
}
|
|
}
|