trustless-generic-relayer/ethereum/contracts/coreRelayer/ForwardWrapper.sol

67 lines
2.9 KiB
Solidity

// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../interfaces/IWormholeReceiver.sol";
import "../interfaces/IWormhole.sol";
import "../interfaces/IRelayProvider.sol";
import "../interfaces/IForwardInstructionViewer.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
import "../interfaces/IForwardWrapper.sol";
contract ForwardWrapper {
IForwardInstructionViewer forwardInstructionViewer;
IWormhole wormhole;
error RequesterNotCoreRelayer();
error ForwardNotSufficientlyFunded(uint256 extraAmountNeeded);
constructor(address _wormholeRelayer, address _wormhole) {
forwardInstructionViewer = IForwardInstructionViewer(_wormholeRelayer);
wormhole = IWormhole(_wormhole);
}
function executeInstruction(
IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction,
bytes[] memory signedVaas
) public payable returns (bool callToTargetContractSucceeded, uint256 transactionFeeRefundAmount) {
if (msg.sender != address(forwardInstructionViewer)) {
revert RequesterNotCoreRelayer();
}
uint256 preGas = gasleft();
// Calls the 'receiveWormholeMessages' endpoint on the contract 'instruction.targetAddress'
// (with the gas limit and value specified in instruction, and 'encodedVMs' as the input)
(callToTargetContractSucceeded,) = forwardInstructionViewer.fromWormholeFormat(instruction.targetAddress).call{
gas: instruction.executionParameters.gasLimit,
value: instruction.receiverValueTarget
}(abi.encodeCall(IWormholeReceiver.receiveWormholeMessages, (signedVaas, new bytes[](0))));
uint256 postGas = gasleft();
// Calculate the amount of gas used in the call (upperbounding at the gas limit, which shouldn't have been exceeded)
uint256 gasUsed = (preGas - postGas) > instruction.executionParameters.gasLimit
? instruction.executionParameters.gasLimit
: (preGas - postGas);
// Calculate the amount of maxTransactionFee to refund (multiply the maximum refund by the fraction of gas unused)
transactionFeeRefundAmount = (instruction.executionParameters.gasLimit - gasUsed)
* instruction.maximumRefundTarget / instruction.executionParameters.gasLimit;
IWormholeRelayerInternalStructs.ForwardInstruction memory forwardInstruction =
forwardInstructionViewer.getForwardInstruction();
if (forwardInstruction.isValid) {
uint256 feeForForward = transactionFeeRefundAmount + forwardInstruction.msgValue;
if (feeForForward < forwardInstruction.totalFee) {
revert ForwardNotSufficientlyFunded(forwardInstruction.totalFee - feeForForward);
}
}
if (!callToTargetContractSucceeded) {
msg.sender.call{value: msg.value}("");
}
}
}