The home for Hyperlane core contracts, sdk packages, and other infrastructure
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
hyperlane-monorepo/solidity/contracts/isms/warp-route/RateLimitedIsm.sol

69 lines
2.0 KiB

// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
import {IMailbox} from "contracts/interfaces/IMailbox.sol";
import {MailboxClient} from "contracts/client/MailboxClient.sol";
import {RateLimited} from "contracts/libs/RateLimited.sol";
import {IInterchainSecurityModule} from "contracts/interfaces/IInterchainSecurityModule.sol";
import {Message} from "contracts/libs/Message.sol";
import {TokenMessage} from "contracts/token/libs/TokenMessage.sol";
contract RateLimitedIsm is
MailboxClient,
RateLimited,
IInterchainSecurityModule
{
using Message for bytes;
using TokenMessage for bytes;
address public immutable recipient;
mapping(bytes32 messageId => bool validated) public messageValidated;
modifier validateMessageOnce(bytes calldata _message) {
bytes32 messageId = _message.id();
require(!messageValidated[messageId], "MessageAlreadyValidated");
messageValidated[messageId] = true;
_;
}
modifier onlyRecipient(bytes calldata _message) {
require(_message.recipientAddress() == recipient, "InvalidRecipient");
_;
}
constructor(
address _mailbox,
uint256 _maxCapacity,
address _recipient
) MailboxClient(_mailbox) RateLimited(_maxCapacity) {
recipient = _recipient;
}
/// @inheritdoc IInterchainSecurityModule
function moduleType() external pure returns (uint8) {
return uint8(IInterchainSecurityModule.Types.NULL);
}
/**
* Verify a message, rate limit, and increment the sender's limit.
* @dev ensures that this gets called by the Mailbox
*/
function verify(
bytes calldata,
bytes calldata _message
)
external
onlyRecipient(_message)
validateMessageOnce(_message)
returns (bool)
{
require(_isDelivered(_message.id()), "InvalidDeliveredMessage");
uint256 newAmount = _message.body().amount();
validateAndConsumeFilledLevel(newAmount);
return true;
}
}