Copy
Ask AI
// SPDX-License-Identifier: GPL-3.0
pragma solidity 0.8.29;
import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
import { IPushOracleReceiver } from "./interfaces/oracle/IPushOracleReceiver.sol";
import { IInterchainSecurityModule } from "./interfaces/IInterchainSecurityModule.sol";
import { ProtocolFeeHook } from "./ProtocolFeeHook.sol";
import { TypeCasts } from "./libs/TypeCasts.sol";
contract PushOracleReceiver is IPushOracleReceiver, Ownable {
using TypeCasts for address;
IInterchainSecurityModule public interchainSecurityModule;
address payable public paymentHook;
address public trustedMailBox;
mapping(string => Data) public updates;
error InvalidISMAddress();
modifier validateAddress(address _address) {
if (_address == address(0)) revert InvalidAddress();
_;
}
function handle(
uint32 _origin,
bytes32 _sender,
bytes calldata _data
) external payable override validateAddress(paymentHook) {
if (msg.sender != trustedMailBox) revert UnauthorizedMailbox();
if (address(interchainSecurityModule) == address(0))
revert InvalidISMAddress();
(string memory key, uint128 timestamp, uint128 value) = abi.decode(
_data,
(string, uint128, uint128)
);
if (updates[key].timestamp >= timestamp) {
return;
}
Data memory newData = Data({ timestamp: timestamp, value: value });
updates[key] = newData;
emit ReceivedMessage(key, timestamp, value);
uint256 gasPrice = tx.gasprice;
uint256 fee = ProtocolFeeHook(payable(paymentHook)).gasUsedPerTx() *
gasPrice;
bool success;
{
(success, ) = paymentHook.call{ value: fee }("");
}
if (!success) revert AmountTransferFailed();
}
function setInterchainSecurityModule(
address _ism
) external onlyOwner validateAddress(_ism) {
emit InterchainSecurityModuleUpdated(
address(interchainSecurityModule),
_ism
);
interchainSecurityModule = IInterchainSecurityModule(_ism);
}
function setPaymentHook(
address payable _paymentHook
) external onlyOwner validateAddress(_paymentHook) {
emit PaymentHookUpdated(paymentHook, _paymentHook);
paymentHook = _paymentHook;
}
function setTrustedMailBox(
address _mailbox
) external onlyOwner validateAddress(_mailbox) {
emit TrustedMailBoxUpdated(trustedMailBox, _mailbox);
trustedMailBox = _mailbox;
}
function retrieveLostTokens(
address receiver
) external onlyOwner validateAddress(receiver) {
uint256 balance = address(this).balance;
if (balance == 0) revert NoBalanceToWithdraw();
(bool success, ) = payable(receiver).call{ value: balance }("");
if (!success) revert AmountTransferFailed();
emit TokensRecovered(receiver, balance);
}
receive() external payable {}
fallback() external payable {}
}