Skip to content

Commit

Permalink
feat: test for deadline
Browse files Browse the repository at this point in the history
  • Loading branch information
reednaa committed Feb 14, 2024
1 parent 5fd0a21 commit 29395c8
Show file tree
Hide file tree
Showing 9 changed files with 143 additions and 15 deletions.
14 changes: 8 additions & 6 deletions src/IncentivizedMessageEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,14 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
/// @dev Should generally be the same as the one set by the AMB such that we can verify messages with this identifier
function _uniqueSourceIdentifier() virtual internal view returns(bytes32 sourceIdentifier);

/// @notice Returns the max deadline for this AMB.
/// @notice Returns the duration for which a proof is valid for.
/// It may vary by destination.
/// @dev Remember to add block.timestamp to the duration where proofs remain vaild for.
/// @return timestamp The timestamp of when the application's message won't get delivered but rather acked back.
function _maxDeadline(bytes32 destinationIdentifier) virtual internal view returns(uint64 timestamp);
function _proofValidPeriod(bytes32 destinationIdentifier) virtual internal view returns(uint64 timestamp);

function maxDeadline(bytes32 destinationIdentifier) external view returns(uint64 timestamp) {
return timestamp = uint64(block.timestamp) + _maxDeadline(destinationIdentifier);
function proofValidPeriod(bytes32 destinationIdentifier) external view returns(uint64 timestamp) {
return timestamp = _proofValidPeriod(destinationIdentifier);
}

/// @param sendLostGasTo Who should receive Ether which would otherwise block
Expand Down Expand Up @@ -231,8 +231,10 @@ abstract contract IncentivizedMessageEscrow is IIncentivizedMessageEscrow, Bytes
// Check that the deadline is lower than the AMB specification.
unchecked {
// Timestamps do not overflow in uint64 within reason.
uint64 ambMaxDeadline = _maxDeadline(destinationIdentifier);
if (ambMaxDeadline != 0 && deadline < uint64(block.timestamp) + ambMaxDeadline) revert DeadlineTooLong(ambMaxDeadline, deadline);
uint64 ambMaxDeadline = _proofValidPeriod(destinationIdentifier);
if (ambMaxDeadline != 0 && deadline > uint64(block.timestamp) + ambMaxDeadline) revert DeadlineTooLong(uint64(block.timestamp) + ambMaxDeadline, deadline);
// Check that the deadline is in the future.
if (deadline != 0 && block.timestamp >= deadline) revert DeadlineInPast(uint64(block.timestamp), deadline);
}

// Prepare to store incentive
Expand Down
9 changes: 6 additions & 3 deletions src/apps/mock/IncentivizedMockEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ contract IncentivizedMockEscrow is IncentivizedMessageEscrow, Ownable2Step {
uint256 public costOfMessages;
uint256 public accumulator = 1;

uint64 immutable PROOF_PERIOD;

event Message(bytes32 destinationIdentifier, bytes recipient, bytes message);

constructor(address sendLostGasTo, bytes32 uniqueChainIndex, address signer, uint256 costOfMessages_) IncentivizedMessageEscrow(sendLostGasTo) {
constructor(address sendLostGasTo, bytes32 uniqueChainIndex, address signer, uint256 costOfMessages_, uint64 proofPeriod) IncentivizedMessageEscrow(sendLostGasTo) {
UNIQUE_SOURCE_IDENTIFIER = uniqueChainIndex;
_transferOwnership(signer);
costOfMessages = costOfMessages_;
PROOF_PERIOD = proofPeriod;
}

function estimateAdditionalCost() external view returns(address asset, uint256 amount) {
Expand All @@ -30,8 +33,8 @@ contract IncentivizedMockEscrow is IncentivizedMessageEscrow, Ownable2Step {
accumulator = 1;
}

function _maxDeadline(bytes32 /* destinationIdentifier */) override internal pure returns(uint64) {
return 0;
function _proofValidPeriod(bytes32 /* destinationIdentifier */) override internal view returns(uint64) {
return PROOF_PERIOD;
}

function _uniqueSourceIdentifier() override internal view returns(bytes32 sourceIdentifier) {
Expand Down
2 changes: 1 addition & 1 deletion src/apps/mock/OnRecvIncentivizedMockEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ contract OnRecvIncentivizedMockEscrow is IncentivizedMessageEscrow {
amount = 0;
}

function _maxDeadline(bytes32 /* destinationIdentifier */) override internal pure returns(uint64) {
function _proofValidPeriod(bytes32 /* destinationIdentifier */) override internal pure returns(uint64) {
return 0;
}

Expand Down
2 changes: 1 addition & 1 deletion src/apps/wormhole/IncentivizedWormholeEscrow.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract IncentivizedWormholeEscrow is IncentivizedMessageEscrow, WormholeVerifi
amount = WORMHOLE.messageFee();
}

function _maxDeadline(bytes32 /* destinationIdentifier */) override internal pure returns(uint64) {
function _proofValidPeriod(bytes32 /* destinationIdentifier */) override internal pure returns(uint64) {
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions src/interfaces/IMessageEscrowErrors.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ interface IMessageEscrowErrors {
error NotEnoughGasExeuction(); // 6fa3d3bb
error RefundGasToIsZero(); // 6a1a6afe
error DeadlineTooLong(uint64 maxAllowed, uint64 actual); // 54090af9
error DeadlineInPast(uint64 blocktimestamp, uint64 actual); // 2d098d59
error CannotRetryWrongMessage(bytes32 expected, bytes32 actual); // 48ce7fac
error MessageAlreadyProcessed(); // 7b042609
error DeadlineNotPassed(uint64 expected, uint64 actual); // 862c57f4
Expand Down
122 changes: 122 additions & 0 deletions test/IncentivizedMessageEscrow/escrowMessage/Deadline.t.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.13;

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

import { IncentivizedMockEscrow } from "../../../src/apps/mock/IncentivizedMockEscrow.sol";
import { MockApplication } from "../../mocks/MockApplication.sol";
import { ICrossChainReceiver } from "../../../src/interfaces/ICrossChainReceiver.sol";


contract SubmitPackageDeadlineTest is TestCommon {

function _newEscrow(uint64 deadline) internal {
escrow = new IncentivizedMockEscrow(sendLostGasTo, _DESTINATION_IDENTIFIER, SIGNER, 0, deadline);

application = ICrossChainReceiver(address(new MockApplication(address(escrow))));

// Set implementations to the escrow address.
vm.prank(address(application));
escrow.setRemoteImplementation(_DESTINATION_IDENTIFIER, abi.encode(address(escrow)));

vm.prank(address(this));
escrow.setRemoteImplementation(_DESTINATION_IDENTIFIER, abi.encode(address(escrow)));
}


function test_max_proof_period(uint64 proofPeriod) public {
vm.assume(proofPeriod != 0);
vm.assume(proofPeriod > block.timestamp);
vm.assume(type(uint64).max - 5 > proofPeriod);
_newEscrow(proofPeriod);

// Try to submit a proof that is too far into the future.
vm.expectRevert(abi.encodeWithSignature("DeadlineTooLong(uint64,uint64)", uint64(block.timestamp + proofPeriod), uint64(block.timestamp + proofPeriod + 1)));
escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
uint64(block.timestamp + proofPeriod + 1)
);

// We just need to set it correctly.
escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
uint64(block.timestamp + proofPeriod)
);
}

function test_zero_implies_any_proofPeriod(uint64 testDeadline) public {
vm.assume(testDeadline > block.timestamp);
_newEscrow(0);

// We can set it to anything that is not in the past.
escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
testDeadline
);
}

function test_zero_implies_any_deadline(uint64 testDeadline) public {
_newEscrow(0);

vm.warp(testDeadline);

// We can set it to anything that is not in the past.
escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
0
);
}

function test_call_deadline_in_past(uint64 testDeadline) public {
vm.assume(type(uint64).max - 100 > testDeadline);
vm.assume(testDeadline > block.timestamp);
_newEscrow(0);

vm.warp(testDeadline);

vm.expectRevert(abi.encodeWithSignature("DeadlineInPast(uint64,uint64)", uint64(block.timestamp), testDeadline));
escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
testDeadline
);

uint256 snapshot = vm.snapshot();

escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
testDeadline + 1
);

vm.revertTo(snapshot);

vm.warp(testDeadline-1);
escrow.submitMessage{value: _getTotalIncentive(_INCENTIVE)}(
_DESTINATION_IDENTIFIER,
_DESTINATION_ADDRESS_APPLICATION,
_MESSAGE,
_INCENTIVE,
testDeadline
);


}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ contract sendPacketPaymentTest is TestCommon {
(SIGNER, PRIVATEKEY) = makeAddrAndKey("signer");
_REFUND_GAS_TO = makeAddr("Alice");
BOB = makeAddr("Bob");
escrow = new IncentivizedMockEscrow(sendLostGasTo, _DESTINATION_IDENTIFIER, SIGNER, SEND_MESSAGE_PAYMENT_COST);
escrow = new IncentivizedMockEscrow(sendLostGasTo, _DESTINATION_IDENTIFIER, SIGNER, SEND_MESSAGE_PAYMENT_COST, 0);

application = ICrossChainReceiver(address(new MockApplication(address(escrow))));

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(0x10055), // Gas used
uint48(0x1003f), // Gas used
uint64(1),
uint8(1)
)
Expand Down
4 changes: 2 additions & 2 deletions test/TestCommon.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import "../src/apps/mock/IncentivizedMockEscrow.sol";
import "../src/interfaces/IIncentivizedMessageEscrow.sol";
import { IMessageEscrowEvents } from "../src/interfaces/IMessageEscrowEvents.sol";
import { IMessageEscrowStructs } from "../src/interfaces/IMessageEscrowStructs.sol";
import "./mocks/MockApplication.sol";
import { MockApplication } from "./mocks/MockApplication.sol";
import { ICrossChainReceiver } from "../src/interfaces/ICrossChainReceiver.sol";

interface ICansubmitMessage is IMessageEscrowStructs{
Expand Down Expand Up @@ -45,7 +45,7 @@ contract TestCommon is Test, IMessageEscrowEvents, IMessageEscrowStructs {
_REFUND_GAS_TO = makeAddr("Alice");
BOB = makeAddr("Bob");
sendLostGasTo = makeAddr("sendLostGasTo");
escrow = new IncentivizedMockEscrow(sendLostGasTo, _DESTINATION_IDENTIFIER, SIGNER, 0);
escrow = new IncentivizedMockEscrow(sendLostGasTo, _DESTINATION_IDENTIFIER, SIGNER, 0, 0);

application = ICrossChainReceiver(address(new MockApplication(address(escrow))));

Expand Down

0 comments on commit 29395c8

Please sign in to comment.