Merge with interface changes
This commit is contained in:
parent
1efb72ce55
commit
e8a8ee4e92
|
@ -103,14 +103,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
|
|||
address payable relayerRefundAddress,
|
||||
DeliveryVAAInfo memory vaaInfo
|
||||
) internal {
|
||||
// lock the contract to prevent reentrancy
|
||||
uint256 transactionFeeRefundAmount = internalInstruction.maximumRefundTarget;
|
||||
bool callToTargetContractSucceeded = true;
|
||||
bool forwardIsFunded = false;
|
||||
ForwardInstruction memory forwardingRequest = getForwardInstruction();
|
||||
DeliveryStatus status;
|
||||
|
||||
if(internalInstruction.targetAddress != 0x0) {
|
||||
if (internalInstruction.targetAddress != 0x0) {
|
||||
if (isContractLocked()) {
|
||||
revert IDelivery.ReentrantCall();
|
||||
}
|
||||
|
@ -118,65 +111,66 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
|
|||
setContractLock(true);
|
||||
setLockedTargetAddress(fromWormholeFormat(internalInstruction.targetAddress));
|
||||
|
||||
uint256 preGas = gasleft();
|
||||
uint256 preGas = gasleft();
|
||||
|
||||
(bool callToInstructionExecutorSucceeded, bytes memory data) = getWormholeRelayerCallerAddress().call{
|
||||
value: internalInstruction.receiverValueTarget
|
||||
}(abi.encodeCall(IForwardWrapper.executeInstruction, (internalInstruction, encodedVMs)));
|
||||
(bool callToInstructionExecutorSucceeded, bytes memory data) = getWormholeRelayerCallerAddress().call{
|
||||
value: internalInstruction.receiverValueTarget
|
||||
}(abi.encodeCall(IForwardWrapper.executeInstruction, (internalInstruction, encodedVMs)));
|
||||
|
||||
uint256 postGas = gasleft();
|
||||
uint256 postGas = gasleft();
|
||||
|
||||
uint256 transactionFeeRefundAmount;
|
||||
bool callToTargetContractSucceeded = true;
|
||||
if (callToInstructionExecutorSucceeded) {
|
||||
(callToTargetContractSucceeded, transactionFeeRefundAmount) = abi.decode(data, (bool, uint256));
|
||||
} else {
|
||||
// Calculate the amount of gas used in the call (upperbounding at the gas limit, which shouldn't have been exceeded)
|
||||
uint256 gasUsed = (preGas - postGas) > internalInstruction.executionParameters.gasLimit
|
||||
? internalInstruction.executionParameters.gasLimit
|
||||
: (preGas - postGas);
|
||||
uint256 transactionFeeRefundAmount;
|
||||
bool callToTargetContractSucceeded = true;
|
||||
if (callToInstructionExecutorSucceeded) {
|
||||
(callToTargetContractSucceeded, transactionFeeRefundAmount) = abi.decode(data, (bool, uint256));
|
||||
} else {
|
||||
// Calculate the amount of gas used in the call (upperbounding at the gas limit, which shouldn't have been exceeded)
|
||||
uint256 gasUsed = (preGas - postGas) > internalInstruction.executionParameters.gasLimit
|
||||
? internalInstruction.executionParameters.gasLimit
|
||||
: (preGas - postGas);
|
||||
|
||||
// Calculate the amount of maxTransactionFee to refund (multiply the maximum refund by the fraction of gas unused)
|
||||
transactionFeeRefundAmount = (internalInstruction.executionParameters.gasLimit - gasUsed)
|
||||
* internalInstruction.maximumRefundTarget / internalInstruction.executionParameters.gasLimit;
|
||||
// Calculate the amount of maxTransactionFee to refund (multiply the maximum refund by the fraction of gas unused)
|
||||
transactionFeeRefundAmount = (internalInstruction.executionParameters.gasLimit - gasUsed)
|
||||
* internalInstruction.maximumRefundTarget / internalInstruction.executionParameters.gasLimit;
|
||||
}
|
||||
|
||||
// Retrieve the forward instruction created during execution of 'receiveWormholeMessages'
|
||||
ForwardInstruction memory forwardInstruction = getForwardInstruction();
|
||||
|
||||
//clear forwarding request from storage
|
||||
clearForwardInstruction();
|
||||
|
||||
// unlock the contract
|
||||
setContractLock(false);
|
||||
|
||||
DeliveryStatus status;
|
||||
if (forwardInstruction.isValid) {
|
||||
// If the user made a forward/multichainForward request, then try to execute it
|
||||
emitForward(transactionFeeRefundAmount, forwardInstruction);
|
||||
status = DeliveryStatus.FORWARD_REQUEST_SUCCESS;
|
||||
} else {
|
||||
status = callToTargetContractSucceeded
|
||||
? (callToInstructionExecutorSucceeded ? DeliveryStatus.SUCCESS : DeliveryStatus.FORWARD_REQUEST_FAILURE)
|
||||
: DeliveryStatus.RECEIVER_FAILURE;
|
||||
}
|
||||
|
||||
// Emit a status update that can be read by a SDK
|
||||
emit Delivery({
|
||||
recipientContract: fromWormholeFormat(internalInstruction.targetAddress),
|
||||
sourceChain: vaaInfo.sourceChain,
|
||||
sequence: vaaInfo.sourceSequence,
|
||||
deliveryVaaHash: vaaInfo.deliveryVaaHash,
|
||||
status: status
|
||||
});
|
||||
|
||||
payRefunds(
|
||||
internalInstruction,
|
||||
relayerRefundAddress,
|
||||
transactionFeeRefundAmount,
|
||||
callToInstructionExecutorSucceeded && callToTargetContractSucceeded,
|
||||
forwardInstruction.isValid
|
||||
);
|
||||
}
|
||||
|
||||
// Retrieve the forward instruction created during execution of 'receiveWormholeMessages'
|
||||
ForwardInstruction memory forwardInstruction = getForwardInstruction();
|
||||
|
||||
//clear forwarding request from storage
|
||||
clearForwardInstruction();
|
||||
|
||||
// unlock the contract
|
||||
setContractLock(false);
|
||||
|
||||
DeliveryStatus status;
|
||||
if (forwardInstruction.isValid) {
|
||||
// If the user made a forward/multichainForward request, then try to execute it
|
||||
emitForward(transactionFeeRefundAmount, forwardInstruction);
|
||||
status = DeliveryStatus.FORWARD_REQUEST_SUCCESS;
|
||||
} else {
|
||||
status = callToTargetContractSucceeded
|
||||
? (callToInstructionExecutorSucceeded ? DeliveryStatus.SUCCESS : DeliveryStatus.FORWARD_REQUEST_FAILURE)
|
||||
: DeliveryStatus.RECEIVER_FAILURE;
|
||||
}
|
||||
|
||||
// Emit a status update that can be read by a SDK
|
||||
emit Delivery({
|
||||
recipientContract: fromWormholeFormat(internalInstruction.targetAddress),
|
||||
sourceChain: vaaInfo.sourceChain,
|
||||
sequence: vaaInfo.sourceSequence,
|
||||
deliveryVaaHash: vaaInfo.deliveryVaaHash,
|
||||
status: status
|
||||
});
|
||||
|
||||
payRefunds(
|
||||
internalInstruction,
|
||||
relayerRefundAddress,
|
||||
transactionFeeRefundAmount,
|
||||
callToInstructionExecutorSucceeded && callToTargetContractSucceeded,
|
||||
forwardInstruction.isValid
|
||||
);
|
||||
}
|
||||
|
||||
function payRefunds(
|
||||
|
@ -258,7 +252,6 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
|
|||
// receiverValue (in this chain's currency), upper bound on gas
|
||||
DeliveryInstruction memory deliveryInstruction = container.instructions[targetParams.multisendIndex];
|
||||
|
||||
|
||||
// Check that the relay provider passed in at least [(one wormhole message fee) + instruction.maximumRefund + instruction.receiverValue] of this chain's currency as msg.value
|
||||
if (msg.value < deliveryInstruction.maximumRefundTarget + deliveryInstruction.receiverValueTarget) {
|
||||
revert IDelivery.InsufficientRelayerFunds();
|
||||
|
|
|
@ -134,13 +134,9 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
|
|||
returns (bytes memory encoded)
|
||||
{
|
||||
encoded = abi.encodePacked(
|
||||
container.payloadId,
|
||||
uint8(container.messages.length),
|
||||
uint8(container.instructions.length)
|
||||
container.payloadId, container.requesterAddress, uint8(container.messages.length), uint8(container.instructions.length)
|
||||
);
|
||||
|
||||
encoded = abi.encodePacked(container.requesterAddress);
|
||||
|
||||
for (uint256 i = 0; i < container.messages.length; i++) {
|
||||
encoded = abi.encodePacked(encoded, encodeMessageInfo(container.messages[i]));
|
||||
}
|
||||
|
@ -371,14 +367,13 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
|
|||
|
||||
instruction.provider = encoded.toBytes32(index);
|
||||
index += 32;
|
||||
|
||||
|
||||
instruction.executionParameters.version = encoded.toUint8(index);
|
||||
index += 1;
|
||||
|
||||
instruction.executionParameters.gasLimit = encoded.toUint32(index);
|
||||
index += 4;
|
||||
|
||||
|
||||
newIndex = index;
|
||||
}
|
||||
|
||||
|
@ -426,7 +421,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
|
|||
index += 1;
|
||||
|
||||
bytes32 requesterAddress = encoded.toBytes32(index);
|
||||
index +=32;
|
||||
index += 32;
|
||||
|
||||
uint8 messagesArrayLen = encoded.toUint8(index);
|
||||
index += 1;
|
||||
|
@ -456,7 +451,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* @notice Helper function that converts an EVM address to wormhole format
|
||||
* @param addr (EVM 20-byte address)
|
||||
* @return whFormat (32-byte address in Wormhole format)
|
||||
|
|
|
@ -42,5 +42,4 @@ abstract contract CoreRelayerStructs {
|
|||
uint64 sourceSequence;
|
||||
bytes32 deliveryVaaHash;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -43,7 +43,6 @@ interface IDelivery {
|
|||
*/
|
||||
function deliverSingle(TargetDeliveryParametersSingle memory targetParams) external payable;
|
||||
|
||||
|
||||
error InvalidEmitterInOriginalDeliveryVM(); // The original delivery VAA (original signed wormhole message with delivery instructions) has an invalid sender
|
||||
error InvalidVaa(uint8 index, string reason); // The VAA is not valid
|
||||
error InvalidDeliveryVaa(string reason); // The Delivery VAA is not valid
|
||||
|
|
|
@ -40,7 +40,6 @@ contract RelayProviderSetters is Context, RelayProviderState {
|
|||
_state.rewardAddress = rewardAddress;
|
||||
}
|
||||
|
||||
|
||||
function setMaximumBudget(uint16 targetChainId, uint256 amount) internal {
|
||||
_state.maximumBudget[targetChainId] = amount;
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ interface IWormholeRelayerInstructionParser {
|
|||
bytes32 refundAddress;
|
||||
uint256 maximumRefundTarget;
|
||||
uint256 receiverValueTarget;
|
||||
bytes32 provider;
|
||||
ExecutionParameters executionParameters;
|
||||
}
|
||||
|
||||
struct ExecutionParameters {
|
||||
uint8 version;
|
||||
uint32 gasLimit;
|
||||
bytes32 providerDeliveryAddress;
|
||||
}
|
||||
|
||||
function decodeDeliveryInstructionsContainer(bytes memory encoded)
|
||||
|
@ -32,7 +32,6 @@ interface IWormholeRelayerInstructionParser {
|
|||
pure
|
||||
returns (DeliveryInstructionsContainer memory);
|
||||
|
||||
|
||||
function toWormholeFormat(address addr) external pure returns (bytes32 whFormat);
|
||||
|
||||
function fromWormholeFormat(bytes32 whFormatAddress) external pure returns (address addr);
|
||||
|
|
|
@ -109,7 +109,7 @@ contract MockGenericRelayer {
|
|||
parser.decodeDeliveryInstructionsContainer(parsedDeliveryVAA.payload);
|
||||
|
||||
bytes[] memory encodedVMsToBeDelivered = new bytes[](container.messages.length);
|
||||
|
||||
console.log("AA");
|
||||
for (uint8 i = 0; i < container.messages.length; i++) {
|
||||
for (uint8 j = 0; j < encodedVMs.length; j++) {
|
||||
if (messageInfoMatchesVAA(container.messages[i], encodedVMs[j])) {
|
||||
|
@ -118,7 +118,7 @@ contract MockGenericRelayer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
console.log("A");
|
||||
for (uint8 k = 0; k < container.instructions.length; k++) {
|
||||
uint256 budget =
|
||||
container.instructions[k].maximumRefundTarget + container.instructions[k].receiverValueTarget;
|
||||
|
@ -129,9 +129,10 @@ contract MockGenericRelayer {
|
|||
multisendIndex: k,
|
||||
relayerRefundAddress: payable(relayers[targetChain])
|
||||
});
|
||||
|
||||
console.log("A..");
|
||||
vm.prank(relayers[targetChain]);
|
||||
IDelivery(wormholeRelayerContracts[targetChain]).deliverSingle{value: budget}(package);
|
||||
console.log("A...DONE");
|
||||
}
|
||||
bytes32 key = keccak256(abi.encodePacked(parsedDeliveryVAA.emitterChainId, parsedDeliveryVAA.sequence));
|
||||
pastEncodedVMs[key] = encodedVMsToBeDelivered;
|
||||
|
|
|
@ -876,31 +876,6 @@ contract WormholeRelayerTests is Test {
|
|||
setup.target.coreRelayerFull.deliverSingle{value: stack.budget}(stack.package);
|
||||
}
|
||||
|
||||
function testRevertDeliveryUnexpectedRelayer(
|
||||
GasParameters memory gasParams,
|
||||
FeeParameters memory feeParams,
|
||||
bytes memory message
|
||||
) public {
|
||||
StandardSetupTwoChains memory setup = standardAssumeAndSetupTwoChains(gasParams, feeParams, 1000000);
|
||||
|
||||
vm.recordLogs();
|
||||
|
||||
DeliveryStack memory stack;
|
||||
|
||||
stack.payment = setup.source.coreRelayer.quoteGas(
|
||||
setup.targetChainId, gasParams.targetGasLimit, address(setup.source.relayProvider)
|
||||
) + 3 * setup.source.wormhole.messageFee();
|
||||
|
||||
setup.source.integration.sendMessageWithRefundAddress{value: stack.payment}(
|
||||
message, setup.targetChainId, address(setup.target.integration), setup.target.refundAddress
|
||||
);
|
||||
|
||||
prepareDeliveryStack(stack, setup);
|
||||
|
||||
vm.expectRevert(abi.encodeWithSignature("UnexpectedRelayer()"));
|
||||
setup.target.coreRelayerFull.deliverSingle{value: stack.budget}(stack.package);
|
||||
}
|
||||
|
||||
function testRevertDeliveryInsufficientRelayerFunds(
|
||||
GasParameters memory gasParams,
|
||||
FeeParameters memory feeParams,
|
||||
|
@ -1203,7 +1178,6 @@ contract WormholeRelayerTests is Test {
|
|||
message, 32, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
);
|
||||
|
||||
|
||||
vm.expectRevert(abi.encodeWithSignature("RelayProviderDoesNotSupportTargetChain()"));
|
||||
setup.source.integration.sendMessageWithRefundAddress{value: maxTransactionFee + uint256(3) * wormholeFee}(
|
||||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress)
|
||||
|
|
Loading…
Reference in New Issue