Application Budget Bugfixes (#60)
* Application Budget Fixes and Tests * Adding application budget to redelivery test * Application Budget Test with Redelivery Works * remove console log import * Remove console logs from tests * Remove console logs from mockrelayerintegration * Use uint32.max and fix outOfFund error in tests * Removed unnecessary require
This commit is contained in:
parent
7cd5b5871b
commit
5a3ff82c43
|
@ -8,8 +8,6 @@ import "../libraries/external/BytesLib.sol";
|
|||
import "./CoreRelayerGovernance.sol";
|
||||
import "./CoreRelayerStructs.sol";
|
||||
|
||||
import "forge-std/console.sol";
|
||||
|
||||
contract CoreRelayer is CoreRelayerGovernance {
|
||||
using BytesLib for bytes;
|
||||
|
||||
|
@ -317,8 +315,8 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
|
||||
(
|
||||
uint256 requestFee,
|
||||
uint256 applicationBudgetTarget,
|
||||
uint256 maximumRefund,
|
||||
uint256 applicationBudgetTarget,
|
||||
bool isSufficient,
|
||||
string memory reason
|
||||
) = verifyFunding(
|
||||
|
@ -359,8 +357,8 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (
|
||||
uint256 requestFee,
|
||||
uint256 applicationBudgetTarget,
|
||||
uint256 maximumRefund,
|
||||
uint256 applicationBudgetTarget,
|
||||
bool isSufficient,
|
||||
string memory reason
|
||||
)
|
||||
|
@ -372,7 +370,7 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
? args.provider.quoteDeliveryOverhead(args.targetChain)
|
||||
: args.provider.quoteRedeliveryOverhead(args.targetChain);
|
||||
uint256 overheadBudgetTarget =
|
||||
quoteAssetConversion(args.sourceChain, overheadFeeSource, args.targetChain, args.provider);
|
||||
assetConversionHelper(args.sourceChain, overheadFeeSource, args.targetChain, 1, 1, true, args.provider);
|
||||
maximumRefund = args.isDelivery
|
||||
? calculateTargetDeliveryMaximumRefund(args.targetChain, args.computeBudgetSource, args.provider)
|
||||
: calculateTargetRedeliveryMaximumRefund(args.targetChain, args.computeBudgetSource, args.provider);
|
||||
|
@ -411,7 +409,6 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
revert ReentrantCall();
|
||||
}
|
||||
setContractLock(true);
|
||||
|
||||
// store gas budget pre target invocation to calculate unused gas budget
|
||||
uint256 preGas = gasleft();
|
||||
|
||||
|
@ -637,7 +634,6 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
) {
|
||||
revert InsufficientRelayerFunds();
|
||||
}
|
||||
|
||||
//Overwrite compute budget and application budget on the original request and proceed.
|
||||
originalInstruction.maximumRefundTarget = redeliveryInstruction.newMaximumRefundTarget;
|
||||
originalInstruction.applicationBudgetTarget = redeliveryInstruction.newApplicationBudgetTarget;
|
||||
|
@ -740,16 +736,9 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint32 gasAmount)
|
||||
{
|
||||
IWormhole wormhole = wormhole();
|
||||
if (computeBudget <= provider.quoteDeliveryOverhead(targetChain)) {
|
||||
return 0;
|
||||
} else {
|
||||
uint256 remainder = computeBudget - provider.quoteDeliveryOverhead(targetChain);
|
||||
uint256 gas = remainder / provider.quoteGasPrice(targetChain);
|
||||
|
||||
if (gas >= 2 ** 32) return uint32(2 ** 32 - 1);
|
||||
return uint32(gas);
|
||||
}
|
||||
gasAmount = calculateTargetGasDeliveryAmountHelper(
|
||||
targetChain, computeBudget, provider.quoteDeliveryOverhead(targetChain), provider
|
||||
);
|
||||
}
|
||||
|
||||
function calculateTargetDeliveryMaximumRefund(uint16 targetChain, uint256 computeBudget, IRelayProvider provider)
|
||||
|
@ -757,13 +746,9 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint256 maximumRefund)
|
||||
{
|
||||
uint256 deliveryOverhead = provider.quoteDeliveryOverhead(targetChain);
|
||||
if (computeBudget >= deliveryOverhead) {
|
||||
uint256 remainder = computeBudget - deliveryOverhead;
|
||||
maximumRefund = quoteAssetConversion(chainId(), remainder, targetChain, provider);
|
||||
} else {
|
||||
maximumRefund = 0;
|
||||
}
|
||||
maximumRefund = calculateTargetDeliveryMaximumRefundHelper(
|
||||
targetChain, computeBudget, provider.quoteDeliveryOverhead(targetChain), provider
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -775,16 +760,9 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint32 gasAmount)
|
||||
{
|
||||
IWormhole wormhole = wormhole();
|
||||
if (computeBudget <= wormhole.messageFee() + provider.quoteRedeliveryOverhead(targetChain)) {
|
||||
return 0;
|
||||
} else {
|
||||
uint256 remainder = computeBudget - wormhole.messageFee() - provider.quoteRedeliveryOverhead(targetChain);
|
||||
uint256 gas = remainder / provider.quoteGasPrice(targetChain);
|
||||
|
||||
if (gas >= 2 ** 32) return uint32(2 ** 32 - 1);
|
||||
return uint32(gas);
|
||||
}
|
||||
gasAmount = calculateTargetGasDeliveryAmountHelper(
|
||||
targetChain, computeBudget, provider.quoteRedeliveryOverhead(targetChain), provider
|
||||
);
|
||||
}
|
||||
|
||||
function calculateTargetRedeliveryMaximumRefund(uint16 targetChain, uint256 computeBudget, IRelayProvider provider)
|
||||
|
@ -792,8 +770,41 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint256 maximumRefund)
|
||||
{
|
||||
uint256 remainder = computeBudget - provider.quoteRedeliveryOverhead(targetChain);
|
||||
maximumRefund = quoteAssetConversion(chainId(), remainder, targetChain, provider);
|
||||
maximumRefund = calculateTargetDeliveryMaximumRefundHelper(
|
||||
targetChain, computeBudget, provider.quoteRedeliveryOverhead(targetChain), provider
|
||||
);
|
||||
}
|
||||
|
||||
function calculateTargetGasDeliveryAmountHelper(
|
||||
uint16 targetChain,
|
||||
uint256 computeBudget,
|
||||
uint256 deliveryOverhead,
|
||||
IRelayProvider provider
|
||||
) internal view returns (uint32 gasAmount) {
|
||||
if (computeBudget <= deliveryOverhead) {
|
||||
gasAmount = 0;
|
||||
} else {
|
||||
uint256 gas = (computeBudget - deliveryOverhead) / provider.quoteGasPrice(targetChain);
|
||||
if (gas > type(uint32).max) {
|
||||
gasAmount = type(uint32).max;
|
||||
} else {
|
||||
gasAmount = uint32(gas);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function calculateTargetDeliveryMaximumRefundHelper(
|
||||
uint16 targetChain,
|
||||
uint256 computeBudget,
|
||||
uint256 deliveryOverhead,
|
||||
IRelayProvider provider
|
||||
) internal view returns (uint256 maximumRefund) {
|
||||
if (computeBudget >= deliveryOverhead) {
|
||||
uint256 remainder = computeBudget - deliveryOverhead;
|
||||
maximumRefund = assetConversionHelper(chainId(), remainder, targetChain, 1, 1, false, provider);
|
||||
} else {
|
||||
maximumRefund = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function quoteGasDeliveryFee(uint16 targetChain, uint32 gasLimit, IRelayProvider provider)
|
||||
|
@ -801,7 +812,7 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint256 deliveryQuote)
|
||||
{
|
||||
return provider.quoteDeliveryOverhead(targetChain) + (gasLimit * provider.quoteGasPrice(targetChain))
|
||||
deliveryQuote = provider.quoteDeliveryOverhead(targetChain) + (gasLimit * provider.quoteGasPrice(targetChain))
|
||||
+ wormhole().messageFee();
|
||||
}
|
||||
|
||||
|
@ -810,16 +821,19 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint256 redeliveryQuote)
|
||||
{
|
||||
return provider.quoteRedeliveryOverhead(targetChain) + (gasLimit * provider.quoteGasPrice(targetChain))
|
||||
+ wormhole().messageFee();
|
||||
redeliveryQuote = provider.quoteRedeliveryOverhead(targetChain)
|
||||
+ (gasLimit * provider.quoteGasPrice(targetChain)) + wormhole().messageFee();
|
||||
}
|
||||
|
||||
//This is used internally to calculate the exchange rate for the provider without deducting the buffer amount
|
||||
function quoteAssetConversion(uint16 sourceChain, uint256 sourceAmount, uint16 targetChain, IRelayProvider provider)
|
||||
internal
|
||||
view
|
||||
returns (uint256 targetAmount)
|
||||
{
|
||||
function assetConversionHelper(
|
||||
uint16 sourceChain,
|
||||
uint256 sourceAmount,
|
||||
uint16 targetChain,
|
||||
uint256 multiplier,
|
||||
uint256 multiplierDenominator,
|
||||
bool roundUp,
|
||||
IRelayProvider provider
|
||||
) internal view returns (uint256 targetAmount) {
|
||||
uint256 srcNativeCurrencyPrice = provider.quoteAssetPrice(sourceChain);
|
||||
if (srcNativeCurrencyPrice == 0) {
|
||||
revert SrcNativeCurrencyPriceIsZero();
|
||||
|
@ -830,7 +844,14 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
revert DstNativeCurrencyPriceIsZero();
|
||||
}
|
||||
|
||||
return sourceAmount * srcNativeCurrencyPrice / dstNativeCurrencyPrice;
|
||||
uint256 numerator = sourceAmount * srcNativeCurrencyPrice * multiplier;
|
||||
uint256 denominator = dstNativeCurrencyPrice * multiplierDenominator;
|
||||
|
||||
if (roundUp) {
|
||||
targetAmount = (numerator + denominator - 1) / denominator;
|
||||
} else {
|
||||
targetAmount = numerator / denominator;
|
||||
}
|
||||
}
|
||||
|
||||
//If the integrator pays at least nativeQuote, they should receive at least targetAmount as their application budget
|
||||
|
@ -839,9 +860,10 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint256 nativeQuote)
|
||||
{
|
||||
uint256 sourceAmount = quoteAssetConversion(targetChain, targetAmount, chainId(), provider);
|
||||
(uint16 buffer, uint16 denominator) = provider.getAssetConversionBuffer(targetChain);
|
||||
nativeQuote = (sourceAmount * (denominator + buffer) + denominator - 1) / denominator;
|
||||
nativeQuote = assetConversionHelper(
|
||||
targetChain, targetAmount, chainId(), uint256(0) + denominator + buffer, denominator, true, provider
|
||||
);
|
||||
}
|
||||
|
||||
//This should invert quoteApplicationBudgetAmount, I.E when a user pays the sourceAmount, they receive at least the value of targetAmount they requested from
|
||||
|
@ -851,9 +873,11 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
view
|
||||
returns (uint256 targetAmount)
|
||||
{
|
||||
uint256 amount = quoteAssetConversion(chainId(), sourceAmount, targetChain, provider);
|
||||
(uint16 buffer, uint16 denominator) = provider.getAssetConversionBuffer(targetChain);
|
||||
targetAmount = amount * denominator / (denominator + buffer);
|
||||
|
||||
targetAmount = assetConversionHelper(
|
||||
chainId(), sourceAmount, targetChain, denominator, uint256(0) + denominator + buffer, false, provider
|
||||
);
|
||||
}
|
||||
|
||||
function convertToEncodedRedeliveryByTxHashInstruction(
|
||||
|
@ -908,7 +932,7 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
newEncoded = abi.encodePacked(
|
||||
newEncoded,
|
||||
calculateTargetDeliveryMaximumRefund(request.targetChain, request.computeBudget, provider),
|
||||
quoteAssetConversion(chainId(), request.applicationBudget, request.targetChain, provider)
|
||||
convertApplicationBudgetAmount(request.applicationBudget, request.targetChain, provider)
|
||||
);
|
||||
newEncoded = abi.encodePacked(
|
||||
newEncoded,
|
||||
|
|
|
@ -95,7 +95,6 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
bool forward = (parsed.payload.toUint8(0) == 1);
|
||||
verifiedPayloads[parsed.hash] = parsed.payload.slice(1, parsed.payload.length - 1);
|
||||
message = parsed.payload.slice(1, parsed.payload.length - 1);
|
||||
|
||||
if (forward) {
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(
|
||||
parsed.nonce, abi.encodePacked(uint8(0), bytes("received!")), 200
|
||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue