Rebase completed!
This commit is contained in:
parent
f0c610c237
commit
46d276e37e
|
@ -57,7 +57,7 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
Send[] memory requests = new Send[](1);
|
||||
requests[0] = request;
|
||||
MultichainSend memory container =
|
||||
MultichainSend({payloadId: 1, relayProviderAddress: address(provider), requests: requests});
|
||||
MultichainSend({ relayProviderAddress: address(provider), requests: requests});
|
||||
return multichainSend(container, nonce);
|
||||
}
|
||||
|
||||
|
@ -65,7 +65,7 @@ contract CoreRelayer is CoreRelayerGovernance {
|
|||
Send[] memory requests = new Send[](1);
|
||||
requests[0] = request;
|
||||
MultichainSend memory container =
|
||||
MultichainSend({payloadId: 1, relayProviderAddress: address(provider), requests: requests});
|
||||
MultichainSend({relayProviderAddress: address(provider), requests: requests});
|
||||
return multichainForward(container, request.targetChain, nonce);
|
||||
}
|
||||
|
||||
|
|
|
@ -198,6 +198,6 @@ contract CoreRelayerMessages is CoreRelayerStructs, CoreRelayerGetters {
|
|||
}
|
||||
|
||||
return
|
||||
MultichainSend({payloadId: payloadId, relayProviderAddress: relayProviderAddress, requests: requestArray});
|
||||
MultichainSend({ relayProviderAddress: relayProviderAddress, requests: requestArray});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,7 +10,6 @@ abstract contract CoreRelayerStructs {
|
|||
//which should be considered untrusted and unmodifiable
|
||||
|
||||
struct MultichainSend {
|
||||
uint8 payloadId; // payloadID = 1
|
||||
address relayProviderAddress;
|
||||
Send[] requests;
|
||||
}
|
||||
|
|
|
@ -41,10 +41,12 @@ interface IWormholeRelayer {
|
|||
payable
|
||||
returns (uint64 sequence);
|
||||
|
||||
|
||||
/**
|
||||
* @dev When requesting a multiforward, the rollover chain is the chain where any remaining funds should be sent once all
|
||||
* the requested budgets have been covered. The remaining funds will be added to the maxTransactionFee of the rollover chain.
|
||||
*/
|
||||
|
||||
function multichainForward(MultichainSend memory deliveryRequests, uint16 rolloverChain, uint32 nonce)
|
||||
external
|
||||
payable;
|
||||
|
|
|
@ -5,7 +5,7 @@ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
|||
|
||||
import "../interfaces/IWormhole.sol";
|
||||
import "../interfaces/IWormholeReceiver.sol";
|
||||
import "../interfaces/ICoreRelayer.sol";
|
||||
import "../interfaces/IWormholeRelayer.sol";
|
||||
|
||||
/**
|
||||
* This contract is a malicious "integration" that attempts to attack the forward mechanism.
|
||||
|
@ -14,7 +14,7 @@ contract AttackForwardIntegration is IWormholeReceiver {
|
|||
mapping(bytes32 => bool) consumedMessages;
|
||||
address attackerReward;
|
||||
IWormhole wormhole;
|
||||
ICoreRelayer core_relayer;
|
||||
IWormholeRelayer core_relayer;
|
||||
uint32 nonce = 1;
|
||||
uint16 targetChainId;
|
||||
|
||||
|
@ -22,7 +22,7 @@ contract AttackForwardIntegration is IWormholeReceiver {
|
|||
// This just needs to be enough to pay for the call to the destination address.
|
||||
uint32 SAFE_DELIVERY_GAS_CAPTURE = 30000;
|
||||
|
||||
constructor(IWormhole initWormhole, ICoreRelayer initCoreRelayer, uint16 chainId, address initAttackerReward) {
|
||||
constructor(IWormhole initWormhole, IWormholeRelayer initCoreRelayer, uint16 chainId, address initAttackerReward) {
|
||||
attackerReward = initAttackerReward;
|
||||
wormhole = initWormhole;
|
||||
core_relayer = initCoreRelayer;
|
||||
|
@ -43,21 +43,21 @@ contract AttackForwardIntegration is IWormholeReceiver {
|
|||
}
|
||||
|
||||
function requestForward(uint16 targetChain, bytes32 attackerRewardAddress) internal {
|
||||
uint256 computeBudget = core_relayer.quoteGasDeliveryFee(
|
||||
uint256 maxTransactionFee = core_relayer.quoteGas(
|
||||
targetChain, SAFE_DELIVERY_GAS_CAPTURE, core_relayer.getDefaultRelayProvider()
|
||||
);
|
||||
|
||||
ICoreRelayer.DeliveryRequest memory request = ICoreRelayer.DeliveryRequest({
|
||||
IWormholeRelayer.Send memory request = IWormholeRelayer.Send({
|
||||
targetChain: targetChain,
|
||||
targetAddress: attackerRewardAddress,
|
||||
// All remaining funds will be returned to the attacker
|
||||
refundAddress: attackerRewardAddress,
|
||||
computeBudget: computeBudget,
|
||||
applicationBudget: 0,
|
||||
maxTransactionFee: maxTransactionFee,
|
||||
receiverValue: 0,
|
||||
relayParameters: core_relayer.getDefaultRelayParams()
|
||||
});
|
||||
|
||||
core_relayer.requestForward{value: computeBudget}(request, nonce, core_relayer.getDefaultRelayProvider());
|
||||
core_relayer.forward{value: maxTransactionFee}(request, nonce, core_relayer.getDefaultRelayProvider());
|
||||
}
|
||||
|
||||
function toWormholeFormat(address addr) public pure returns (bytes32 whFormat) {
|
||||
|
|
|
@ -95,27 +95,26 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
uint16[] memory chains,
|
||||
uint256[] memory computeBudgets
|
||||
) public payable {
|
||||
for(uint16 i=0; i<messages.length; i++) {
|
||||
for (uint16 i = 0; i < messages.length; i++) {
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(1, messages[i], 200);
|
||||
}
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(1, encodeFurtherInstructions(furtherInstructions), 200);
|
||||
ICoreRelayer.DeliveryRequest[] memory requests = new ICoreRelayer.DeliveryRequest[](chains.length);
|
||||
for(uint16 i=0; i<chains.length; i++) {
|
||||
requests[i] = ICoreRelayer.DeliveryRequest({
|
||||
IWormholeRelayer.Send[] memory requests = new IWormholeRelayer.Send[](chains.length);
|
||||
for (uint16 i = 0; i < chains.length; i++) {
|
||||
requests[i] = IWormholeRelayer.Send({
|
||||
targetChain: chains[i],
|
||||
targetAddress: registeredContracts[chains[i]],
|
||||
refundAddress: registeredContracts[chains[i]],
|
||||
computeBudget: computeBudgets[i],
|
||||
applicationBudget: 0,
|
||||
maxTransactionFee: computeBudgets[i],
|
||||
receiverValue: 0,
|
||||
relayParameters: relayer.getDefaultRelayParams()
|
||||
});
|
||||
});
|
||||
}
|
||||
ICoreRelayer.DeliveryRequestsContainer memory container = ICoreRelayer.DeliveryRequestsContainer({
|
||||
payloadId: 1,
|
||||
IWormholeRelayer.MultichainSend memory container = IWormholeRelayer.MultichainSend({
|
||||
requests: requests,
|
||||
relayProviderAddress: address(relayer.getDefaultRelayProvider())
|
||||
relayProviderAddress: relayer.getDefaultRelayProvider()
|
||||
});
|
||||
relayer.requestMultidelivery{value: (msg.value - wormhole.messageFee()*(1 + messages.length))}(container, 1);
|
||||
relayer.multichainSend{value: (msg.value - wormhole.messageFee() * (1 + messages.length))}(container, 1);
|
||||
}
|
||||
|
||||
function executeSend(
|
||||
|
@ -129,14 +128,12 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
targetChain: targetChainId,
|
||||
targetAddress: relayer.toWormholeFormat(address(destination)),
|
||||
refundAddress: relayer.toWormholeFormat(address(refundAddress)), // This will be ignored on the target chain if the intent is to perform a forward
|
||||
maxTransactionFee: msg.value - 3 * wormhole.messageFee() - applicationBudget,
|
||||
maxTransactionFee: msg.value - 3 * wormhole.messageFee() - receiverValue,
|
||||
receiverValue: receiverValue,
|
||||
relayParameters: relayer.getDefaultRelayParams()
|
||||
});
|
||||
|
||||
relayer.send{value: msg.value - 2 * wormhole.messageFee()}(
|
||||
request, nonce, relayer.getDefaultRelayProvider()
|
||||
);
|
||||
relayer.send{value: msg.value - 2 * wormhole.messageFee()}(request, nonce, relayer.getDefaultRelayProvider());
|
||||
}
|
||||
|
||||
function receiveWormholeMessages(bytes[] memory wormholeObservations, bytes[] memory) public payable override {
|
||||
|
@ -159,8 +156,7 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
for (uint16 i = 0; i < instructions.newMessages.length; i++) {
|
||||
wormhole.publishMessage{value: wormhole.messageFee()}(parsed.nonce, instructions.newMessages[i], 200);
|
||||
}
|
||||
IWormholeRelayer.Send[] memory sendRequests =
|
||||
new IWormholeRelayer.Send[](instructions.chains.length);
|
||||
IWormholeRelayer.Send[] memory sendRequests = new IWormholeRelayer.Send[](instructions.chains.length);
|
||||
for (uint16 i = 0; i < instructions.chains.length; i++) {
|
||||
sendRequests[i] = IWormholeRelayer.Send({
|
||||
targetChain: instructions.chains[i],
|
||||
|
@ -173,8 +169,9 @@ contract MockRelayerIntegration is IWormholeReceiver {
|
|||
relayParameters: relayer.getDefaultRelayParams()
|
||||
});
|
||||
}
|
||||
IWormholeRelayer.SendContainer memory container =
|
||||
IWormholeRelayer.SendContainer(1, address(relayer.getDefaultRelayProvider()), sendRequests);
|
||||
IWormholeRelayer.MultichainSend memory container =
|
||||
IWormholeRelayer.MultichainSend({requests: sendRequests, relayProviderAddress: relayer.getDefaultRelayProvider()});
|
||||
|
||||
relayer.multichainForward(container, sendRequests[0].targetChain, parsed.nonce);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -393,8 +393,7 @@ contract TestCoreRelayer is Test {
|
|||
relayerProfit / gasParams.targetGasPrice / feeParams.targetNativePrice;
|
||||
assertTrue(howMuchGasRelayerCouldHavePaidForAndStillProfited >= 30000); // takes around this much gas (seems to go from 36k-200k?!?)
|
||||
assertTrue(
|
||||
USDcost - (relayerProfit + (uint256(1) * feeParams.receiverValueTarget * feeParams.targetNativePrice))
|
||||
>= 0,
|
||||
USDcost - (relayerProfit + (uint256(1) * feeParams.receiverValueTarget * feeParams.targetNativePrice)) >= 0,
|
||||
"We paid enough"
|
||||
);
|
||||
assertTrue(
|
||||
|
@ -517,18 +516,18 @@ contract TestCoreRelayer is Test {
|
|||
);
|
||||
|
||||
vm.assume(
|
||||
setup.source.coreRelayer.quoteGasDeliveryFee(
|
||||
setup.targetChainId, gasParams.targetGasLimit, setup.source.relayProvider
|
||||
setup.source.coreRelayer.quoteGas(
|
||||
setup.targetChainId, gasParams.targetGasLimit, address(setup.source.relayProvider)
|
||||
) < uint256(2) ** 222
|
||||
);
|
||||
vm.assume(
|
||||
setup.target.coreRelayer.quoteGasDeliveryFee(setup.sourceChainId, 500000, setup.target.relayProvider)
|
||||
setup.target.coreRelayer.quoteGas(setup.sourceChainId, 500000, address(setup.target.relayProvider))
|
||||
< uint256(2) ** 222 / feeParams.targetNativePrice
|
||||
);
|
||||
|
||||
// Estimate the cost based on the initialized values
|
||||
uint256 computeBudget = setup.source.coreRelayer.quoteGasDeliveryFee(
|
||||
setup.targetChainId, gasParams.targetGasLimit, setup.source.relayProvider
|
||||
uint256 computeBudget = setup.source.coreRelayer.quoteGas(
|
||||
setup.targetChainId, gasParams.targetGasLimit, address(setup.source.relayProvider)
|
||||
);
|
||||
|
||||
{
|
||||
|
@ -784,12 +783,7 @@ contract TestCoreRelayer is Test {
|
|||
vm.expectRevert(abi.encodeWithSignature("NonceIsZero()"));
|
||||
|
||||
setup.source.integration.sendMessageGeneral{value: maxTransactionFee + 3 * wormholeFee}(
|
||||
message,
|
||||
setup.targetChainId,
|
||||
address(setup.target.integration),
|
||||
address(setup.target.refundAddress),
|
||||
0,
|
||||
0
|
||||
message, setup.targetChainId, address(setup.target.integration), address(setup.target.refundAddress), 0, 0
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -1084,7 +1078,6 @@ contract TestCoreRelayer is Test {
|
|||
vm.prank(setup.target.relayer);
|
||||
setup.target.coreRelayerFull.redeliverSingle{value: stack.budget}(stack.package);
|
||||
assertTrue(keccak256(setup.target.integration.getMessage()) == keccak256(message));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue