deliverSingle is nice

This commit is contained in:
derpy-duck 2023-02-28 21:45:43 +00:00 committed by chase-45
parent a0484dead1
commit c2117b6ef1
5 changed files with 101 additions and 28 deletions

View File

@ -196,6 +196,9 @@ contract CoreRelayer is CoreRelayerDelivery {
if (nonce == 0) {
revert IWormholeRelayer.NonceIsZero();
}
if(sendContainer.requests.length == 0) {
revert IWormholeRelayer.MultichainSendEmpty();
}
IRelayProvider relayProvider = IRelayProvider(sendContainer.relayProviderAddress);
@ -252,6 +255,9 @@ contract CoreRelayer is CoreRelayerDelivery {
if (msg.sender != lockedTargetAddress()) {
revert IWormholeRelayer.ForwardRequestFromWrongAddress();
}
if(sendContainer.requests.length == 0) {
revert IWormholeRelayer.MultichainSendEmpty();
}
uint256 wormholeMessageFee = wormhole().messageFee();
uint256 totalFee = getTotalFeeMultichainSend(sendContainer, wormholeMessageFee);
@ -291,6 +297,7 @@ contract CoreRelayer is CoreRelayerDelivery {
* @param request Information about the resend request, including the source chain and source transaction hash,
* @param relayProvider The address of (the relay provider you wish to deliver the messages)'s contract on this source chain. This must be a contract that implements IRelayProvider.
* If the targetAddress's receiveWormholeMessage function uses 'gasLimit' units of gas, then we must have newMaxTransactionFee >= quoteGasResend(targetChain, gasLimit, relayProvider)
* This must be the same relayProvider that was designated to relay these messages previously
*
* @return sequence The sequence number for the emitted wormhole message, which contains encoded delivery instructions meant for your specified relay provider.
* The relay provider will listen for these messages, and then execute the redelivery as described
@ -314,7 +321,7 @@ contract CoreRelayer is CoreRelayerDelivery {
// Check that the total amount of value the relay provider needs to use for this redelivery is <= the relayProvider's maximum budget for 'targetChain'
// and check that the calculated gas is greater than 0
checkRedeliveryInstruction(instruction, provider, wormholeMessageFee);
checkRedeliveryInstruction(instruction, provider);
// Publish a wormhole message indicating to the relay provider (who is watching wormhole messages from this contract)
// to re-relay the messages from transaction 'request.txHash' with the calculated amount of gas and receiverValue

View File

@ -260,11 +260,23 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
deliveryInstruction.executionParameters = redeliveryInstruction.executionParameters;
}
/**
* @notice The relay provider calls 'deliverSingle' to relay messages as described by one delivery instruction
*
* The instruction specifies the target chain (must be this chain), target address, refund address, maximum refund (in this chain's currency),
* receiverValue (in this chain's currency), upper bound on gas, and the permissioned address allowed to execute this instruction
*
* The relay provider must pass in the signed wormhole messages from the source chain of the same nonce
* (the wormhole message with the delivery instructions (the delivery VAA) must be one of these messages)
* as well as identify which of these messages is the delivery VAA and which of the many instructions in the multichainSend container is meant to be executed
*
* @param targetParams struct containing the signed wormhole messages and encoded delivery instruction container (and other information)
*/
function deliverSingle(IDelivery.TargetDeliveryParametersSingle memory targetParams) public payable {
// cache wormhole instance
IWormhole wormhole = wormhole();
// validate the deliveryIndex
// Verify the signature and emitter of the wormhole message containing the delivery instructions container
(IWormhole.VM memory deliveryVM, bool valid, string memory reason) =
wormhole.parseAndVerifyVM(targetParams.encodedVMs[targetParams.deliveryIndex]);
if (!valid) {
@ -275,21 +287,25 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
}
DeliveryInstructionsContainer memory container = decodeDeliveryInstructionsContainer(deliveryVM.payload);
//ensure this is a funded delivery, not a failed forward.
// Check that the delivery instructions container was fully funded
if (!container.sufficientlyFunded) {
revert IDelivery.SendNotSufficientlyFunded();
}
// parse the deliveryVM payload into the DeliveryInstructions struct
// Obtain the specific instruction that is intended to be executed in this function
// specifying the the target chain (must be this chain), target address, refund address, maximum refund (in this chain's currency),
// receiverValue (in this chain's currency), upper bound on gas, and the permissioned address allowed to execute this instruction
DeliveryInstruction memory deliveryInstruction = container.instructions[targetParams.multisendIndex];
//make sure the specified relayer is the relayer delivering this message
// make sure that msg.sender is the permissioned address allowed to execute this instruction
if (fromWormholeFormat(deliveryInstruction.executionParameters.providerDeliveryAddress) != msg.sender) {
revert IDelivery.UnexpectedRelayer();
}
uint256 wormholeMessageFee = wormhole.messageFee();
//make sure relayer passed in sufficient funds
// make sure relayer passed in (as msg.value) sufficient funds
if (
msg.value
< deliveryInstruction.maximumRefundTarget + deliveryInstruction.receiverValueTarget + wormholeMessageFee
@ -297,7 +313,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
revert IDelivery.InsufficientRelayerFunds();
}
//make sure this delivery is intended for this chain
// make sure 'targetChain' is the current chain
if (chainId() != deliveryInstruction.targetChain) {
revert IDelivery.TargetChainIsNotThisChain(deliveryInstruction.targetChain);
}
@ -312,10 +328,20 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
);
}
/**
* @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)
*/
function toWormholeFormat(address addr) public pure returns (bytes32 whFormat) {
return bytes32(uint256(uint160(addr)));
}
/**
* @notice Helper function that converts an Wormhole format (32-byte) address to the EVM 'address' 20-byte format
* @param whFormatAddress (32-byte address in Wormhole format)
* @return addr (EVM 20-byte address)
*/
function fromWormholeFormat(bytes32 whFormatAddress) public pure returns (address addr) {
return address(uint160(uint256(whFormatAddress)));
}

View File

@ -133,14 +133,13 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
*/
function checkRedeliveryInstruction(
RedeliveryByTxHashInstruction memory instruction,
IRelayProvider relayProvider,
uint256 wormholeMessageFee
IRelayProvider relayProvider
) internal view {
if (instruction.executionParameters.gasLimit == 0) {
revert IWormholeRelayer.MaxTransactionFeeNotEnough(0);
}
if (
instruction.newMaximumRefundTarget + instruction.newReceiverValueTarget + wormholeMessageFee
instruction.newMaximumRefundTarget + instruction.newReceiverValueTarget
> relayProvider.quoteMaximumBudget(instruction.targetChain)
) {
revert IWormholeRelayer.FundsTooMuch(0);

View File

@ -4,36 +4,75 @@
pragma solidity ^0.8.0;
interface IDelivery {
function deliverSingle(TargetDeliveryParametersSingle memory targetParams) external payable;
function redeliverSingle(TargetRedeliveryByTxHashParamsSingle memory targetParams) external payable;
/**
* @notice TargetDeliveryParametersSingle is the struct that the relay provider passes into 'deliverSingle'
* containing an array of the signed wormhole messages that are to be relayed
*
* @custom:member encodedVMs An array of signed wormhole messages (all of the same nonce, and from the same source chain transaction)
* @custom:member deliveryIndex index such that encodedVMs[deliveryIndex] is the signed wormhole message from the source chain's CoreRelayer contract with payload being the encoded delivery instruction container
* @custom:member multisendIndex The delivery instruction container at 'encodedVMs[deliveryIndex]' contains many delivery instructions, each specifying a different destination address
* This 'multisendIndex' indicates which of those delivery instructions should be executed (specifically, the instruction deliveryInstructionsContainer.instructions[multisendIndex])
* @custom:member relayerRefundAddress The address to which any refunds to the relay provider should be sent
*/
struct TargetDeliveryParametersSingle {
// encoded batchVM to be delivered on the target chain
bytes[] encodedVMs;
// Index of the delivery VM in a batch
uint8 deliveryIndex;
// Index of the target chain inside the delivery VM
uint8 multisendIndex;
//refund address
address payable relayerRefundAddress;
}
/**
* @notice The relay provider calls 'deliverSingle' to relay messages as described by one delivery instruction
*
* The instruction specifies the target chain (must be this chain), target address, refund address, maximum refund (in this chain's currency),
* receiverValue (in this chain's currency), upper bound on gas, and the permissioned address allowed to execute this instruction
*
* The relay provider must pass in the signed wormhole messages from the source chain of the same nonce
* (the wormhole message with the delivery instructions (the delivery VAA) must be one of these messages)
* as well as identify which of these messages is the delivery VAA and which of the many instructions in the multichainSend container is meant to be executed
*
* @param targetParams struct containing the signed wormhole messages and encoded delivery instruction container (and other information)
*/
function deliverSingle(TargetDeliveryParametersSingle memory targetParams) external payable;
/**
* @notice TargetRedeliveryByTxHashParamsSingle is the struct that the relay provider passes into 'redeliverSingle'
* containing an array of the signed wormhole messages that are to be relayed
*
* @custom:member redeliveryVM The signed wormhole message from the source chain's CoreRelayer contract with payload being the encoded redelivery instruction
* @custom:member sourceEncodedVMs An array of signed wormhole messages (all of the same nonce, and from the same source chain transaction), which are the original messages that are meant to be redelivered
* @custom:member relayerRefundAddress The address to which any refunds to the relay provider should be sent
*/
struct TargetRedeliveryByTxHashParamsSingle {
bytes redeliveryVM;
bytes[] sourceEncodedVMs;
address payable relayerRefundAddress;
}
error InvalidEmitterInOriginalDeliveryVM(uint8 index);
error InvalidRedeliveryVM(string reason);
error InvalidEmitterInRedeliveryVM();
error MismatchingRelayProvidersInRedelivery(); // The same relay provider must be specified when doing a single VAA redeliver
error UnexpectedRelayer(); // msg.sender must be the provider
error InvalidVaa(uint8 index, string reason);
error InvalidEmitter();
error SendNotSufficientlyFunded(); // This delivery request was not sufficiently funded, and must request redelivery
error InsufficientRelayerFunds(); // The relayer didn't pass sufficient funds (msg.value does not cover the necessary budget fees)
error TargetChainIsNotThisChain(uint16 targetChainId);
/**
* @notice The relay provider calls 'redeliverSingle' to relay messages as described by one redelivery instruction
*
* The instruction specifies, among other things, the target chain (must be this chain), refund address, new maximum refund (in this chain's currency),
* new receiverValue (in this chain's currency), new upper bound on gas
*
* The relay provider must pass in the original signed wormhole messages from the source chain of the same nonce
* (the wormhole message with the original delivery instructions (the delivery VAA) must be one of these messages)
* as well as the wormhole message with the new redelivery instruction (the redelivery VAA)
*
* @param targetParams struct containing the signed wormhole messages and encoded redelivery instruction (and other information)
*/
function redeliverSingle(TargetRedeliveryByTxHashParamsSingle memory targetParams) external payable;
error InvalidEmitterInRedeliveryVM(); // The redelivery VAA (signed wormhole message with redelivery instructions) has an invalid sender
error InvalidEmitterInOriginalDeliveryVM(uint8 index); // The original delivery VAA (original signed wormhole message with delivery instructions) has an invalid sender
error InvalidRedeliveryVM(string reason); // The redelivery VAA is not valid
error InvalidVaa(uint8 index, string reason); // The VAA is not valid
error MismatchingRelayProvidersInRedelivery(); // The relay provider specified for the redelivery is different from the relay provider specified for the original delivery
error UnexpectedRelayer(); // msg.sender must be the delivery address of the specified relay provider
error InvalidEmitter(); // The delivery VAA (signed wormhole message with delivery instructions) has an invalid sender
error SendNotSufficientlyFunded(); // The container of delivery instructions (for which this current delivery was in) was not fully funded on the source chain
error InsufficientRelayerFunds(); // The relay provider didn't pass in sufficient funds (msg.value does not cover the necessary budget fees)
error TargetChainIsNotThisChain(uint16 targetChainId); // The specified target chain is not the current chain
error ReentrantCall(); // A delivery cannot occur during another delivery
}

View File

@ -264,6 +264,7 @@ interface IWormholeRelayer {
* @param request Information about the resend request, including the source chain and source transaction hash,
* @param relayProvider The address of (the relay provider you wish to deliver the messages)'s contract on this source chain. This must be a contract that implements IRelayProvider.
* If the targetAddress's receiveWormholeMessage function uses 'gasLimit' units of gas, then we must have newMaxTransactionFee >= quoteGasResend(targetChain, gasLimit, relayProvider)
* This must be the same relayProvider that was designated to relay these messages previously
*
* @return sequence The sequence number for the emitted wormhole message, which contains encoded delivery instructions meant for your specified relay provider.
* The relay provider will listen for these messages, and then execute the redelivery as described
@ -362,4 +363,5 @@ interface IWormholeRelayer {
error MultipleForwardsRequested(); // Only one forward can be requested in a transaction
error ForwardRequestFromWrongAddress(); // A forward was requested from an address that is not the 'targetAddress' of the original delivery
error RelayProviderDoesNotSupportTargetChain(); // Your relay provider does not support the target chain you specified
error MultichainSendEmpty(); // Your delivery request container has size 0
}