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.
72 lines
2.9 KiB
Solidity
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 {}
|
|
}
|