Skip to content

Commit

Permalink
feat: ensure that user’s correctly pay the escrow for processing mess…
Browse files Browse the repository at this point in the history
…ages
  • Loading branch information
reednaa committed Feb 16, 2024
1 parent f245155 commit cbbe1b8
Show file tree
Hide file tree
Showing 8 changed files with 75 additions and 10 deletions.
41 changes: 37 additions & 4 deletions src/IncentivizedMessageEscrow.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

import { Address } from "openzeppelin/utils/Address.sol";

import { IIncentivizedMessageEscrow } from "./interfaces/IIncentivizedMessageEscrow.sol";
import { ICrossChainReceiver } from "./interfaces/ICrossChainReceiver.sol";
import { Bytes65 } from "./utils/Bytes65.sol";
Expand Down Expand Up @@ -285,7 +287,7 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
if (msg.value > sum) {
// We know: msg.value >= sum, thus msg.value - sum >= 0.
gasRefund = msg.value - sum;
payable(incentive.refundGasTo).transfer(gasRefund);
Address.sendValue(payable(incentive.refundGasTo), msg.value - uint256(gasRefund));
return (gasRefund, messageIdentifier);
}
}
Expand Down Expand Up @@ -316,12 +318,13 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
(bytes32 chainIdentifier, bytes memory implementationIdentifier, bytes calldata message) = _verifyPacket(messagingProtocolContext, rawMessage);

// Figure out if this is a call or an ack.
uint128 cost = 0;
bytes1 context = bytes1(message[0]);
if (context == CTX_SOURCE_TO_DESTINATION) {
bytes memory receiveAckWithContext = _handleMessage(chainIdentifier, implementationIdentifier, message, feeRecipient, gasLimit);

// The cost management is made by _sendPacket so we don't have to check if enough gas has been provided.
_sendPacket(chainIdentifier, implementationIdentifier, receiveAckWithContext);
cost = _sendPacket(chainIdentifier, implementationIdentifier, receiveAckWithContext);
} else if (context == CTX_DESTINATION_TO_SOURCE) {
// Notice that sometimes ack actually handles deadlines which have been passed.
// However, these are much different from "timeouts".
Expand All @@ -338,6 +341,16 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
} else {
revert NotImplementedError();
}

// Check if there is a mis-match between the cost and the value of the message.
if (uint128(msg.value) != cost) {
if (uint128(msg.value) > cost) {
// Send the unused gas back to the the user.
Address.sendValue(payable(msg.sender), msg.value - uint256(cost));
} else {
revert NotEnoughGasProvided(uint128(msg.value), cost);
}
}
}

//--- Internal Functions ---//
Expand Down Expand Up @@ -883,7 +896,17 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
if (storedAckHash == bytes32(0) || storedAckHash != keccak256(receiveAckWithContext)) revert CannotRetryWrongMessage(storedAckHash, keccak256(receiveAckWithContext));

// Send the package again.
_sendPacket(sourceIdentifier, implementationIdentifier, receiveAckWithContext);
uint128 cost = _sendPacket(sourceIdentifier, implementationIdentifier, receiveAckWithContext);

// Check if there is a mis-match between the cost and the value of the message.
if (uint128(msg.value) != cost) {
if (uint128(msg.value) > cost) {
// Send the unused gas back to the the user.
Address.sendValue(payable(msg.sender), msg.value - uint256(cost));
} else {
revert NotEnoughGasProvided(uint128(msg.value), cost);
}
}
}

/**
Expand Down Expand Up @@ -951,10 +974,20 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
emit TimeoutInitiated(messageIdentifier);

// Send the message
_sendPacket(
uint128 cost = _sendPacket(
sourceIdentifier,
destinationIncentives,
receiveAckWithContext
);

// Check if there is a mis-match between the cost and the value of the message.
if (uint128(msg.value) != cost) {
if (uint128(msg.value) > cost) {
// Send the unused gas back to the the user.
Address.sendValue(payable(msg.sender), msg.value - uint256(cost));
} else {
revert NotEnoughGasProvided(uint128(msg.value), cost);
}
}
}
}
13 changes: 13 additions & 0 deletions src/interfaces/IIncentivizedMessageEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -36,4 +36,17 @@ interface IIncentivizedMessageEscrow is IMessageEscrowStructs, IMessageEscrowErr
* @return amount The number of assets to pay.
*/
function estimateAdditionalCost() external view returns(address asset, uint256 amount);

function timeoutMessage(
bytes calldata destinationIncentives,
bytes32 sourceIdentifier,
uint256 originBlockNumber,
bytes calldata message
) external payable;

function reemitAckMessage(
bytes32 sourceIdentifier,
bytes calldata implementationIdentifier,
bytes calldata receiveAckWithContext
) external payable;
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ contract GasSpendControlTest is TestCommon {
messageIdentifier,
_DESTINATION_ADDRESS_APPLICATION,
destinationFeeRecipient,
uint48(0x366e9), // Gas used
uint48(0x36708), // Gas used
uint64(1),
bytes1(0xff), // This states that the call went wrong.
message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ contract processPacketNoReceiveTest is TestCommon {
messageIdentifier,
_DESTINATION_ADDRESS_THIS,
feeRecipient,
uint48(0x80bc), // Gas used
uint48(0x80db), // Gas used
uint64(1),
abi.encodePacked(bytes1(0xff)),
message
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ contract CallReentryTest is TestCommon, ICrossChainReceiver {
messageIdentifier,
_DESTINATION_ADDRESS_APPLICATION,
feeRecipient,
uint48(0xf8dd), // Gas used
uint48(0xf8f3), // Gas used
uint64(1),
uint8(1)
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ contract processPacketCallTest is TestCommon {
messageIdentifier,
_DESTINATION_ADDRESS_APPLICATION,
feeRecipient,
uint48(0x7af8), // Gas used
uint48(0x7b03), // Gas used
uint64(1),
mockAck
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

import "forge-std/Test.sol";
import { TestCommon } from "../../TestCommon.t.sol";


contract ReemitAckMessageTest is TestCommon {

function test_ack_process_message() public {
bytes memory message = _MESSAGE;
bytes32 feeRecipient = bytes32(uint256(uint160(address(this))));

bytes32 destinationFeeRecipient = bytes32(uint256(uint160(address(this))));

(, bytes memory messageWithContext) = setupForAck(address(application), message, destinationFeeRecipient);

}
}
4 changes: 2 additions & 2 deletions test/TestCommon.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,8 @@ interface ICansubmitMessage is IMessageEscrowStructs{

contract TestCommon is Test, IMessageEscrowEvents, IMessageEscrowStructs {

uint256 constant GAS_SPENT_ON_SOURCE = 6583;
uint256 constant GAS_SPENT_ON_DESTINATION = 31480;
uint256 constant GAS_SPENT_ON_SOURCE = 6586;
uint256 constant GAS_SPENT_ON_DESTINATION = 31491;

bytes32 constant _DESTINATION_IDENTIFIER = bytes32(uint256(0x123123) + uint256(2**255));

Expand Down

0 comments on commit cbbe1b8

Please sign in to comment.