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

Consider using assembly for low level call to avoid return bombs #107

Closed
michaelkaplan13 opened this issue Nov 3, 2023 · 1 comment · Fixed by #119
Closed

Consider using assembly for low level call to avoid return bombs #107

michaelkaplan13 opened this issue Nov 3, 2023 · 1 comment · Fixed by #119
Assignees
Labels
bug Something isn't working enhancement New feature or request

Comments

@michaelkaplan13
Copy link
Collaborator

michaelkaplan13 commented Nov 3, 2023

Context and scope
When a message is delivered, an external call is made to the destinationAddress specified by the message sender where the amount of gas the call can use is specified in the message by the requiredGasLimit value. The return data from this call is not used and only the success of the call is recorded. Although a gas limit is set for the call, the external contract could force the transaction to use gas in excess of the specified limit due to an open issue with the Solidity compiler. This is possible because the TeleporterMessenger contract pays for memory expansion to accommodate the return data, but the external contract controls the size of that return data. Consider using assembly to explicitly prevent any memory from being allocated for the return data from the external call.

See reference here.

For instance, the change could look like:

        // Call the destination address of the message with the formatted call data.
        // Only provide the required gas limit to the sub-call so that the end application
        // cannot consume an arbitrary amount gas.
        bytes memory payload = abi.encodeCall(
            ITeleporterReceiver.receiveTeleporterMessage,
            (originChainID, message.senderAddress, message.message)
        );
        address target = message.destinationAddress;
        uint256 requiredGas = message.requiredGasLimit;
        bool success;
        assembly ("memory-safe") {
            success := call(
               requiredGas, // gas provided to the call
                target, // call target
                0, // zero value
                add(payload, 0x20), // input data
                mload(payload), // input data length
                0, // output
                0 // output size
            )
        }

        // If the execution failed, store a hash of the message in state such that its
        // execution can be retried again in the future with a higher gas limit (paid by whoever
        // retries).Either way, the message will now be considered "delivered" since the relayer
        // provided enough gas to meet the required gas limit.
        if (!success) {
            _storeFailedMessageExecution(originChainID, message);
            return;
        }

Open questions
Does call in assembly return false if the contract being call hits a revert statement?

@michaelkaplan13 michaelkaplan13 added bug Something isn't working enhancement New feature or request labels Nov 3, 2023
@minghinmatthewlam minghinmatthewlam added this to the production launch milestone Nov 7, 2023
@michaelkaplan13 michaelkaplan13 self-assigned this Nov 8, 2023
@michaelkaplan13 michaelkaplan13 moved this from 📋 Backlog to 🏗 In progress in Avalanche Warp Messaging Nov 8, 2023
@michaelkaplan13
Copy link
Collaborator Author

Does call in assembly return false if the contract being call hits a revert statement?

The answer is yes. I previous had the target and requiredGas in the incorrect order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working enhancement New feature or request
Projects
Archived in project
Status: 👀 In review
Development

Successfully merging a pull request may close this issue.

2 participants