Skip to content

Commit a03c740

Browse files
authored
evm: Explicitly check staticcalls (#375)
* evm: Explicitly check staticcalls * Add check to test helper * Add negative test
1 parent 35ef80c commit a03c740

File tree

5 files changed

+50
-3
lines changed

5 files changed

+50
-3
lines changed

evm/src/NttManager/NttManager.sol

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,13 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
531531
}
532532

533533
function tokenDecimals() public view override(INttManager, RateLimiter) returns (uint8) {
534-
(, bytes memory queriedDecimals) = token.staticcall(abi.encodeWithSignature("decimals()"));
534+
(bool success, bytes memory queriedDecimals) =
535+
token.staticcall(abi.encodeWithSignature("decimals()"));
536+
537+
if (!success) {
538+
revert StaticcallFailed();
539+
}
540+
535541
return abi.decode(queriedDecimals, (uint8));
536542
}
537543

@@ -572,8 +578,13 @@ contract NttManager is INttManager, RateLimiter, ManagerBase {
572578
address tokenAddr,
573579
address accountAddr
574580
) internal view returns (uint256) {
575-
(, bytes memory queriedBalance) =
581+
(bool success, bytes memory queriedBalance) =
576582
tokenAddr.staticcall(abi.encodeWithSelector(IERC20.balanceOf.selector, accountAddr));
583+
584+
if (!success) {
585+
revert StaticcallFailed();
586+
}
587+
577588
return abi.decode(queriedBalance, (uint256));
578589
}
579590
}

evm/src/interfaces/INttManager.sol

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ interface INttManager is IManagerBase {
117117
/// @notice Peer cannot have zero decimals.
118118
error InvalidPeerDecimals();
119119

120+
/// @notice Staticcall reverted
121+
/// @dev Selector 0x1222cd83
122+
error StaticcallFailed();
123+
120124
/// @notice Error when someone other than the original sender tries to cancel a queued outbound transfer.
121125
/// @dev Selector 0xceb40a85.
122126
/// @param canceller The address trying to cancel the transfer.

evm/src/mocks/DummyToken.sol

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,13 @@ contract DummyTokenDifferentDecimals is DummyTokenMintAndBurn {
5454
return _decimals;
5555
}
5656
}
57+
58+
contract DummyTokenBroken is DummyToken {
59+
function decimals() public pure override returns (uint8) {
60+
revert("broken decimals");
61+
}
62+
63+
function balanceOf(address) public pure override returns (uint256) {
64+
revert("broken balanceOf");
65+
}
66+
}

evm/test/NttManager.t.sol

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,22 @@ contract TestNttManager is Test, IRateLimiterEvents {
230230
assertEq(nttManager.isPaused(), false);
231231
}
232232

233+
// === deployment with invalid token
234+
function test_brokenToken() public {
235+
DummyToken t = new DummyTokenBroken();
236+
NttManager implementation = new MockNttManagerContract(
237+
address(t), IManagerBase.Mode.LOCKING, chainId, 1 days, false
238+
);
239+
240+
NttManager newNttManager =
241+
MockNttManagerContract(address(new ERC1967Proxy(address(implementation), "")));
242+
vm.expectRevert(abi.encodeWithSelector(INttManager.StaticcallFailed.selector));
243+
newNttManager.initialize();
244+
245+
vm.expectRevert(abi.encodeWithSelector(INttManager.StaticcallFailed.selector));
246+
newNttManager.transfer(1, 1, bytes32("1"));
247+
}
248+
233249
// === transceiver registration
234250

235251
function test_registerTransceiver() public {

evm/test/libraries/NttManagerHelpers.sol

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ pragma solidity >=0.8.8 <0.9.0;
44

55
import "../../src/libraries/TrimmedAmount.sol";
66
import "../../src/NttManager/NttManager.sol";
7+
import "../../src/interfaces/INttManager.sol";
78

89
library NttManagerHelpersLib {
910
uint16 constant SENDING_CHAIN_ID = 1;
@@ -16,8 +17,13 @@ library NttManagerHelpersLib {
1617
NttManager recipientNttManager,
1718
uint8 decimals
1819
) internal {
19-
(, bytes memory queriedDecimals) =
20+
(bool success, bytes memory queriedDecimals) =
2021
address(nttManager.token()).staticcall(abi.encodeWithSignature("decimals()"));
22+
23+
if (!success) {
24+
revert INttManager.StaticcallFailed();
25+
}
26+
2127
uint8 tokenDecimals = abi.decode(queriedDecimals, (uint8));
2228
recipientNttManager.setPeer(
2329
SENDING_CHAIN_ID, toWormholeFormat(address(nttManager)), tokenDecimals, type(uint64).max

0 commit comments

Comments
 (0)