Fix bug related to refunding of application budget if delivery fails (#42)

* Fix bug related to refunding of application budget if delivery doesn't succeed

* forge fmt

* Fix some yul error

* forge fmt
This commit is contained in:
derpy-duck 2023-01-18 21:35:52 -05:00 committed by GitHub
parent 177862cd78
commit 9d51fd54ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 6 deletions

View File

@ -358,7 +358,7 @@ contract CoreRelayer is CoreRelayerGovernance {
uint256 postGas = gasleft();
// refund unused gas budget
uint256 weiToRefund = 0;
uint256 weiToRefund = internalInstruction.applicationBudgetTarget;
if (success) {
weiToRefund = (internalInstruction.executionParameters.gasLimit - (preGas - postGas))
* internalInstruction.maximumRefundTarget / internalInstruction.executionParameters.gasLimit;
@ -409,11 +409,11 @@ contract CoreRelayer is CoreRelayerGovernance {
}
}
uint256 applicationBudgetPaid = (success ? internalInstruction.applicationBudgetTarget : 0);
uint256 wormholeFeePaid = getForwardingRequest().isValid ? wormhole.messageFee() : 0;
uint256 relayerRefundAmount = msg.value - weiToRefund - applicationBudgetPaid - wormholeFeePaid;
// refund the rest to relayer
msg.sender.call{
value: msg.value - weiToRefund - internalInstruction.applicationBudgetTarget
- (getForwardingRequest().isValid ? wormhole.messageFee() : 0)
}("");
msg.sender.call{value: relayerRefundAmount}("");
}
//REVISE, consider implementing this system into the RelayProvider.

View File

@ -74,7 +74,7 @@ contract MockRelayerIntegration is IWormholeReceiver {
targetChain: targetChainId,
targetAddress: relayer.toWormholeFormat(address(destination)),
refundAddress: relayer.toWormholeFormat(address(refundAddress)), // This will be ignored on the target chain if the intent is to perform a forward
computeBudget: msg.value - 2 * wormhole.messageFee(),
computeBudget: msg.value - 2 * wormhole.messageFee() - applicationBudget,
applicationBudget: applicationBudget, // not needed in this case.
relayParameters: relayer.getDefaultRelayParams() //no overrides
});

View File

@ -357,6 +357,49 @@ contract TestCoreRelayer is Test {
);
}
function testFundsCorrectIfApplicationCallReverts(
GasParameters memory gasParams,
bytes memory message,
uint32 applicationBudget
) public {
(uint16 SOURCE_CHAIN_ID, uint16 TARGET_CHAIN_ID, Contracts memory source, Contracts memory target) =
standardAssumeAndSetupTwoChains(gasParams, 1000000);
vm.recordLogs();
uint256 refundAddressBalance = target.refundAddress.balance;
uint256 relayerBalance = target.relayer.balance;
uint256 rewardAddressBalance = source.rewardAddress.balance;
uint256 payment = source.coreRelayer.quoteGasDeliveryFee(TARGET_CHAIN_ID, 21000, source.relayProvider)
+ source.wormhole.messageFee() + applicationBudget;
source.integration.sendMessageGeneral{value: payment}(
abi.encodePacked(uint8(0), message),
TARGET_CHAIN_ID,
address(target.integration),
address(target.refundAddress),
applicationBudget,
1
);
genericRelayer(SOURCE_CHAIN_ID, 2);
uint256 USDcost = uint256(payment) * gasParams.sourceNativePrice
- (target.refundAddress.balance - refundAddressBalance) * gasParams.targetNativePrice;
uint256 relayerProfit = uint256(gasParams.sourceNativePrice)
* (source.rewardAddress.balance - rewardAddressBalance)
- gasParams.targetNativePrice * (relayerBalance - target.relayer.balance);
uint256 howMuchGasRelayerCouldHavePaidForAndStillProfited =
relayerProfit / gasParams.targetGasPrice / gasParams.targetNativePrice;
assertTrue(
USDcost == relayerProfit + 2 * map[SOURCE_CHAIN_ID].wormhole.messageFee() * gasParams.sourceNativePrice,
"We paid the exact amount"
);
}
function testForward(GasParameters memory gasParams, bytes memory message) public {
(uint16 SOURCE_CHAIN_ID, uint16 TARGET_CHAIN_ID, Contracts memory source, Contracts memory target) =
standardAssumeAndSetupTwoChains(gasParams, 1000000);