diff --git a/contracts/SpokePool.sol b/contracts/SpokePool.sol index 888beb905..87ddcfa10 100644 --- a/contracts/SpokePool.sol +++ b/contracts/SpokePool.sol @@ -1307,6 +1307,9 @@ abstract contract SpokePool is **************************************/ function _depositV3(DepositV3Params memory params) internal { + // Verify depositor is a valid EVM address. + params.depositor.checkAddress(); + // Check that deposit route is enabled for the input token. There are no checks required for the output token // which is pulled from the relayer at fill time and passed through this contract atomically to the recipient. if (!enabledDepositRoutes[params.inputToken.toAddress()][params.destinationChainId]) revert DisabledRoute(); diff --git a/contracts/libraries/AddressConverters.sol b/contracts/libraries/AddressConverters.sol index 929bd789c..6b52ff479 100644 --- a/contracts/libraries/AddressConverters.sol +++ b/contracts/libraries/AddressConverters.sol @@ -8,15 +8,19 @@ library Bytes32ToAddress { error InvalidBytes32(); function toAddress(bytes32 _bytes32) internal pure returns (address) { - if (uint256(_bytes32) >> 160 != 0) { - revert InvalidBytes32(); - } + checkAddress(_bytes32); return address(uint160(uint256(_bytes32))); } function toAddressUnchecked(bytes32 _bytes32) internal pure returns (address) { return address(uint160(uint256(_bytes32))); } + + function checkAddress(bytes32 _bytes32) internal pure { + if (uint256(_bytes32) >> 160 != 0) { + revert InvalidBytes32(); + } + } } library AddressToBytes32 { diff --git a/test/evm/hardhat/SpokePool.Deposit.ts b/test/evm/hardhat/SpokePool.Deposit.ts index 64cd36f8c..fff3cf5f0 100644 --- a/test/evm/hardhat/SpokePool.Deposit.ts +++ b/test/evm/hardhat/SpokePool.Deposit.ts @@ -853,6 +853,15 @@ describe("SpokePool Depositor Logic", async function () { const functionCalldata = spokePool.interface.encodeFunctionData("deposit", [...depositArgs]); await expect(spokePool.connect(depositor).callback(functionCalldata)).to.be.reverted; }); + it("depositor must be valid evm address", async function () { + const functionCalldata = spokePool.interface.encodeFunctionData("deposit", [ + ...getDepositArgsFromRelayData({ + ...relayData, + depositor: "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d", + }), + ]); + await expect(spokePool.connect(depositor).callback(functionCalldata)).to.be.reverted; + }); it("unsafe deposit ID", async function () { // new deposit ID should be the uint256 equivalent of the keccak256 hash of packed {msg.sender, depositor, forcedDepositId}. const forcedDepositId = "99";