wormhole/ethereum/forge-test/relayer/BigRevertBufferIntegration.sol

118 lines
4.6 KiB
Solidity

// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import "../../contracts/relayer/libraries/BytesParsing.sol";
import "../../contracts/interfaces/relayer/IWormholeRelayerTyped.sol";
import {
EvmDeliveryInstruction
} from "../../contracts/relayer/libraries/RelayerInternalStructs.sol";
import {WormholeRelayerDelivery} from "../../contracts/relayer/wormholeRelayer/WormholeRelayerDelivery.sol";
import {WormholeRelayerBase} from "../../contracts/relayer/wormholeRelayer/WormholeRelayerBase.sol";
import {IWormholeReceiver} from "../../contracts/interfaces/relayer/IWormholeReceiver.sol";
import {toWormholeFormat, fromWormholeFormat} from "../../contracts/relayer/libraries/Utils.sol";
import {MockWormhole} from "./MockWormhole.sol";
import "forge-std/Test.sol";
import "forge-std/console.sol";
uint256 constant uint256Length = 32;
/**
* This contract is meant to test different kinds of extreme scenarios when an integration returns data
* after its `receiveWormholeMessages` interface is called.
*
* Only meant for testing purposes.
*/
contract BigRevertBufferIntegration is IWormholeReceiver {
using BytesParsing for bytes;
// This is the function which receives all messages from the remote contracts.
function receiveWormholeMessages(
bytes memory payload,
bytes[] memory, /*additionalVaas*/
bytes32, /*sourceAddress*/
uint16, /*sourceChain*/
bytes32 /*deliveryHash*/
) public payable override {
(uint256 revertLength,) = payload.asUint256(0);
bytes memory revertBuffer = new bytes(revertLength);
for (uint256 i = 0; i < revertBuffer.length; ++i) {
revertBuffer[i] = bytes1(uint8(i));
}
// We avoid reverting with the standard `Error(string)` here because it may mess up terminals with these garbage bytes
// It's easier to predict what to test with this anyway.
assembly ("memory-safe") {
let buf := add(revertBuffer, uint256Length)
revert(buf, revertLength)
}
}
}
contract ExecuteInstructionHarness is WormholeRelayerDelivery {
constructor(address _wormhole) WormholeRelayerBase(_wormhole) {}
function executeInstruction_harness(EvmDeliveryInstruction memory instruction)
public
returns (DeliveryResults memory results)
{
return executeInstruction(instruction);
}
}
contract TestBigBuffers is Test {
ExecuteInstructionHarness harness;
function setUp() public {
// deploy Wormhole
MockWormhole wormhole = new MockWormhole({
initChainId: 2,
initEvmChainId: block.chainid
});
harness = new ExecuteInstructionHarness(address(wormhole));
console.log(address(harness));
}
function testExecuteInstructionTruncatesLongRevertBuffers() public {
console.log(address(harness));
Gas gasLimit = Gas.wrap(500_000);
uint256 sizeRequested = 512;
bytes32 targetIntegration = toWormholeFormat(address(new BigRevertBufferIntegration()));
// We encode 512 as the requested revert buffer length to our test integration contract
bytes memory payload = abi.encode(sizeRequested);
bytes32 userAddress = toWormholeFormat(address(0x8080));
WormholeRelayerDelivery.DeliveryResults memory results = harness.executeInstruction_harness(
EvmDeliveryInstruction({
sourceChain: 6,
targetAddress: targetIntegration,
payload: payload,
gasLimit: gasLimit,
totalReceiverValue: TargetNative.wrap(0),
targetChainRefundPerGasUnused: GasPrice.wrap(0),
senderAddress: userAddress,
deliveryHash: bytes32(0),
signedVaas: new bytes[](0)
})
);
assertTrue(uint8(results.status) == uint8(IWormholeRelayerDelivery.DeliveryStatus.RECEIVER_FAILURE));
assertTrue(results.gasUsed <= gasLimit);
assertEq(
results.additionalStatusInfo,
abi.encodePacked(
// First word
bytes32(0x000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f),
// Second word
bytes32(0x202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f),
// Third word
bytes32(0x404142434445464748494a4b4c4d4e4f505152535455565758595a5b5c5d5e5f),
// Fourth word
bytes32(0x606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f),
// Four extra bytes
bytes4(0x80818283)
)
);
}
}