Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: capping gasLimit in the quoteEvmDeliveryPrice #4649

Merged
merged 1 commit into from
Jul 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,9 @@ abstract contract BaseWormhole is GasCap {
* https://github.com/wormhole-foundation/wormhole/blob/main/ethereum/contracts/relayer/deliveryProvider/DeliveryProvider.sol
*/
function quoteEVMDeliveryPrice(uint256 _gasLimit, address _amb) public view returns (uint256 _cost) {
(_cost, ) = IWormholeRelayer(_amb).quoteEVMDeliveryPrice(MIRROR_WORMHOLE_ID, 0, _gasLimit);
// First Get the gas, if it is more than the cap use the cap
// And calculcate delievery price with gasCap
(_cost, ) = IWormholeRelayer(_amb).quoteEVMDeliveryPrice(MIRROR_WORMHOLE_ID, 0, _getGas(_gasLimit));
}

// ============ Private fns ============
Expand Down Expand Up @@ -105,8 +107,11 @@ abstract contract BaseWormhole is GasCap {
// Should always be sending a merkle root
require(_data.length == 32, "!data length");

// Should include gas limit info in specialized calldata
require(_encodedData.length == 32, "!encoded data length");

//calculate cost to deliver message
uint256 gasLimit = _getGasFromEncoded(_encodedData);
uint256 gasLimit = abi.decode(_encodedData, (uint256));
uint256 deliveryCost = quoteEVMDeliveryPrice(gasLimit, _amb);
require(deliveryCost == msg.value, "!msg.value");

Expand All @@ -129,15 +134,4 @@ abstract contract BaseWormhole is GasCap {
require(uint256(_whFormatAddress) >> 160 == 0, "!evm address");
return address(uint160(uint256(_whFormatAddress)));
}

/**
* @notice Using Wormhole relayer (AMB), the gas is provided to `sendMessage` as an encoded uint
*/
function _getGasFromEncoded(bytes memory _encodedData) internal view returns (uint256 _gas) {
// Should include gssas info in specialized calldata
require(_encodedData.length == 32, "!encoded data length");

// Get the gas, if it is more than the cap use the cap
_gas = _getGas(abi.decode(_encodedData, (uint256)));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,69 @@ contract WormholeHubConnectorTest is ConnectorHelper {
WormholeHubConnector(_l1Connector).sendMessage{value: 100}(_data, encodedData);
}

function test_WormholeHubConnector_sendMessage_sendMessageWithGasCap(bytes memory _data) public {
vm.assume(_data.length == 32);

uint256 gasLimit = _gasCapL2 + 1;
bytes memory encodedData = abi.encode(gasLimit);

// Mock the call to fees
vm.mockCall(
_amb,
abi.encodeWithSignature("quoteEVMDeliveryPrice(uint16,uint256,uint256)", _chainIdL2, 0, _gasCapL2),
abi.encode(100, 100)
);

// Mock the call to sendPayloadToEvm
vm.mockCall(
_amb,
100,
abi.encodeWithSignature(
"sendPayloadToEvm(uint16,address,bytes,uint256,uint256,uint16,address)",
_chainIdL2,
address(_l2Connector),
_data,
uint256(0),
gasLimit,
_chainIdL2,
_owner
),
abi.encode(uint64(1))
);

// Check: correct event?
vm.expectEmit(false, false, false, true, _l1Connector);
emit MessageSent(_data, encodedData, _rootManager);

// Check: call to sendPayloadToEvm?
vm.expectCall(
_amb,
100,
abi.encodeWithSignature(
"sendPayloadToEvm(uint16,address,bytes,uint256,uint256,uint16,address)",
_chainIdL2,
address(_l2Connector),
_data,
0,
gasLimit,
_chainIdL2,
_owner
)
);

// Check: call to fees?
vm.expectCall(
_amb,
abi.encodeWithSignature("quoteEVMDeliveryPrice(uint16,uint256,uint256)", _chainIdL2, 0, _gasCapL2)
);

vm.deal(_rootManager, 1 ether);
vm.prank(_rootManager);
WormholeHubConnector(_l1Connector).sendMessage{value: 100}(_data, encodedData);
}

// Access control
function test_WormholeHubConnector_sendMessage_revertIfSenderIsNotRootManager(
function test_WormholeConnector_sendMessage_revertIfSenderIsNotRootManager(
address _nonRootManager,
bytes memory _data
) public {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,65 @@ contract WormholeSpokeConnectorTest is ConnectorHelper {
WormholeSpokeConnector(_l2Connector).send{value: 100}(encodedData);
}

function test_WormholeSpokeConnector_send_sendWithGasCap(bytes32 _root) public {
vm.assume(_root != bytes32(0));
uint256 gasLimit = _gasCapL1 + 1;
bytes memory encodedData = abi.encode(gasLimit);
bytes memory _data = abi.encodePacked(_root);

// Mock the call to fees
vm.mockCall(
_amb,
abi.encodeWithSignature("quoteEVMDeliveryPrice(uint16,uint256,uint256)", _chainIdL1, 0, _gasCapL1),
abi.encode(100, 100)
);

vm.mockCall(_merkle, abi.encodeWithSelector(MerkleTreeManager.root.selector), abi.encode(_root));

// Mock the call to sendPayloadToEvm
vm.mockCall(
_amb,
100,
abi.encodeWithSignature(
"sendPayloadToEvm(uint16,address,bytes,uint256,uint256,uint16,address)",
_chainIdL1,
address(_l1Connector),
_data,
uint256(0),
gasLimit,
_chainIdL1,
_owner
),
abi.encode(uint64(1))
);

// Check: call to sendPayloadToEvm?
vm.expectCall(
_amb,
100,
abi.encodeWithSignature(
"sendPayloadToEvm(uint16,address,bytes,uint256,uint256,uint16,address)",
_chainIdL1,
address(_l1Connector),
_data,
0,
gasLimit,
_chainIdL1,
_owner
)
);

// Check: call to fees?
vm.expectCall(
_amb,
abi.encodeWithSignature("quoteEVMDeliveryPrice(uint16,uint256,uint256)", _chainIdL1, 0, _gasCapL1)
);

vm.deal(_owner, 1 ether);
vm.prank(_owner);
WormholeSpokeConnector(_l2Connector).send{value: 100}(encodedData);
}

// data length
function test_WormholeSpokeConnector_send_failsIfBadDataLength(bytes memory _data) public {
vm.assume(_data.length != 32);
Expand Down