Skip to content

Commit 47dcbca

Browse files
authored
STABLE-7554: Internal audit changes (circlefin#44)
1 parent 2e28bff commit 47dcbca

14 files changed

+273
-133
lines changed

src/MessageTransmitter.sol

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -247,12 +247,10 @@ contract MessageTransmitter is
247247
* of the attester address recovered from signatures.
248248
* @return success bool, true if successful
249249
*/
250-
function receiveMessage(bytes calldata message, bytes calldata attestation)
251-
external
252-
override
253-
whenNotPaused
254-
returns (bool success)
255-
{
250+
function receiveMessage(
251+
bytes calldata message,
252+
bytes calldata attestation
253+
) external override whenNotPaused returns (bool success) {
256254
// Validate each signature in the attestation
257255
_verifyAttestationSignatures(message, attestation);
258256

@@ -313,10 +311,9 @@ contract MessageTransmitter is
313311
* to avoid impacting users who rely on large messages.
314312
* @param newMaxMessageBodySize new max message body size, in bytes
315313
*/
316-
function setMaxMessageBodySize(uint256 newMaxMessageBodySize)
317-
external
318-
onlyOwner
319-
{
314+
function setMaxMessageBodySize(
315+
uint256 newMaxMessageBodySize
316+
) external onlyOwner {
320317
maxMessageBodySize = newMaxMessageBodySize;
321318
emit MaxMessageBodySizeUpdated(maxMessageBodySize);
322319
}
@@ -372,11 +369,10 @@ contract MessageTransmitter is
372369
destination
373370
* @return hash of source and nonce
374371
*/
375-
function _hashSourceAndNonce(uint32 _source, uint64 _nonce)
376-
internal
377-
pure
378-
returns (bytes32)
379-
{
372+
function _hashSourceAndNonce(
373+
uint32 _source,
374+
uint64 _nonce
375+
) internal pure returns (bytes32) {
380376
return keccak256(abi.encodePacked(_source, _nonce));
381377
}
382378

src/messages/v2/AddressUtils.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ library AddressUtils {
2626
* @notice Converts an address to bytes32 by left-padding with zeros (alignment preserving cast.)
2727
* @param addr The address to convert to bytes32
2828
*/
29-
function addressToBytes32(address addr) internal pure returns (bytes32) {
29+
function toBytes32(address addr) internal pure returns (bytes32) {
3030
return bytes32(uint256(uint160(addr)));
3131
}
3232

@@ -36,7 +36,7 @@ library AddressUtils {
3636
* For use cases where this is not acceptable, validate that the first 12 bytes of _buf are zero-padding.
3737
* @param _buf the bytes32 to convert to address
3838
*/
39-
function bytes32ToAddress(bytes32 _buf) internal pure returns (address) {
39+
function toAddress(bytes32 _buf) internal pure returns (address) {
4040
return address(uint160(uint256(_buf)));
4141
}
4242
}

src/messages/v2/MessageV2.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ library MessageV2 {
8383
bytes32 _recipient,
8484
bytes32 _destinationCaller,
8585
uint32 _minFinalityThreshold,
86-
bytes memory _messageBody
86+
bytes calldata _messageBody
8787
) internal pure returns (bytes memory) {
8888
return
8989
abi.encodePacked(

src/v2/BaseMessageTransmitter.sol

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,9 @@
1717
*/
1818
pragma solidity 0.7.6;
1919

20-
import {IMessageTransmitterV2} from "../interfaces/v2/IMessageTransmitterV2.sol";
2120
import {Attestable} from "../roles/Attestable.sol";
2221
import {Pausable} from "../roles/Pausable.sol";
2322
import {Rescuable} from "../roles/Rescuable.sol";
24-
import {MessageV2} from "../messages/v2/MessageV2.sol";
25-
import {AddressUtils} from "../messages/v2/AddressUtils.sol";
26-
import {TypedMemView} from "@memview-sol/contracts/TypedMemView.sol";
27-
import {IMessageHandlerV2} from "../interfaces/v2/IMessageHandlerV2.sol";
2823
import {Initializable} from "../proxy/Initializable.sol";
2924

3025
/**
@@ -85,7 +80,7 @@ contract BaseMessageTransmitter is
8580
/**
8681
* @notice Returns the current initialized version
8782
*/
88-
function initializedVersion() public view returns (uint64) {
83+
function initializedVersion() external view returns (uint64) {
8984
return _getInitializedVersion();
9085
}
9186
}

src/v2/BaseTokenMessenger.sol

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ abstract contract BaseTokenMessenger is Rescuable, Denylistable, Initializable {
211211
/**
212212
* @notice Returns the current initialized version
213213
*/
214-
function initializedVersion() public view returns (uint64) {
214+
function initializedVersion() external view returns (uint64) {
215215
return _getInitializedVersion();
216216
}
217217

@@ -260,9 +260,7 @@ abstract contract BaseTokenMessenger is Rescuable, Denylistable, Initializable {
260260
* @return true if message sender is the registered local message transmitter
261261
*/
262262
function _isLocalMessageTransmitter() internal view returns (bool) {
263-
return
264-
address(localMessageTransmitter) != address(0) &&
265-
msg.sender == address(localMessageTransmitter);
263+
return msg.sender == address(localMessageTransmitter);
266264
}
267265

268266
/**

src/v2/FinalityThresholds.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pragma solidity 0.7.6;
2020
// The threshold at which (and above) messages are considered finalized.
2121
uint32 constant FINALITY_THRESHOLD_FINALIZED = 2000;
2222

23-
// The threshold at which (and above) messages are considered finalized.
23+
// The threshold at which (and above) messages are considered confirmed.
2424
uint32 constant FINALITY_THRESHOLD_CONFIRMED = 1000;
2525

2626
// The minimum allowed level of finality accepted by TokenMessenger

src/v2/MessageTransmitterV2.sol

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,9 +56,12 @@ contract MessageTransmitterV2 is IMessageTransmitterV2, BaseMessageTransmitter {
5656
);
5757

5858
// ============ Libraries ============
59+
using AddressUtils for address;
60+
using AddressUtils for address payable;
61+
using AddressUtils for bytes32;
62+
using MessageV2 for bytes29;
5963
using TypedMemView for bytes;
6064
using TypedMemView for bytes29;
61-
using MessageV2 for bytes29;
6265

6366
// ============ Constructor ============
6467
/**
@@ -117,9 +120,13 @@ contract MessageTransmitterV2 is IMessageTransmitterV2, BaseMessageTransmitter {
117120
maxMessageBodySize = maxMessageBodySize_;
118121

119122
// Attester configuration
120-
for (uint256 i; i < attesters_.length; i++) {
123+
uint256 _attestersLength = attesters_.length;
124+
for (uint256 i; i < _attestersLength; ++i) {
121125
_enableAttester(attesters_[i]);
122126
}
127+
128+
// Claim 0-nonce
129+
usedNonces[bytes32(0)] = 1;
123130
}
124131

125132
// ============ External Functions ============
@@ -147,7 +154,7 @@ contract MessageTransmitterV2 is IMessageTransmitterV2, BaseMessageTransmitter {
147154
);
148155
require(recipient != bytes32(0), "Recipient must be nonzero");
149156

150-
bytes32 _messageSender = AddressUtils.addressToBytes32(msg.sender);
157+
bytes32 _messageSender = msg.sender.toBytes32();
151158

152159
// serialize message
153160
bytes memory _message = MessageV2._formatMessageForRelay(
@@ -292,8 +299,7 @@ contract MessageTransmitterV2 is IMessageTransmitterV2, BaseMessageTransmitter {
292299
// Validate destination caller
293300
if (_msg._getDestinationCaller() != bytes32(0)) {
294301
require(
295-
_msg._getDestinationCaller() ==
296-
AddressUtils.addressToBytes32(msg.sender),
302+
_msg._getDestinationCaller() == msg.sender.toBytes32(),
297303
"Invalid caller for message"
298304
);
299305
}
@@ -308,7 +314,7 @@ contract MessageTransmitterV2 is IMessageTransmitterV2, BaseMessageTransmitter {
308314
// Unpack remaining values
309315
_sourceDomain = _msg._getSourceDomain();
310316
_sender = _msg._getSender();
311-
_recipient = AddressUtils.bytes32ToAddress(_msg._getRecipient());
317+
_recipient = _msg._getRecipient().toAddress();
312318
_finalityThresholdExecuted = _msg._getFinalityThresholdExecuted();
313319
_messageBody = _msg._getMessageBody().clone();
314320
}

src/v2/TokenMessengerV2.sol

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {IRelayerV2} from "../interfaces/v2/IRelayerV2.sol";
2424
import {IMessageHandlerV2} from "../interfaces/v2/IMessageHandlerV2.sol";
2525
import {TypedMemView} from "@memview-sol/contracts/TypedMemView.sol";
2626
import {BurnMessageV2} from "../messages/v2/BurnMessageV2.sol";
27-
import {Initializable} from "../proxy/Initializable.sol";
2827
import {TOKEN_MESSENGER_MIN_FINALITY_THRESHOLD} from "./FinalityThresholds.sol";
2928

3029
/**
@@ -62,9 +61,12 @@ contract TokenMessengerV2 is IMessageHandlerV2, BaseTokenMessenger {
6261
);
6362

6463
// ============ Libraries ============
64+
using AddressUtils for address;
65+
using AddressUtils for address payable;
66+
using AddressUtils for bytes32;
67+
using BurnMessageV2 for bytes29;
6568
using TypedMemView for bytes;
6669
using TypedMemView for bytes29;
67-
using BurnMessageV2 for bytes29;
6870

6971
// ============ Constructor ============
7072
/**
@@ -122,7 +124,8 @@ contract TokenMessengerV2 is IMessageHandlerV2, BaseTokenMessenger {
122124
localMinter = ITokenMinterV2(tokenMinter_);
123125

124126
// Remote messenger configuration
125-
for (uint256 i; i < remoteDomains_.length; i++) {
127+
uint256 _remoteDomainsLength = remoteDomains_.length;
128+
for (uint256 i; i < _remoteDomainsLength; ++i) {
126129
require(
127130
remoteTokenMessengers_[i] != bytes32(0),
128131
"Invalid TokenMessenger"
@@ -344,10 +347,10 @@ contract TokenMessengerV2 is IMessageHandlerV2, BaseTokenMessenger {
344347
// Format message body
345348
bytes memory _burnMessage = BurnMessageV2._formatMessageForRelay(
346349
messageBodyVersion,
347-
AddressUtils.addressToBytes32(_burnToken),
350+
_burnToken.toBytes32(),
348351
_mintRecipient,
349352
_amount,
350-
AddressUtils.addressToBytes32(msg.sender),
353+
msg.sender.toBytes32(),
351354
_maxFee,
352355
_hookData
353356
);
@@ -398,7 +401,7 @@ contract TokenMessengerV2 is IMessageHandlerV2, BaseTokenMessenger {
398401
);
399402

400403
return (
401-
AddressUtils.bytes32ToAddress(_msg._getMintRecipient()),
404+
_msg._getMintRecipient().toAddress(),
402405
_msg._getBurnToken(),
403406
_msg._getAmount()
404407
);
@@ -439,5 +442,6 @@ contract TokenMessengerV2 is IMessageHandlerV2, BaseTokenMessenger {
439442
// Validate fee
440443
_fee = _msg._getFeeExecuted();
441444
require(_fee == 0 || _fee < _amount, "Fee equals or exceeds amount");
445+
require(_fee <= _msg._getMaxFee(), "Fee exceeds max fee");
442446
}
443447
}

test/examples/CCTPHookWrapper.t.sol

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -318,14 +318,16 @@ contract CCTPHookWrapperTest is Test {
318318
bytes memory _hookData
319319
) internal pure returns (bytes memory) {
320320
return
321-
MessageV2._formatMessageForRelay(
321+
abi.encodePacked(
322322
_messageVersion,
323-
0,
324-
0,
325-
bytes32(0),
326-
bytes32(0),
327-
bytes32(0),
328-
0,
323+
uint32(0), // sourceDomain
324+
uint32(0), // destinationDomain
325+
bytes32(0), // nonce
326+
bytes32(0), // sender
327+
bytes32(0), // recipient
328+
bytes32(0), // destinationCaller
329+
uint32(0), // minFinalityThreshold
330+
uint32(0), // finalityThresholdExecuted
329331
_createBurnMessage(_messageBodyVersion, _hookData)
330332
);
331333
}

test/messages/v2/AddressUtils.t.sol

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ import {AddressUtils} from "../../../src/messages/v2/AddressUtils.sol";
2323

2424
contract AddressUtilsTest is Test {
2525
function testAddressToBytes32Conversion(address _addr) public pure {
26-
bytes32 _addrAsBytes32 = AddressUtils.addressToBytes32(_addr);
27-
address _recoveredAddr = AddressUtils.bytes32ToAddress(_addrAsBytes32);
26+
bytes32 _addrAsBytes32 = AddressUtils.toBytes32(_addr);
27+
address _recoveredAddr = AddressUtils.toAddress(_addrAsBytes32);
2828
assertEq(_recoveredAddr, _addr);
2929
}
3030

3131
function testAddressToBytes32LeftPads(address _addr) public pure {
32-
bytes32 _addrAsBytes32 = AddressUtils.addressToBytes32(_addr);
32+
bytes32 _addrAsBytes32 = AddressUtils.toBytes32(_addr);
3333

3434
// addresses are 20 bytes, so the first 12 bytes should be 0 (left-padded)
3535
for (uint8 i; i < 12; i++) {

0 commit comments

Comments
 (0)