Skip to content

Commit

Permalink
evm: fixes rounding error in relayFee
Browse files Browse the repository at this point in the history
If we don't round up, the quoted relay fee may be insufficient to cover
the whole transfer.
  • Loading branch information
scnale committed Sep 30, 2024
1 parent c1130bc commit eed2391
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 0 deletions.
3 changes: 3 additions & 0 deletions evm/src/assets/TbrUser.sol
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,9 @@ abstract contract TbrUser is TbrBase {

(uint relayFee, uint wormholeFee) = _quoteRelay(chainId, gasDropoff, baseFee);
uint totalFee = (relayFee + wormholeFee) / _TOTAL_FEE_DIVISOR;
// We need to round up to ensure that the quoted relay fee is able to cover the remainder.
if ((relayFee + wormholeFee) % _TOTAL_FEE_DIVISOR > 0)
++totalFee;
if (totalFee > type(uint64).max)
revert FeeTooLarge(totalFee, commandIndex);

Expand Down
40 changes: 40 additions & 0 deletions evm/test/User.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,46 @@ contract UserTest is TbrTestBase {
assertEq(fee, expectedFee);
}

function testRelayFee_RemainderBelowMwei(uint32 gasDropoff) public {
gasDropoff = uint32(bound(gasDropoff, 1, MAX_GAS_DROPOFF_AMOUNT));
uint256 feeQuote = 1e6;
uint64 expectedFee = uint64(feeQuote) / 1e6 + 1;

vm.mockCall(
address(oracle),
abi.encodeWithSelector(IPriceOracle.get1959.selector),
abi.encode(abi.encodePacked(uint256(feeQuote)))
);

// Less than 1kWei
uint fakeWormholeFee = 100;
vm.mockCall(
address(wormholeCore),
abi.encodeWithSelector(
wormholeCore.messageFee.selector
),
abi.encode(uint256(fakeWormholeFee))
);

bytes memory response = invokeTbr(
abi.encodePacked(
tbr.get1959.selector,
DISPATCHER_PROTOCOL_VERSION0,
RELAY_FEE_ID,
SOLANA_CHAIN_ID,
gasDropoff
)
);

uint offset;
bool isPaused;
uint64 fee;
(isPaused, offset) = response.asBoolUnchecked(offset);
(fee, offset) = response.asUint64Unchecked(offset);
assertEq(isPaused, false);
assertEq(fee, expectedFee);
}

function testRelayFee_GasDropoffExceedsMaximum() public {
uint32 gasDropoff = MAX_GAS_DROPOFF_AMOUNT + 1;
uint commandIndex = 0;
Expand Down

0 comments on commit eed2391

Please sign in to comment.