Compare commits

...

5 Commits

Author SHA1 Message Date
Joe Howarth 42e643363c update relayer engine hash 2023-04-04 14:13:41 -05:00
derpy-duck 214736c7b8 Typescript / relayer engine / sdk related changes; now blocked on a SPY Port issue 2023-04-04 19:06:46 +00:00
derpy-duck 7e150947d5 Relay provider can set chains enabled and disabled 2023-04-04 16:26:32 +00:00
derpy-duck 8746431744 Remove outdated names 2023-04-04 14:21:53 +00:00
derpy-duck d639d81bd3 Move CoreRelayerStructs into its own interface file for organization 2023-04-04 14:15:30 +00:00
34 changed files with 139 additions and 165 deletions

View File

@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
import "../interfaces/IWormholeRelayer.sol";
import "./CoreRelayerDelivery.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
contract CoreRelayer is CoreRelayerDelivery {
/**
@ -256,7 +256,7 @@ contract CoreRelayer is CoreRelayerDelivery {
// For each 'Send' request,
// calculate how much gas the relay provider can pay for on 'request.targetChain' using 'request.newTransactionFee',
// and calculate how much value the relay provider will pass into 'request.targetAddress'
DeliveryInstructionsContainer memory instructionsContainer =
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory instructionsContainer =
convertMultichainSendToDeliveryInstructionsContainer(sendContainer);
// For each 'Send' request,
@ -309,7 +309,7 @@ contract CoreRelayer is CoreRelayerDelivery {
// For each 'Send' request,
// calculate how much gas the relay provider can pay for on 'request.targetChain' using 'request.newTransactionFee',
// and calculate how much value the relay provider will pass into 'request.targetAddress'
DeliveryInstructionsContainer memory instructionsContainer =
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory instructionsContainer =
convertMultichainSendToDeliveryInstructionsContainer(sendContainer);
// For each 'Send' request,
@ -320,7 +320,7 @@ contract CoreRelayer is CoreRelayerDelivery {
// Save information about the forward in state, so it can be processed after the execution of 'receiveWormholeMessages',
// because we will then know how much of the 'maxTransactionFee' of the current delivery is still available for use in this forward
setForwardInstruction(
ForwardInstruction({
IWormholeRelayerInternalStructs.ForwardInstruction({
container: encodeDeliveryInstructionsContainer(instructionsContainer),
msgValue: msg.value,
totalFee: totalFee,

View File

@ -1,4 +1,3 @@
// contracts/Bridge.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
@ -7,7 +6,7 @@ import "../interfaces/IWormholeReceiver.sol";
import "../interfaces/IDelivery.sol";
import "../interfaces/IForwardWrapper.sol";
import "./CoreRelayerGovernance.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
contract CoreRelayerDelivery is CoreRelayerGovernance {
enum DeliveryStatus {
@ -36,8 +35,11 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
* @param forwardInstruction A struct containing information about the user's forward/multichainForward request
*
*/
function emitForward(uint256 transactionFeeRefundAmount, ForwardInstruction memory forwardInstruction) internal {
DeliveryInstructionsContainer memory container =
function emitForward(
uint256 transactionFeeRefundAmount,
IWormholeRelayerInternalStructs.ForwardInstruction memory forwardInstruction
) internal {
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory container =
decodeDeliveryInstructionsContainer(forwardInstruction.container);
// Add any additional funds which were passed in to the forward as msg.value
@ -98,10 +100,10 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
* - deliveryVaaHash hash of delivery VAA
*/
function _executeDelivery(
DeliveryInstruction memory internalInstruction,
IWormholeRelayerInternalStructs.DeliveryInstruction memory internalInstruction,
bytes[] memory encodedVMs,
address payable relayerRefundAddress,
DeliveryVAAInfo memory vaaInfo
IWormholeRelayerInternalStructs.DeliveryVAAInfo memory vaaInfo
) internal {
if (internalInstruction.targetAddress != 0x0) {
if (isContractLocked()) {
@ -135,7 +137,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
}
// Retrieve the forward instruction created during execution of 'receiveWormholeMessages'
ForwardInstruction memory forwardInstruction = getForwardInstruction();
IWormholeRelayerInternalStructs.ForwardInstruction memory forwardInstruction = getForwardInstruction();
//clear forwarding request from storage
clearForwardInstruction();
@ -174,7 +176,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
}
function payRefunds(
DeliveryInstruction memory internalInstruction,
IWormholeRelayerInternalStructs.DeliveryInstruction memory internalInstruction,
address payable relayerRefundAddress,
uint256 transactionFeeRefundAmount,
bool receiverValueWasPaid,
@ -208,7 +210,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
}
/**
* @notice The relay provider calls 'deliverSingle' to relay messages as described by one delivery instruction
* @notice The relay provider calls 'deliver' 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),
* receiver value (in this chain's currency), upper bound on gas, and the permissioned address allowed to execute this instruction
@ -228,7 +230,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
*
* @param targetParams struct containing the signed wormhole messages and encoded delivery instruction container (and other information)
*/
function deliverSingle(IDelivery.TargetDeliveryParametersSingle memory targetParams) public payable {
function deliver(IDelivery.TargetDeliveryParameters memory targetParams) public payable {
IWormhole wormhole = wormhole();
// Obtain the delivery VAA
@ -245,12 +247,14 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
revert IDelivery.InvalidEmitter();
}
DeliveryInstructionsContainer memory container = decodeDeliveryInstructionsContainer(deliveryVM.payload);
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory container =
decodeDeliveryInstructionsContainer(deliveryVM.payload);
// 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
DeliveryInstruction memory deliveryInstruction = container.instructions[targetParams.multisendIndex];
IWormholeRelayerInternalStructs.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) {
@ -269,7 +273,7 @@ contract CoreRelayerDelivery is CoreRelayerGovernance {
deliveryInstruction,
targetParams.encodedVMs,
targetParams.relayerRefundAddress,
DeliveryVAAInfo({
IWormholeRelayerInternalStructs.DeliveryVAAInfo({
sourceChain: deliveryVM.emitterChainId,
sourceSequence: deliveryVM.sequence,
deliveryVaaHash: deliveryVM.hash

View File

@ -1,11 +1,10 @@
// contracts/Getters.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../interfaces/IWormhole.sol";
import "../interfaces/IRelayProvider.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
import "./CoreRelayerState.sol";
import "../libraries/external/BytesLib.sol";
@ -53,7 +52,7 @@ contract CoreRelayerGetters is CoreRelayerState {
return _state.defaultRelayProvider;
}
function getForwardInstruction() public view returns (CoreRelayerStructs.ForwardInstruction memory) {
function getForwardInstruction() public view returns (IWormholeRelayerInternalStructs.ForwardInstruction memory) {
return _state.forwardInstruction;
}

View File

@ -1,4 +1,3 @@
// contracts/Relayer.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
@ -9,7 +8,7 @@ import "../libraries/external/BytesLib.sol";
import "./CoreRelayerGetters.sol";
import "./CoreRelayerSetters.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
import "./CoreRelayerMessages.sol";
import "../interfaces/IWormhole.sol";

View File

@ -1,4 +1,3 @@
// contracts/Implementation.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

View File

@ -1,4 +1,3 @@
// contracts/Bridge.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
@ -6,10 +5,10 @@ pragma solidity ^0.8.0;
import "../libraries/external/BytesLib.sol";
import "./CoreRelayerGetters.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
import "../interfaces/IWormholeRelayer.sol";
contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
contract CoreRelayerMessages is CoreRelayerGetters {
using BytesLib for bytes;
error InvalidPayloadId(uint8 payloadId);
@ -50,7 +49,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
function convertMultichainSendToDeliveryInstructionsContainer(IWormholeRelayer.MultichainSend memory sendContainer)
internal
view
returns (DeliveryInstructionsContainer memory instructionsContainer)
returns (IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory instructionsContainer)
{
instructionsContainer.payloadId = 1;
instructionsContainer.senderAddress = toWormholeFormat(msg.sender);
@ -59,7 +58,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
instructionsContainer.messages = sendContainer.messages;
uint256 length = sendContainer.requests.length;
instructionsContainer.instructions = new DeliveryInstruction[](length);
instructionsContainer.instructions = new IWormholeRelayerInternalStructs.DeliveryInstruction[](length);
for (uint256 i = 0; i < length; i++) {
instructionsContainer.instructions[i] =
convertSendToDeliveryInstruction(sendContainer.requests[i], relayProvider);
@ -84,7 +83,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
function convertSendToDeliveryInstruction(IWormholeRelayer.Send memory send, IRelayProvider relayProvider)
internal
view
returns (DeliveryInstruction memory instruction)
returns (IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction)
{
instruction.targetChain = send.targetChain;
instruction.targetAddress = send.targetAddress;
@ -94,7 +93,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
calculateTargetDeliveryMaximumRefund(send.targetChain, send.maxTransactionFee, relayProvider);
instruction.receiverValueTarget =
convertReceiverValueAmount(send.receiverValue, send.targetChain, relayProvider);
instruction.executionParameters = ExecutionParameters({
instruction.executionParameters = IWormholeRelayerInternalStructs.ExecutionParameters({
version: 1,
gasLimit: calculateTargetGasDeliveryAmount(send.targetChain, send.maxTransactionFee, relayProvider)
});
@ -108,13 +107,13 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
* @param container A DeliveryInstructionsContainer
* @param relayProvider The relayProvider whos maximum budget we are checking against
*/
function checkInstructions(DeliveryInstructionsContainer memory container, IRelayProvider relayProvider)
internal
view
{
function checkInstructions(
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory container,
IRelayProvider relayProvider
) internal view {
uint256 length = container.instructions.length;
for (uint8 i = 0; i < length; i++) {
DeliveryInstruction memory instruction = container.instructions[i];
IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction = container.instructions[i];
if (instruction.executionParameters.gasLimit == 0) {
revert IWormholeRelayer.MaxTransactionFeeNotEnough(i);
}
@ -127,12 +126,10 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
}
}
// encode a 'DeliveryInstructionsContainer' into bytes
function encodeDeliveryInstructionsContainer(DeliveryInstructionsContainer memory container)
public
pure
returns (bytes memory encoded)
{
// encode a 'IWormholeRelayerInternalStructs.DeliveryInstructionsContainer' into bytes
function encodeDeliveryInstructionsContainer(
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory container
) public pure returns (bytes memory encoded) {
encoded = abi.encodePacked(
container.payloadId,
container.senderAddress,
@ -165,7 +162,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
}
// encode a 'DeliveryInstruction' into bytes
function encodeDeliveryInstruction(DeliveryInstruction memory instruction)
function encodeDeliveryInstruction(IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction)
internal
pure
returns (bytes memory encoded)
@ -302,6 +299,9 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
bool roundUp,
IRelayProvider provider
) internal view returns (uint256 targetAmount) {
if (!provider.isChainSupported(targetChain)) {
revert IWormholeRelayer.RelayProviderDoesNotSupportTargetChain();
}
uint256 srcNativeCurrencyPrice = provider.quoteAssetPrice(sourceChain);
if (srcNativeCurrencyPrice == 0) {
revert IWormholeRelayer.RelayProviderDoesNotSupportTargetChain();
@ -348,7 +348,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
function decodeDeliveryInstruction(bytes memory encoded, uint256 index)
public
pure
returns (DeliveryInstruction memory instruction, uint256 newIndex)
returns (IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction, uint256 newIndex)
{
// target chain of the delivery instruction
instruction.targetChain = encoded.toUint16(index);
@ -410,7 +410,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
function decodeDeliveryInstructionsContainer(bytes memory encoded)
public
pure
returns (DeliveryInstructionsContainer memory)
returns (IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory)
{
uint256 index = 0;
@ -437,7 +437,8 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
(messages[i], index) = decodeMessageInfo(encoded, index);
}
DeliveryInstruction[] memory instructionArray = new DeliveryInstruction[](instructionsArrayLen);
IWormholeRelayerInternalStructs.DeliveryInstruction[] memory instructionArray =
new IWormholeRelayerInternalStructs.DeliveryInstruction[](instructionsArrayLen);
for (uint8 i = 0; i < instructionsArrayLen; i++) {
(instructionArray[i], index) = decodeDeliveryInstruction(encoded, index);
}
@ -446,7 +447,7 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
revert InvalidDeliveryInstructionsPayload(encoded.length);
}
return DeliveryInstructionsContainer({
return IWormholeRelayerInternalStructs.DeliveryInstructionsContainer({
payloadId: payloadId,
senderAddress: senderAddress,
relayProviderAddress: relayProviderAddress,

View File

@ -1,4 +1,3 @@
// contracts/Wormhole.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

View File

@ -1,11 +1,10 @@
// contracts/Setters.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./CoreRelayerState.sol";
import "@openzeppelin/contracts/utils/Context.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
import {IWormhole} from "../interfaces/IWormhole.sol";
contract CoreRelayerSetters is CoreRelayerState, Context {
@ -43,7 +42,7 @@ contract CoreRelayerSetters is CoreRelayerState, Context {
_state.registeredCoreRelayerContract[chainId] = relayerAddress;
}
function setForwardInstruction(CoreRelayerStructs.ForwardInstruction memory request) internal {
function setForwardInstruction(IWormholeRelayerInternalStructs.ForwardInstruction memory request) internal {
_state.forwardInstruction = request;
}

View File

@ -1,4 +1,3 @@
// contracts/Setup.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;

View File

@ -1,9 +1,8 @@
// contracts/State.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
contract CoreRelayerStorage {
struct Provider {
@ -26,7 +25,7 @@ contract CoreRelayerStorage {
// address of the default relay provider on this chain
address defaultRelayProvider;
// Request which will be forwarded from the current delivery.
CoreRelayerStructs.ForwardInstruction forwardInstruction;
IWormholeRelayerInternalStructs.ForwardInstruction forwardInstruction;
// Wrapper contract to facilitate forwards
address forwardWrapper;
// mapping of initialized implementations

View File

@ -6,7 +6,7 @@ import "../interfaces/IWormholeReceiver.sol";
import "../interfaces/IWormhole.sol";
import "../interfaces/IRelayProvider.sol";
import "../interfaces/IForwardInstructionViewer.sol";
import "./CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
import "../interfaces/IForwardWrapper.sol";
contract ForwardWrapper {
@ -21,11 +21,10 @@ contract ForwardWrapper {
wormhole = IWormhole(_wormhole);
}
function executeInstruction(CoreRelayerStructs.DeliveryInstruction memory instruction, bytes[] memory signedVaas)
public
payable
returns (bool callToTargetContractSucceeded, uint256 transactionFeeRefundAmount)
{
function executeInstruction(
IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction,
bytes[] memory signedVaas
) public payable returns (bool callToTargetContractSucceeded, uint256 transactionFeeRefundAmount) {
if (msg.sender != address(forwardInstructionViewer)) {
revert RequesterNotCoreRelayer();
}
@ -50,7 +49,7 @@ contract ForwardWrapper {
transactionFeeRefundAmount = (instruction.executionParameters.gasLimit - gasUsed)
* instruction.maximumRefundTarget / instruction.executionParameters.gasLimit;
CoreRelayerStructs.ForwardInstruction memory forwardInstruction =
IWormholeRelayerInternalStructs.ForwardInstruction memory forwardInstruction =
forwardInstructionViewer.getForwardInstruction();
if (forwardInstruction.isValid) {

View File

@ -4,7 +4,7 @@ pragma solidity ^0.8.0;
interface IDelivery {
/**
* @notice TargetDeliveryParametersSingle is the struct that the relay provider passes into 'deliverSingle'
* @notice TargetDeliveryParameters is the struct that the relay provider passes into 'deliver'
* containing an array of the signed wormhole messages that are to be relayed
*
* @custom:member encodedVMs An array of signed wormhole messages (all from the same source chain transaction)
@ -13,7 +13,7 @@ interface IDelivery {
* 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 {
struct TargetDeliveryParameters {
bytes[] encodedVMs;
bytes encodedDeliveryVAA;
uint8 multisendIndex;
@ -21,7 +21,7 @@ interface IDelivery {
}
/**
* @notice The relay provider calls 'deliverSingle' to relay messages as described by one delivery instruction
* @notice The relay provider calls 'deliver' 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),
* receiver value (in this chain's currency), upper bound on gas, and the permissioned address allowed to execute this instruction
@ -41,7 +41,7 @@ interface IDelivery {
*
* @param targetParams struct containing the signed wormhole messages and encoded delivery instruction container (and other information)
*/
function deliverSingle(TargetDeliveryParametersSingle memory targetParams) external payable;
function deliver(TargetDeliveryParameters 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

View File

@ -2,15 +2,17 @@
pragma solidity ^0.8.0;
import "../coreRelayer/CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
interface IForwardInstructionViewer {
function getForwardInstruction() external view returns (CoreRelayerStructs.ForwardInstruction memory);
function encodeDeliveryInstructionsContainer(CoreRelayerStructs.DeliveryInstructionsContainer memory container)
function getForwardInstruction()
external
pure
returns (bytes memory encoded);
view
returns (IWormholeRelayerInternalStructs.ForwardInstruction memory);
function encodeDeliveryInstructionsContainer(
IWormholeRelayerInternalStructs.DeliveryInstructionsContainer memory container
) external pure returns (bytes memory encoded);
/**
* @notice Helper function that converts an Wormhole format (32-byte) address to the EVM 'address' 20-byte format

View File

@ -2,11 +2,11 @@
pragma solidity ^0.8.0;
import "../coreRelayer/CoreRelayerStructs.sol";
import "../interfaces/IWormholeRelayerInternalStructs.sol";
interface IForwardWrapper {
function executeInstruction(CoreRelayerStructs.DeliveryInstruction memory instruction, bytes[] memory signedVaas)
external
payable
returns (bool callToTargetContractSucceeded, uint256 transactionFeeRefundAmount);
function executeInstruction(
IWormholeRelayerInternalStructs.DeliveryInstruction memory instruction,
bytes[] memory signedVaas
) external payable returns (bool callToTargetContractSucceeded, uint256 transactionFeeRefundAmount);
}

View File

@ -19,4 +19,6 @@ interface IRelayProvider {
function getRewardAddress() external view returns (address payable rewardAddress);
function getConsistencyLevel() external view returns (uint8 consistencyLevel);
function isChainSupported(uint16 targetChainId) external view returns (bool supported);
}

View File

@ -1,11 +1,10 @@
// contracts/Structs.sol
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
import "../interfaces/IWormholeRelayer.sol";
abstract contract CoreRelayerStructs {
interface IWormholeRelayerInternalStructs {
struct DeliveryInstructionsContainer {
uint8 payloadId; //1
bytes32 senderAddress;

View File

@ -13,8 +13,7 @@ contract RelayProvider is RelayProviderGovernance, IRelayProvider {
//Returns the delivery overhead fee required to deliver a message to targetChain, denominated in this chain's wei.
function quoteDeliveryOverhead(uint16 targetChain) public view override returns (uint256 nativePriceQuote) {
uint256 targetFees =
uint256(1) * deliverGasOverhead(targetChain) * gasPrice(targetChain) + wormholeFee(targetChain);
uint256 targetFees = uint256(1) * deliverGasOverhead(targetChain) * gasPrice(targetChain);
return quoteAssetConversion(targetChain, targetFees, chainId());
}
@ -43,6 +42,10 @@ contract RelayProvider is RelayProviderGovernance, IRelayProvider {
return 200; //REVISE consider adding state variable for this
}
function isChainSupported(uint16 targetChainId) public view override returns (bool supported) {
return _state.supportedChains[targetChainId];
}
//Returns a buffer amount, and a buffer denominator, whereby the bufferAmount / bufferDenominator will be reduced from
//receiverValue conversions, giving an overhead to the provider on each conversion
function getAssetConversionBuffer(uint16 targetChain)

View File

@ -44,10 +44,6 @@ contract RelayProviderGetters is RelayProviderState {
return _state.maximumBudget[targetChainId];
}
function wormholeFee(uint16 targetChainId) public view returns (uint32) {
return _state.wormholeFee[targetChainId];
}
function rewardAddress() public view returns (address payable) {
return _state.rewardAddress;
}

View File

@ -22,12 +22,11 @@ abstract contract RelayProviderGovernance is RelayProviderGetters, RelayProvider
error CallerMustBeOwner();
event ContractUpgraded(address indexed oldContract, address indexed newContract);
event ChainSupportUpdated(uint16 targetChainId, bool isSupported);
event OwnershipTransfered(address indexed oldOwner, address indexed newOwner);
event RewardAddressUpdated(address indexed newAddress);
event DeliveryAddressUpdated(uint16 indexed targetChainId, bytes32 indexed newAddress);
event DeliverGasOverheadUpdated(uint32 indexed oldGasOverhead, uint32 indexed newGasOverhead);
event CoreRelayerUpdated(address coreRelayer);
event ApprovedSenderUpdated(address sender, bool approved);
event AssetConversionBufferUpdated(uint16 targetChain, uint16 buffer, uint16 bufferDenominator);
function updateCoreRelayer(address payable newAddress) public onlyOwner {
@ -35,6 +34,11 @@ abstract contract RelayProviderGovernance is RelayProviderGetters, RelayProvider
emit CoreRelayerUpdated(newAddress);
}
function updateSupportedChain(uint16 targetChainId, bool isSupported) public onlyOwner {
setChainSupported(targetChainId, isSupported);
emit ChainSupportUpdated(targetChainId, isSupported);
}
function updateRewardAddress(address payable newAddress) public onlyOwner {
setRewardAddress(newAddress);
emit RewardAddressUpdated(newAddress);
@ -46,10 +50,6 @@ abstract contract RelayProviderGovernance is RelayProviderGetters, RelayProvider
emit DeliverGasOverheadUpdated(currentGasOverhead, newGasOverhead);
}
function updateWormholeFee(uint16 chainId, uint32 newWormholeFee) public onlyOwner {
setWormholeFee(chainId, newWormholeFee);
}
function updatePrice(uint16 updateChainId, uint128 updateGasPrice, uint128 updateNativeCurrencyPrice)
public
onlyOwner

View File

@ -28,12 +28,12 @@ contract RelayProviderSetters is Context, RelayProviderState {
_state.coreRelayer = coreRelayer;
}
function setDeliverGasOverhead(uint16 chainId, uint32 deliverGasOverhead) internal {
_state.deliverGasOverhead[chainId] = deliverGasOverhead;
function setChainSupported(uint16 targetChainId, bool isSupported) internal {
_state.supportedChains[targetChainId] = isSupported;
}
function setWormholeFee(uint16 chainId, uint32 wormholeFee) internal {
_state.wormholeFee[chainId] = wormholeFee;
function setDeliverGasOverhead(uint16 chainId, uint32 deliverGasOverhead) internal {
_state.deliverGasOverhead[chainId] = deliverGasOverhead;
}
function setRewardAddress(address payable rewardAddress) internal {

View File

@ -30,12 +30,12 @@ contract RelayProviderStorage {
address payable coreRelayer;
// Dictionary of implementation contract -> initialized flag
mapping(address => bool) initializedImplementations;
// Supported chains to deliver to
mapping(uint16 => bool) supportedChains;
// Dictionary of wormhole chain id -> price data
mapping(uint16 => PriceData) data;
// The delivery overhead gas required to deliver a message to targetChain, denominated in targetChain's gas.
mapping(uint16 => uint32) deliverGasOverhead;
// The wormhole fee to deliver a message to targetChain, denominated in targetChain's wei.
mapping(uint16 => uint32) wormholeFee;
// The maximum budget that is allowed for a delivery on target chain, denominated in the targetChain's wei.
mapping(uint16 => uint256) maximumBudget;
// Dictionary of wormhole chain id -> assetConversion

View File

@ -123,7 +123,7 @@ contract MockGenericRelayer {
uint256 budget =
container.instructions[k].maximumRefundTarget + container.instructions[k].receiverValueTarget;
uint16 targetChain = container.instructions[k].targetChain;
IDelivery.TargetDeliveryParametersSingle memory package = IDelivery.TargetDeliveryParametersSingle({
IDelivery.TargetDeliveryParameters memory package = IDelivery.TargetDeliveryParameters({
encodedVMs: encodedVMsToBeDelivered,
encodedDeliveryVAA: encodedDeliveryVAA,
multisendIndex: k,
@ -131,7 +131,7 @@ contract MockGenericRelayer {
});
console.log("A..");
vm.prank(relayers[targetChain]);
IDelivery(wormholeRelayerContracts[targetChain]).deliverSingle{value: budget}(package);
IDelivery(wormholeRelayerContracts[targetChain]).deliver{value: budget}(package);
console.log("A...DONE");
}
bytes32 key = keccak256(abi.encodePacked(parsedDeliveryVAA.emitterChainId, parsedDeliveryVAA.sequence));

View File

@ -12,12 +12,12 @@ import {RelayProviderStructs} from "../contracts/relayProvider/RelayProviderStru
import {IWormholeRelayer} from "../contracts/interfaces/IWormholeRelayer.sol";
import {IDelivery} from "../contracts/interfaces/IDelivery.sol";
import {CoreRelayer} from "../contracts/coreRelayer/CoreRelayer.sol";
import {CoreRelayerStructs} from "../contracts/coreRelayer/CoreRelayerStructs.sol";
import {IWormholeRelayerInternalStructs} from "../contracts/interfaces/IWormholeRelayerInternalStructs.sol";
import {CoreRelayerSetup} from "../contracts/coreRelayer/CoreRelayerSetup.sol";
import {CoreRelayerImplementation} from "../contracts/coreRelayer/CoreRelayerImplementation.sol";
import {CoreRelayerProxy} from "../contracts/coreRelayer/CoreRelayerProxy.sol";
import {CoreRelayerMessages} from "../contracts/coreRelayer/CoreRelayerMessages.sol";
import {CoreRelayerStructs} from "../contracts/coreRelayer/CoreRelayerStructs.sol";
import {IWormholeRelayerInternalStructs} from "../contracts/interfaces/IWormholeRelayerInternalStructs.sol";
import {CoreRelayerGovernance} from "../contracts/coreRelayer/CoreRelayerGovernance.sol";
import {MockGenericRelayer} from "./MockGenericRelayer.sol";
import {MockWormhole} from "../contracts/mock/MockWormhole.sol";
@ -154,17 +154,6 @@ contract WormholeRelayerTests is Test {
s.source.wormholeSimulator.setMessageFee(feeParams.wormholeFeeOnSource);
s.target.wormholeSimulator.setMessageFee(feeParams.wormholeFeeOnTarget);
uint32 wormholeFeeOnTargetInSourceCurrency = uint32(
feeParams.wormholeFeeOnTarget * s.source.relayProvider.quoteAssetPrice(s.targetChainId)
/ s.source.relayProvider.quoteAssetPrice(s.sourceChainId) + 1
);
s.source.relayProvider.updateWormholeFee(s.targetChainId, wormholeFeeOnTargetInSourceCurrency);
uint32 wormholeFeeOnSourceInTargetCurrency = uint32(
feeParams.wormholeFeeOnSource * s.target.relayProvider.quoteAssetPrice(s.sourceChainId)
/ s.target.relayProvider.quoteAssetPrice(s.targetChainId) + 1
);
s.target.relayProvider.updateWormholeFee(s.sourceChainId, wormholeFeeOnSourceInTargetCurrency);
}
struct Contracts {
@ -204,6 +193,7 @@ contract WormholeRelayerTests is Test {
uint256 maxBudget = type(uint256).max;
for (uint16 i = 1; i <= numChains; i++) {
for (uint16 j = 1; j <= numChains; j++) {
map[i].relayProvider.updateSupportedChain(j, true);
map[i].relayProvider.updateAssetConversionBuffer(j, 500, 10000);
map[i].relayProvider.updateRewardAddress(map[i].rewardAddress);
helpers.registerCoreRelayerContract(
@ -765,8 +755,8 @@ contract WormholeRelayerTests is Test {
bytes[] encodedVMs;
IWormhole.VM parsed;
uint256 budget;
IDelivery.TargetDeliveryParametersSingle package;
CoreRelayer.DeliveryInstruction instruction;
IDelivery.TargetDeliveryParameters package;
IWormholeRelayerInternalStructs.DeliveryInstruction instruction;
}
function prepareDeliveryStack(DeliveryStack memory stack, StandardSetupTwoChains memory setup) internal {
@ -788,7 +778,7 @@ contract WormholeRelayerTests is Test {
stack.encodedVMs[0] = stack.actualVM1;
stack.encodedVMs[1] = stack.actualVM2;
stack.package = IDelivery.TargetDeliveryParametersSingle({
stack.package = IDelivery.TargetDeliveryParameters({
encodedVMs: stack.encodedVMs,
encodedDeliveryVAA: stack.deliveryVM,
multisendIndex: 0,
@ -829,7 +819,7 @@ contract WormholeRelayerTests is Test {
stack.deliveryVM = fakeVM;
stack.package = IDelivery.TargetDeliveryParametersSingle({
stack.package = IDelivery.TargetDeliveryParameters({
encodedVMs: stack.encodedVMs,
encodedDeliveryVAA: stack.deliveryVM,
multisendIndex: 0,
@ -838,7 +828,7 @@ contract WormholeRelayerTests is Test {
vm.prank(setup.target.relayer);
vm.expectRevert(abi.encodeWithSignature("InvalidDeliveryVaa(string)", ""));
setup.target.coreRelayerFull.deliverSingle{value: stack.budget}(stack.package);
setup.target.coreRelayerFull.deliver{value: stack.budget}(stack.package);
}
function testRevertDeliveryInvalidEmitter(
@ -864,7 +854,7 @@ contract WormholeRelayerTests is Test {
stack.deliveryVM = stack.encodedVMs[0];
stack.package = IDelivery.TargetDeliveryParametersSingle({
stack.package = IDelivery.TargetDeliveryParameters({
encodedVMs: stack.encodedVMs,
encodedDeliveryVAA: stack.deliveryVM,
multisendIndex: 0,
@ -873,7 +863,7 @@ contract WormholeRelayerTests is Test {
vm.prank(setup.target.relayer);
vm.expectRevert(abi.encodeWithSignature("InvalidEmitter()"));
setup.target.coreRelayerFull.deliverSingle{value: stack.budget}(stack.package);
setup.target.coreRelayerFull.deliver{value: stack.budget}(stack.package);
}
function testRevertDeliveryInsufficientRelayerFunds(
@ -899,7 +889,7 @@ contract WormholeRelayerTests is Test {
vm.prank(setup.target.relayer);
vm.expectRevert(abi.encodeWithSignature("InsufficientRelayerFunds()"));
setup.target.coreRelayerFull.deliverSingle{value: stack.budget - 1}(stack.package);
setup.target.coreRelayerFull.deliver{value: stack.budget - 1}(stack.package);
}
function testRevertDeliveryTargetChainIsNotThisChain(
@ -925,7 +915,7 @@ contract WormholeRelayerTests is Test {
vm.prank(setup.target.relayer);
vm.expectRevert(abi.encodeWithSignature("TargetChainIsNotThisChain(uint16)", 2));
map[setup.differentChainId].coreRelayerFull.deliverSingle{value: stack.budget}(stack.package);
map[setup.differentChainId].coreRelayerFull.deliver{value: stack.budget}(stack.package);
}
struct SendStackTooDeep {
@ -1177,11 +1167,6 @@ contract WormholeRelayerTests is Test {
setup.source.integration.sendMessageWithRefundAddress{value: maxTransactionFee + uint256(3) * wormholeFee}(
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)
);
}
function testToAndFromWormholeFormat(bytes32 msg2, address msg1) public {

View File

@ -12,12 +12,11 @@ import {RelayProviderStructs} from "../contracts/relayProvider/RelayProviderStru
import {IWormholeRelayer} from "../contracts/interfaces/IWormholeRelayer.sol";
import {IDelivery} from "../contracts/interfaces/IDelivery.sol";
import {CoreRelayer} from "../contracts/coreRelayer/CoreRelayer.sol";
import {CoreRelayerStructs} from "../contracts/coreRelayer/CoreRelayerStructs.sol";
import {IWormholeRelayerInternalStructs} from "../contracts/interfaces/IWormholeRelayerInternalStructs.sol";
import {CoreRelayerSetup} from "../contracts/coreRelayer/CoreRelayerSetup.sol";
import {CoreRelayerImplementation} from "../contracts/coreRelayer/CoreRelayerImplementation.sol";
import {CoreRelayerProxy} from "../contracts/coreRelayer/CoreRelayerProxy.sol";
import {CoreRelayerMessages} from "../contracts/coreRelayer/CoreRelayerMessages.sol";
import {CoreRelayerStructs} from "../contracts/coreRelayer/CoreRelayerStructs.sol";
import {CoreRelayerGovernance} from "../contracts/coreRelayer/CoreRelayerGovernance.sol";
import {MockGenericRelayer} from "./MockGenericRelayer.sol";
import {MockWormhole} from "../contracts/mock/MockWormhole.sol";

View File

@ -4,31 +4,31 @@
"relayProviders": [
{
"chainId": 2,
"address": "0xb4fFe5983B0B748124577Af4d16953bd096b6897"
"address": "0xB349FB172D6D5f693b0aA1C6eEc4c61cFd6846f4"
},
{
"chainId": 4,
"address": "0xdFccc9C59c7361307d47c558ffA75840B32DbA29"
"address": "0x9ce4cd6D7f5e8b14c7a3e8e6A257A86Bd5a6EeA0"
}
],
"coreRelayers": [
{
"chainId": 2,
"address": "0x42D4BA5e542d9FeD87EA657f0295F1968A61c00A"
"address": "0x68b86Cd90A44C805b1cCF4808b29C9c7cf73FDFF"
},
{
"chainId": 4,
"address": "0xFF5181e2210AB92a5c9db93729Bc47332555B9E9"
"address": "0xd45A464a2412A2f83498d13635698a041b9dBe9b"
}
],
"mockIntegrations": [
{
"chainId": 2,
"address": "0x3F4E941ef5071a1D09C2eB4a24DA1Fc43F76fcfF"
"address": "0xB0015714B541A99265f529c7c0d34DA47deCA5b2"
},
{
"chainId": 4,
"address": "0x0d3C71782055bD88A71b611972152d6e984EDF79"
"address": "0xc22Ffa318051d8aF4E5f2E2732d7049486fcE093"
}
]
}

View File

@ -62,10 +62,6 @@ async function configureChainsRelayProvider(chain: ChainInfo) {
console.log("Set address info...")
await relayProvider.updateRewardAddress(thisChainsConfigInfo.rewardAddress).then(wait)
for (const { address, approved } of thisChainsConfigInfo.approvedSenders) {
console.log(`Setting approved sender: ${address}, approved: ${approved}`)
await relayProvider.updateApprovedSender(address, approved).then(wait)
}
console.log("Set gas and native prices...")

View File

@ -32,9 +32,8 @@ async function registerChainsRelayProvider(chain: ChainInfo) {
for (let i = 0; i < chains.length; i++) {
console.log(`Cross registering with chain ${chains[i].chainId}...`)
const targetChainProviderAddress = getRelayProviderAddress(chains[i])
const whAddress = "0x" + tryNativeToHexString(targetChainProviderAddress, "ethereum")
await relayProvider.updateDeliveryAddress(chains[i].chainId, whAddress).then(wait)
console.log(`Cross registering with chain ${chains[i].chainId}...`)
await relayProvider.updateSupportedChain(chains[i].chainId, true).then(wait)
}
console.log("done with registrations on " + chain.chainId)

View File

@ -15,7 +15,7 @@ import {
loadMockIntegrations,
} from "../ts-scripts/helpers/env"
import { MockRelayerIntegration, IWormholeRelayer } from "../../sdk/src"
import { getDeliveryInfoBySourceTx, DeliveryInfo, RedeliveryInfo } from "../../sdk/src"
//import { getDeliveryInfoBySourceTx, DeliveryInfo, RedeliveryInfo } from "../../sdk/src"
const ETHEREUM_ROOT = `${__dirname}/..`
init()
@ -280,6 +280,7 @@ describe("Core Relayer Integration Test - Two Chains", () => {
expect(message2).to.equal(arbitraryPayload2)
})
/*
it("Executes a redelivery", async () => {
const arbitraryPayload = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
@ -451,8 +452,9 @@ describe("Core Relayer Integration Test - Two Chains", () => {
})
*/
/*
it("Tests the Typescript SDK during a delivery", async () => {
const arbitraryPayload = ethers.utils.hexlify(
ethers.utils.toUtf8Bytes(generateRandomString(32))
@ -579,5 +581,6 @@ describe("Core Relayer Integration Test - Two Chains", () => {
expect(status).to.equal("Delivery Success")
})
*/
})

View File

@ -5,6 +5,7 @@
"main": "index.js",
"scripts": {
"start": "ts-node src/app.ts --flag=testnet",
"tilt": "ts-node src/app.ts --flag=tilt",
"build": "tsc",
"watch": "tsc --watch",
"test": "echo \"Error: no test specified\" && exit 1"
@ -17,7 +18,7 @@
"@types/koa": "^2.13.5",
"clone": "^2.1.2",
"koa": "^2.14.1",
"wormhole-relayer": "github:gabzim/wormhole-relayer#0c82a15",
"wormhole-relayer": "github:gabzim/wormhole-relayer#03c7c62",
"yargs": "^17.7.1"
},
"peerDependencies": {

View File

@ -1,4 +1,4 @@
export type { CoreRelayer, CoreRelayerStructs } from "./ethers-contracts/CoreRelayer"
export type { CoreRelayer } from "./ethers-contracts/CoreRelayer"
export { CoreRelayer__factory } from "./ethers-contracts/factories/CoreRelayer__factory"
export type { MockRelayerIntegration } from "./ethers-contracts/MockRelayerIntegration"
export { MockRelayerIntegration__factory } from "./ethers-contracts/factories/MockRelayerIntegration__factory"

View File

@ -15,7 +15,7 @@ import * as deepCopy from "clone"
export type GRContext = StandardRelayerContext & {
relayProviders: Record<EVMChainId, string>
wormholeRelayer: Record<EVMChainId, string>
wormholeRelayers: Record<EVMChainId, string>
}
type Opts = {
@ -38,7 +38,7 @@ type ContractsJson = {
async function main() {
let opts = yargs(process.argv.slice(2)).argv as unknown as Opts
const contracts = await loadContractsJson()
const contracts = await loadContractsJson(opts.flag)
const app = new StandardRelayerApp<GRContext>(flagToEnvironment(opts.flag), {
name: "GenericRelayer",
@ -61,7 +61,7 @@ async function main() {
// Set up middleware
app.use(async (ctx: GRContext, next: Next) => {
ctx.relayProviders = deepCopy(relayProviders)
ctx.wormholeRelayer = deepCopy(wormholeRelayers)
ctx.wormholeRelayers = deepCopy(wormholeRelayers)
next()
})
@ -98,9 +98,9 @@ function flagToEnvironment(flag: Flag): Environment {
}
}
async function loadContractsJson(): Promise<ContractsJson> {
async function loadContractsJson(flag: Flag): Promise<ContractsJson> {
return JSON.parse(
await fs.readFile(`../ethereum/ts-scripts/config/testnet/contracts.json`, {
await fs.readFile(`../ethereum/ts-scripts/config/${flag}/contracts.json`, {
encoding: "utf-8",
})
) as ContractsJson

View File

@ -4,7 +4,7 @@ import {
IDelivery,
MessageInfoType,
RelayerPayloadId,
RelayProvider__factory,
CoreRelayer__factory,
parseWormholeRelayerPayloadType,
parseWormholeRelayerSend,
} from "../pkgs/sdk/src"
@ -46,29 +46,21 @@ async function processDelivery(ctx: GRContext) {
const budget = ix.receiverValueTarget.add(ix.maximumRefundTarget).add(100)
await ctx.wallets.onEVM(chainId, async ({ wallet }) => {
const relayProvider = RelayProvider__factory.connect(
ctx.relayProviders[chainId],
const coreRelayer = CoreRelayer__factory.connect(
ctx.wormholeRelayers[chainId],
wallet
)
const input: IDelivery.TargetDeliveryParametersSingleStruct = {
const input: IDelivery.TargetDeliveryParametersStruct = {
encodedVMs: fetchedVaas.map((v) => v.bytes),
encodedDeliveryVAA: ctx.vaaBytes!,
multisendIndex: i,
relayerRefundAddress: wallet.address,
}
const isApprovedSender = await relayProvider.approvedSender(wallet.address)
if (!isApprovedSender) {
ctx.logger.warn(
`Approved sender not set correctly for chain ${chainId}, should be ${wallet.address}`
)
return
}
await relayProvider
await coreRelayer
// @ts-ignore
.deliverSingle(input, { value: budget, gasLimit: 3000000 })
.deliver(input, { value: budget, gasLimit: 3000000 })
.then((x) => x.wait())
ctx.logger.info(

View File

@ -1,4 +1,4 @@
export type { CoreRelayer, CoreRelayerStructs } from "./ethers-contracts/CoreRelayer"
export type { CoreRelayer } from "./ethers-contracts/CoreRelayer"
export { CoreRelayer__factory } from "./ethers-contracts/factories/CoreRelayer__factory"
export type { MockRelayerIntegration } from "./ethers-contracts/MockRelayerIntegration"
export { MockRelayerIntegration__factory } from "./ethers-contracts/factories/MockRelayerIntegration__factory"

View File

@ -1,4 +1,4 @@
export type { CoreRelayer, CoreRelayerStructs } from "./ethers-contracts/CoreRelayer"
export type { CoreRelayer } from "./ethers-contracts/CoreRelayer"
export { CoreRelayer__factory } from "./ethers-contracts/factories/CoreRelayer__factory"
export type { MockRelayerIntegration } from "./ethers-contracts/MockRelayerIntegration"
export { MockRelayerIntegration__factory } from "./ethers-contracts/factories/MockRelayerIntegration__factory"