Bugfixes
This commit is contained in:
parent
0998f557da
commit
991e88eac2
|
@ -25,31 +25,33 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
// map that stores payloads from received VAAs
|
||||
mapping(bytes32 => bytes) verifiedPayloads;
|
||||
|
||||
bytes message;
|
||||
// mapping of other MockRelayerIntegration contracts
|
||||
mapping(uint16 => bytes32) registeredContracts;
|
||||
|
||||
bytes[] messages;
|
||||
|
||||
struct FurtherInstructions {
|
||||
bool keepSending;
|
||||
bytes newMessage;
|
||||
bytes[] newMessages;
|
||||
uint16[] chains;
|
||||
uint32[] gasLimits;
|
||||
}
|
||||
|
||||
struct Message {
|
||||
bytes text;
|
||||
FurtherInstructions furtherInstructions;
|
||||
}
|
||||
|
||||
constructor(address _wormholeCore, address _coreRelayer) {
|
||||
wormhole = IWormhole(_wormholeCore);
|
||||
relayer = IWormholeRelayer(_coreRelayer);
|
||||
owner = msg.sender;
|
||||
}
|
||||
|
||||
function sendMessage(bytes memory _message, uint16 targetChainId, address destination) public payable {
|
||||
sendMessage(_message, targetChainId, destination, destination);
|
||||
}
|
||||
|
||||
function sendMessage(bytes memory _message, uint16 targetChainId, address destination, address refundAddress)
|
||||
public
|
||||
payable
|
||||
{
|
||||
executeSend(abi.encodePacked(uint8(0), _message), targetChainId, destination, refundAddress, 0, 1);
|
||||
sendMessageGeneral(_message, targetChainId, destination, refundAddress, 0, 1);
|
||||
}
|
||||
|
||||
function sendMessageWithForwardedResponse(
|
||||
|
@ -58,7 +60,21 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
address destination,
|
||||
address refundAddress
|
||||
) public payable {
|
||||
executeSend(abi.encodePacked(uint8(1), _message), targetChainId, destination, refundAddress, 0, 1);
|
||||
uint16[] memory chains = new uint16[](1);
|
||||
chains[0] = wormhole.chainId();
|
||||
uint32[] memory gasLimits = new uint32[](1);
|
||||
gasLimits[0] = 1000000;
|
||||
bytes[] memory newMessages = new bytes[](1);
|
||||
newMessages[0] = bytes("received!");
|
||||
FurtherInstructions memory instructions = FurtherInstructions({
|
||||
keepSending: true,
|
||||
newMessages: newMessages,
|
||||
chains: chains,
|
||||
gasLimits: gasLimits
|
||||
});
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(1, _message, 200);
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(1, encodeFurtherInstructions(instructions), 200);
|
||||
executeSend(targetChainId, destination, refundAddress, 0, 1);
|
||||
}
|
||||
|
||||
function sendMessageGeneral(
|
||||
|
@ -69,18 +85,18 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
uint256 receiverValue,
|
||||
uint32 nonce
|
||||
) public payable {
|
||||
executeSend(fullMessage, targetChainId, destination, refundAddress, receiverValue, nonce);
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(nonce, fullMessage, 200);
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(1, abi.encodePacked(uint8(0)), 200);
|
||||
executeSend(targetChainId, destination, refundAddress, receiverValue, nonce);
|
||||
}
|
||||
|
||||
function executeSend(
|
||||
bytes memory fullMessage,
|
||||
uint16 targetChainId,
|
||||
address destination,
|
||||
address refundAddress,
|
||||
uint256 receiverValue,
|
||||
uint32 nonce
|
||||
) internal {
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(nonce, fullMessage, 200);
|
||||
|
||||
IWormholeRelayer.Send memory request = IWormholeRelayer.Send({
|
||||
targetChain: targetChainId,
|
||||
|
@ -97,46 +113,49 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
function receiveWormholeMessages(bytes[] memory wormholeObservations, bytes[] memory) public payable override {
|
||||
// loop through the array of wormhole observations from the batch and store each payload
|
||||
uint256 numObservations = wormholeObservations.length;
|
||||
for (uint256 i = 0; i < numObservations - 1;) {
|
||||
messages = new bytes[](wormholeObservations.length - 2);
|
||||
for (uint256 i = 0; i < numObservations - 2; i++) {
|
||||
(IWormhole.VM memory parsed, bool valid, string memory reason) =
|
||||
wormhole.parseAndVerifyVM(wormholeObservations[i]);
|
||||
require(valid, reason);
|
||||
require(registeredContracts[parsed.emitterChainId] == parsed.emitterAddress);
|
||||
messages[i] = parsed.payload;
|
||||
}
|
||||
|
||||
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
|
||||
);
|
||||
(IWormhole.VM memory parsed, bool valid, string memory reason) =
|
||||
wormhole.parseAndVerifyVM(wormholeObservations[wormholeObservations.length - 2]);
|
||||
FurtherInstructions memory instructions = decodeFurtherInstructions(parsed.payload);
|
||||
|
||||
uint256 maxTransactionFee =
|
||||
relayer.quoteGas(parsed.emitterChainId, 500000, relayer.getDefaultRelayProvider());
|
||||
|
||||
IWormholeRelayer.Send memory request = IWormholeRelayer.Send({
|
||||
targetChain: parsed.emitterChainId,
|
||||
targetAddress: parsed.emitterAddress,
|
||||
refundAddress: parsed.emitterAddress,
|
||||
maxTransactionFee: maxTransactionFee,
|
||||
if(instructions.keepSending) {
|
||||
for(uint16 i=0; i<instructions.newMessages.length; i++) {
|
||||
wormhole.publishMessage(parsed.nonce, instructions.newMessages[i], 200);
|
||||
}
|
||||
ICoreRelayer.DeliveryRequest[] memory deliveryRequests = new ICoreRelayer.DeliveryRequest[](instructions.chains.length);
|
||||
for(uint16 i=0; i<instructions.chains.length; i++) {
|
||||
deliveryRequests[i] = ICoreRelayer.DeliveryRequest({
|
||||
targetChain: instructions.chains[i],
|
||||
targetAddress: registeredContracts[instructions.chains[i]],
|
||||
refundAddress: registeredContracts[instructions.chains[i]],
|
||||
maxTransactionFee: relayer.quoteGas(instructions.chains[i], instructions.gasLimits[i], relayer.getDefaultRelayProvider()),
|
||||
receiverValue: 0,
|
||||
relayParameters: relayer.getDefaultRelayParams()
|
||||
});
|
||||
|
||||
relayer.forward(request, parsed.nonce, relayer.getDefaultRelayProvider());
|
||||
}
|
||||
|
||||
unchecked {
|
||||
i += 1;
|
||||
}
|
||||
IWormholeRelayer.SendContainer memory container = Iwormhole.SendContainer(1, address(relayer.getDefaultRelayProvider()), deliveryRequests);
|
||||
relayer.multichainForward(container, deliveryRequests[0].targetChain, parsed.nonce);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getPayload(bytes32 hash) public view returns (bytes memory) {
|
||||
return verifiedPayloads[hash];
|
||||
}
|
||||
|
||||
function getMessage() public view returns (bytes memory) {
|
||||
return message;
|
||||
function getFirstMessage() public view returns (bytes memory) {
|
||||
if(messages.length == 0) {
|
||||
return new bytes(0);
|
||||
}
|
||||
return messages[0];
|
||||
}
|
||||
|
||||
function clearPayload(bytes32 hash) public {
|
||||
|
@ -151,30 +170,54 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
return bytes32(uint256(uint160(address(this))));
|
||||
}
|
||||
|
||||
function encodeMessage(Message message) public view returns (bytes encodedMessage) {
|
||||
encodedMessage = abi.encodePacked(uint16(message.text.length), message.text, uint8(0));
|
||||
function registerEmitter(uint16 chainId, bytes32 emitterAddress) public {
|
||||
require(msg.sender == owner);
|
||||
registeredContracts[chainId] = emitterAddress;
|
||||
}
|
||||
|
||||
function encodeMessage(Message message, ForwardingInstructions forwardingInstructions) public view returns (bytes encodedMessage) {
|
||||
encodedMessage = abi.encodePacked(encodeMessage(message), uint8(forwardingInstructions.keepSending), uint16(forwardingInstructions.newMessage.length), uint16(forwardingInstuctions.chains.length));
|
||||
for(uint16 i=0; i<forwardingInstructions.chains.length; i++) {
|
||||
encodedMessage = abi.encodePacked(encodedMessage, forwardingInstructions.chains[i], forwardingInstructions.gasLimits[i]);
|
||||
function encodeFurtherInstructions(FurtherInstructions memory furtherInstructions) public view returns (bytes memory encodedFurtherInstructions) {
|
||||
encodedFurtherInstructions = abi.encodePacked(furtherInstructions.keepSending ? uint8(1) : uint8(0), uint16(furtherInstructions.newMessages.length));
|
||||
for(uint16 i=0; i<furtherInstructions.newMessages.length; i++) {
|
||||
encodedFurtherInstructions = abi.encodePacked(encodedFurtherInstructions, uint16(furtherInstructions.newMessages[i].length), furtherInstructions.newMessages[i]);
|
||||
}
|
||||
encodedFurtherInstructions = abi.encodePacked(encodedFurtherInstructions, uint16(furtherInstructions.chains.length));
|
||||
for(uint16 i=0; i<furtherInstructions.chains.length; i++) {
|
||||
encodedFurtherInstructions = abi.encodePacked(encodedFurtherInstructions, furtherInstructions.chains[i], furtherInstructions.gasLimits[i]);
|
||||
}
|
||||
}
|
||||
|
||||
function decodeMessage(bytes encodedMessage) public view returns (Message message) {
|
||||
function decodeFurtherInstructions(bytes memory encodedFurtherInstructions) public view returns (FurtherInstructions memory furtherInstructions) {
|
||||
uint256 index = 0;
|
||||
uint16 length = encodedMessage.toUint16(index);
|
||||
index += 2;
|
||||
message.text = encodedMessage.slice(index, length);
|
||||
index += length;
|
||||
message.forwardingInstructions.keepSending = encodedMessage.toUint8(index) == 1;
|
||||
|
||||
furtherInstructions.keepSending = encodedFurtherInstructions.toUint8(index) == 1;
|
||||
index += 1;
|
||||
length = encodedMessage.toUint16(index);
|
||||
|
||||
if(!furtherInstructions.keepSending) {
|
||||
return furtherInstructions;
|
||||
}
|
||||
|
||||
uint16 length = encodedFurtherInstructions.toUint16(index);
|
||||
index += 2;
|
||||
uint16[] chains = new uint16[](length);
|
||||
uint32[] gasLimits = new uint32[](length);
|
||||
message.forwardingInstructions.
|
||||
furtherInstructions.newMessages = new bytes[](length);
|
||||
for(uint16 i=0; i<length; i++) {
|
||||
uint16 msgLength = encodedFurtherInstructions.toUint16(index);
|
||||
index += 2;
|
||||
furtherInstructions.newMessages[i] = encodedFurtherInstructions.slice(index, msgLength);
|
||||
index += msgLength;
|
||||
}
|
||||
|
||||
length = encodedFurtherInstructions.toUint16(index);
|
||||
index += 2;
|
||||
uint16[] memory chains = new uint16[](length);
|
||||
uint32[] memory gasLimits = new uint32[](length);
|
||||
for(uint16 i=0; i<length; i++) {
|
||||
chains[i] = encodedFurtherInstructions.toUint16(index);
|
||||
index += 2;
|
||||
gasLimits[i] = encodedFurtherInstructions.toUint32(index);
|
||||
index += 4;
|
||||
}
|
||||
furtherInstructions.chains = chains;
|
||||
furtherInstructions.gasLimits = gasLimits;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -288,6 +288,7 @@ contract TestCoreRelayer is Test {
|
|||
map[i].coreRelayerFull, i, j, bytes32(uint256(uint160(address(map[j].coreRelayer))))
|
||||
);
|
||||
map[i].relayProvider.updateMaximumBudget(j, maxBudget);
|
||||
map[i].integration.registerEmitter(j, bytes32(uint256(uint160(address(map[j].integration)))));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -345,9 +346,9 @@ contract TestCoreRelayer is Test {
|
|||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
}
|
||||
|
||||
function testFundsCorrect(GasParameters memory gasParams, FeeParameters memory feeParams, bytes memory message)
|
||||
|
@ -368,7 +369,7 @@ contract TestCoreRelayer is Test {
|
|||
) + 2 * setup.source.wormhole.messageFee() + receiverValueSource;
|
||||
|
||||
setup.source.integration.sendMessageGeneral{value: payment}(
|
||||
abi.encodePacked(uint8(0), message),
|
||||
message,
|
||||
setup.targetChainId,
|
||||
address(setup.target.integration),
|
||||
address(setup.target.refundAddress),
|
||||
|
@ -376,9 +377,9 @@ contract TestCoreRelayer is Test {
|
|||
1
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
|
||||
uint256 USDcost = uint256(payment) * feeParams.sourceNativePrice
|
||||
- (setup.target.refundAddress.balance - refundAddressBalance) * feeParams.targetNativePrice;
|
||||
|
@ -431,7 +432,7 @@ contract TestCoreRelayer is Test {
|
|||
) + 2 * setup.source.wormhole.messageFee() + receiverValueSource;
|
||||
|
||||
setup.source.integration.sendMessageGeneral{value: payment}(
|
||||
abi.encodePacked(uint8(0), message),
|
||||
message,
|
||||
setup.targetChainId,
|
||||
address(setup.target.integration),
|
||||
address(setup.target.refundAddress),
|
||||
|
@ -439,7 +440,7 @@ contract TestCoreRelayer is Test {
|
|||
1
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
uint256 USDcost = uint256(payment) * feeParams.sourceNativePrice
|
||||
- (setup.target.refundAddress.balance - refundAddressBalance) * feeParams.targetNativePrice;
|
||||
|
@ -487,13 +488,13 @@ contract TestCoreRelayer is Test {
|
|||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
|
||||
genericRelayer(setup.targetChainId, 2);
|
||||
genericRelayer(setup.targetChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.source.integration.getMessage()) == keccak256(bytes("received!")));
|
||||
assertTrue(keccak256(setup.source.integration.getFirstMessage()) == keccak256(bytes("received!")));
|
||||
}
|
||||
|
||||
function testRedelivery(GasParameters memory gasParams, FeeParameters memory feeParams, bytes memory message)
|
||||
|
@ -517,10 +518,10 @@ contract TestCoreRelayer is Test {
|
|||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(
|
||||
(keccak256(setup.target.integration.getMessage()) != keccak256(message))
|
||||
(keccak256(setup.target.integration.getFirstMessage()) != keccak256(message))
|
||||
|| (keccak256(message) == keccak256(bytes("")))
|
||||
);
|
||||
Vm.Log[] memory logs = vm.getRecordedLogs();
|
||||
|
@ -548,7 +549,7 @@ contract TestCoreRelayer is Test {
|
|||
|
||||
genericRelayer(setup.sourceChainId, 1);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
}
|
||||
|
||||
function testApplicationBudgetFeeWithRedelivery(
|
||||
|
@ -574,10 +575,10 @@ contract TestCoreRelayer is Test {
|
|||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(
|
||||
(keccak256(setup.target.integration.getMessage()) != keccak256(message))
|
||||
(keccak256(setup.target.integration.getFirstMessage()) != keccak256(message))
|
||||
|| (keccak256(message) == keccak256(bytes("")))
|
||||
);
|
||||
|
||||
|
@ -607,7 +608,7 @@ contract TestCoreRelayer is Test {
|
|||
|
||||
genericRelayer(setup.sourceChainId, 1);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
|
||||
assertTrue(address(setup.target.integration).balance >= oldBalance + feeParams.receiverValueTarget);
|
||||
|
||||
|
@ -633,7 +634,7 @@ contract TestCoreRelayer is Test {
|
|||
|
||||
genericRelayer(setup.sourceChainId, 1);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
|
||||
assertTrue(address(setup.target.integration).balance < oldBalance + feeParams.receiverValueTarget);
|
||||
}
|
||||
|
@ -658,9 +659,9 @@ contract TestCoreRelayer is Test {
|
|||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
|
||||
vm.getRecordedLogs();
|
||||
|
||||
|
@ -670,9 +671,9 @@ contract TestCoreRelayer is Test {
|
|||
secondMessage, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(secondMessage));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(secondMessage));
|
||||
}
|
||||
|
||||
function testRevertNonceZero(GasParameters memory gasParams, FeeParameters memory feeParams, bytes memory message)
|
||||
|
@ -689,8 +690,13 @@ contract TestCoreRelayer is Test {
|
|||
);
|
||||
|
||||
vm.expectRevert(abi.encodeWithSignature("NonceIsZero()"));
|
||||
<<<<<<< HEAD
|
||||
setup.source.integration.sendMessageGeneral{value: maxTransactionFee + 2 * wormholeFee}(
|
||||
abi.encodePacked(uint8(0), message),
|
||||
=======
|
||||
setup.source.integration.sendMessageGeneral{value: computeBudget + 2 * wormholeFee}(
|
||||
message,
|
||||
>>>>>>> 74457f4 (Bugfixes)
|
||||
setup.targetChainId,
|
||||
address(setup.target.integration),
|
||||
address(setup.target.refundAddress),
|
||||
|
@ -763,10 +769,10 @@ contract TestCoreRelayer is Test {
|
|||
+ 2 * setup.source.wormhole.messageFee()
|
||||
}(message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress));
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(
|
||||
(keccak256(setup.target.integration.getMessage()) != keccak256(message))
|
||||
(keccak256(setup.target.integration.getFirstMessage()) != keccak256(message))
|
||||
|| (keccak256(message) == keccak256(bytes("")))
|
||||
);
|
||||
|
||||
|
@ -978,12 +984,17 @@ contract TestCoreRelayer is Test {
|
|||
vm.deal(setup.target.relayer, type(uint256).max);
|
||||
|
||||
assertTrue(
|
||||
(keccak256(setup.target.integration.getMessage()) != keccak256(message))
|
||||
(keccak256(setup.target.integration.getFirstMessage()) != keccak256(message))
|
||||
|| (keccak256(message) == keccak256(bytes("")))
|
||||
);
|
||||
vm.prank(setup.target.relayer);
|
||||
<<<<<<< HEAD
|
||||
setup.target.coreRelayerFull.redeliverSingle{value: stack.budget}(stack.package);
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
=======
|
||||
setup.target.coreRelayer.redeliverSingle{value: stack.budget}(stack.package);
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
>>>>>>> 74457f4 (Bugfixes)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1026,9 +1037,9 @@ contract TestCoreRelayer is Test {
|
|||
value: stack.paymentNotEnough + setup.source.wormhole.messageFee()
|
||||
}(message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress));
|
||||
|
||||
genericRelayer(setup.sourceChainId, 2);
|
||||
genericRelayer(setup.sourceChainId, 3);
|
||||
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
assertTrue(keccak256(setup.target.integration.getFirstMessage()) == keccak256(message));
|
||||
stack.entries = vm.getRecordedLogs();
|
||||
|
||||
stack.actualVM = relayerWormholeSimulator.fetchSignedMessageFromLogs(
|
||||
|
|
Loading…
Reference in New Issue