Merge with interface changes

This commit is contained in:
derpy-duck 2023-04-03 22:29:01 +00:00
parent 1efb72ce55
commit e8a8ee4e92
8 changed files with 65 additions and 106 deletions

View File

@ -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();

View File

@ -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)

View File

@ -42,5 +42,4 @@ abstract contract CoreRelayerStructs {
uint64 sourceSequence;
bytes32 deliveryVaaHash;
}
}

View File

@ -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

View File

@ -40,7 +40,6 @@ contract RelayProviderSetters is Context, RelayProviderState {
_state.rewardAddress = rewardAddress;
}
function setMaximumBudget(uint16 targetChainId, uint256 amount) internal {
_state.maximumBudget[targetChainId] = amount;
}

View File

@ -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);

View File

@ -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;

View File

@ -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)