aere-contracts/contracts/bridge/AereIGP.sol
Aere Network a13a649b77
Some checks are pending
contracts-ci / Install (lockfile) → compile → full test suite (push) Waiting to run
contracts-ci / PQC known-answer tests (NIST vectors) (push) Waiting to run
contracts-ci / Coverage (scoped, with artifacts) (push) Waiting to run
Initial public release
Aere Network public source. Everything here can be checked against the live
chain (chain id 2800, https://rpc.aere.network).

Scope note, stated up front rather than buried: consensus on chain 2800 is
classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at
the signature, precompile, account and transport layers. Nothing here makes the
consensus post-quantum, and no document in it should be read as claiming so.
2026-07-20 01:02:37 +03:00

72 lines
2.9 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import "@openzeppelin/contracts/access/Ownable.sol";
/**
* @title AereIGP (Interchain Gas Paymaster)
* @notice Receives AERE fees from outbound cross-chain messages.
* Foundation/relayer claims these and uses them to fund the gas paid
* on destination chains when delivering inbound messages from AERE.
*
* Hyperlane-compatible interface — apps using Hyperlane's `quoteDispatch` helpers
* query us for the AERE fee required to relay a message to a given destination.
*
* Pricing model (configurable per destination):
* fee = gasOverhead * gasPriceQuote
*
* gasOverhead = chain-specific gas estimate (e.g. Ethereum ~150k, BSC ~80k).
* gasPriceQuote = AERE-denominated quote of destination chain's gas price.
* Owner sets this; in v2 we'll pull from AereOracle once cross-chain price
* feeds are wired.
*/
contract AereIGP is Ownable {
struct DestinationConfig {
uint256 gasOverhead;
uint256 gasPriceQuoteAere; // wei AERE per unit of destination gas
}
mapping(uint32 => DestinationConfig) public destinations;
address public payoutRecipient;
event GasPaymentReceived(bytes32 indexed messageId, uint32 destDomain, uint256 amount);
event DestinationConfigured(uint32 indexed domain, uint256 gasOverhead, uint256 gasPriceQuote);
event PayoutRecipientChanged(address indexed recipient);
constructor(address _payoutRecipient) {
payoutRecipient = _payoutRecipient;
}
function configure(uint32 domain, uint256 gasOverhead, uint256 gasPriceQuoteAere) external onlyOwner {
destinations[domain] = DestinationConfig(gasOverhead, gasPriceQuoteAere);
emit DestinationConfigured(domain, gasOverhead, gasPriceQuoteAere);
}
function setPayoutRecipient(address _r) external onlyOwner {
payoutRecipient = _r;
emit PayoutRecipientChanged(_r);
}
/// Quote the AERE fee required to relay a message to `destDomain`.
function quoteGasPayment(uint32 destDomain) external view returns (uint256) {
DestinationConfig memory c = destinations[destDomain];
return c.gasOverhead * c.gasPriceQuoteAere;
}
/// Called by AereMessenger via postDispatch when a message includes an IGP fee.
function postDispatch(bytes calldata, bytes calldata data) external payable {
(bytes32 messageId, uint32 destDomain) = abi.decode(data, (bytes32, uint32));
emit GasPaymentReceived(messageId, destDomain, msg.value);
}
/// Sweep accumulated fees to the payout recipient (relayer's hot wallet).
function claim() external {
uint256 bal = address(this).balance;
require(bal > 0, "AereIGP: nothing to claim");
(bool ok, ) = payoutRecipient.call{ value: bal }("");
require(ok, "AereIGP: payout failed");
}
receive() external payable {}
}