357 lines
12 KiB
Solidity
357 lines
12 KiB
Solidity
// contracts/Relayer.sol
|
|
// SPDX-License-Identifier: Apache 2
|
|
|
|
pragma solidity ^0.8.19;
|
|
|
|
import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Upgrade.sol";
|
|
|
|
import "../../libraries/external/BytesLib.sol";
|
|
import "../../interfaces/relayer/TypedUnits.sol";
|
|
|
|
import "./DeliveryProviderGetters.sol";
|
|
import "./DeliveryProviderSetters.sol";
|
|
import "./DeliveryProviderStructs.sol";
|
|
import {getSupportedMessageKeyTypes} from "./DeliveryProviderState.sol";
|
|
|
|
abstract contract DeliveryProviderGovernance is
|
|
DeliveryProviderGetters,
|
|
DeliveryProviderSetters,
|
|
ERC1967Upgrade
|
|
{
|
|
using WeiLib for Wei;
|
|
using GasLib for Gas;
|
|
using DollarLib for Dollar;
|
|
using WeiPriceLib for WeiPrice;
|
|
using GasPriceLib for GasPrice;
|
|
|
|
error ChainIdIsZero();
|
|
error GasPriceIsZero();
|
|
error NativeCurrencyPriceIsZero();
|
|
error FailedToInitializeImplementation(string reason);
|
|
error WrongChainId();
|
|
error AddressIsZero();
|
|
error CallerMustBePendingOwner();
|
|
error CallerMustBeOwner();
|
|
error CallerMustBeOwnerOrPricingWallet();
|
|
|
|
event ContractUpgraded(address indexed oldContract, address indexed newContract);
|
|
event ChainSupportUpdated(uint16 targetChain, bool isSupported);
|
|
event OwnershipTransfered(address indexed oldOwner, address indexed newOwner);
|
|
event RewardAddressUpdated(address indexed newAddress);
|
|
event TargetChainAddressUpdated(uint16 indexed targetChain, bytes32 indexed newAddress);
|
|
event DeliverGasOverheadUpdated(Gas indexed oldGasOverhead, Gas indexed newGasOverhead);
|
|
event WormholeRelayerUpdated(address coreRelayer);
|
|
event AssetConversionBufferUpdated(uint16 targetChain, uint16 buffer, uint16 bufferDenominator);
|
|
|
|
function updateWormholeRelayer(address payable newAddress) external onlyOwner {
|
|
updateWormholeRelayerImpl(newAddress);
|
|
}
|
|
|
|
function updateWormholeRelayerImpl(address payable newAddress) internal {
|
|
setWormholeRelayer(newAddress);
|
|
emit WormholeRelayerUpdated(newAddress);
|
|
}
|
|
|
|
function updateSupportedChain(uint16 targetChain, bool isSupported) public onlyOwner {
|
|
setChainSupported(targetChain, isSupported);
|
|
emit ChainSupportUpdated(targetChain, isSupported);
|
|
}
|
|
|
|
function updateSupportedChains(DeliveryProviderStructs.SupportedChainUpdate[] memory updates)
|
|
public
|
|
onlyOwner
|
|
{
|
|
uint256 updatesLength = updates.length;
|
|
for (uint256 i = 0; i < updatesLength;) {
|
|
DeliveryProviderStructs.SupportedChainUpdate memory update = updates[i];
|
|
updateSupportedChainImpl(update.chainId, update.isSupported);
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateSupportedMessageKeyTypes(uint8 keyType, bool supported)
|
|
public
|
|
onlyOwner
|
|
{
|
|
if (supported) {
|
|
getSupportedMessageKeyTypes().bitmap |= (1 << keyType);
|
|
} else {
|
|
getSupportedMessageKeyTypes().bitmap &= ~(1 << keyType);
|
|
}
|
|
}
|
|
|
|
function updatePricingWallet(address newPricingWallet) external onlyOwner {
|
|
setPricingWallet(newPricingWallet);
|
|
}
|
|
|
|
function updateSupportedChainImpl(uint16 targetChain, bool isSupported) internal {
|
|
setChainSupported(targetChain, isSupported);
|
|
emit ChainSupportUpdated(targetChain, isSupported);
|
|
}
|
|
|
|
function updateRewardAddress(address payable newAddress) external onlyOwner {
|
|
updateRewardAddressImpl(newAddress);
|
|
}
|
|
|
|
function updateRewardAddressImpl(address payable newAddress) internal {
|
|
setRewardAddress(newAddress);
|
|
emit RewardAddressUpdated(newAddress);
|
|
}
|
|
|
|
function updateTargetChainAddress(uint16 targetChain, bytes32 newAddress) public onlyOwner {
|
|
updateTargetChainAddressImpl(targetChain, newAddress);
|
|
}
|
|
|
|
function updateTargetChainAddresses(DeliveryProviderStructs.TargetChainUpdate[] memory updates)
|
|
external
|
|
onlyOwner
|
|
{
|
|
uint256 updatesLength = updates.length;
|
|
for (uint256 i = 0; i < updatesLength;) {
|
|
DeliveryProviderStructs.TargetChainUpdate memory update = updates[i];
|
|
updateTargetChainAddressImpl(update.chainId, update.targetChainAddress);
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateTargetChainAddressImpl(uint16 targetChain, bytes32 newAddress) internal {
|
|
setTargetChainAddress(targetChain, newAddress);
|
|
emit TargetChainAddressUpdated(targetChain, newAddress);
|
|
}
|
|
|
|
function updateDeliverGasOverhead(uint16 chainId, Gas newGasOverhead) external onlyOwnerOrPricingWallet {
|
|
updateDeliverGasOverheadImpl(chainId, newGasOverhead);
|
|
}
|
|
|
|
function updateDeliverGasOverheads(
|
|
DeliveryProviderStructs.DeliverGasOverheadUpdate[] memory overheadUpdates
|
|
) external onlyOwnerOrPricingWallet {
|
|
uint256 updatesLength = overheadUpdates.length;
|
|
for (uint256 i = 0; i < updatesLength;) {
|
|
DeliveryProviderStructs.DeliverGasOverheadUpdate memory update = overheadUpdates[i];
|
|
updateDeliverGasOverheadImpl(update.chainId, update.newGasOverhead);
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateDeliverGasOverheadImpl(uint16 chainId, Gas newGasOverhead) internal {
|
|
Gas currentGasOverhead = deliverGasOverhead(chainId);
|
|
setDeliverGasOverhead(chainId, newGasOverhead);
|
|
emit DeliverGasOverheadUpdated(currentGasOverhead, newGasOverhead);
|
|
}
|
|
|
|
function updatePrice(
|
|
uint16 updateChainId,
|
|
GasPrice updateGasPrice,
|
|
WeiPrice updateNativeCurrencyPrice
|
|
) external onlyOwnerOrPricingWallet {
|
|
updatePriceImpl(updateChainId, updateGasPrice, updateNativeCurrencyPrice);
|
|
}
|
|
|
|
function updatePrices(DeliveryProviderStructs.UpdatePrice[] memory updates)
|
|
external
|
|
onlyOwnerOrPricingWallet
|
|
{
|
|
uint256 pricesLength = updates.length;
|
|
for (uint256 i = 0; i < pricesLength;) {
|
|
DeliveryProviderStructs.UpdatePrice memory update = updates[i];
|
|
updatePriceImpl(update.chainId, update.gasPrice, update.nativeCurrencyPrice);
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updatePriceImpl(
|
|
uint16 updateChainId,
|
|
GasPrice updateGasPrice,
|
|
WeiPrice updateNativeCurrencyPrice
|
|
) internal {
|
|
if (updateChainId == 0) {
|
|
revert ChainIdIsZero();
|
|
}
|
|
if (updateGasPrice.unwrap() == 0) {
|
|
revert GasPriceIsZero();
|
|
}
|
|
if (updateNativeCurrencyPrice.unwrap() == 0) {
|
|
revert NativeCurrencyPriceIsZero();
|
|
}
|
|
|
|
setPriceInfo(updateChainId, updateGasPrice, updateNativeCurrencyPrice);
|
|
}
|
|
|
|
function updateMaximumBudget(uint16 targetChain, Wei maximumTotalBudget) external onlyOwnerOrPricingWallet {
|
|
setMaximumBudget(targetChain, maximumTotalBudget);
|
|
}
|
|
|
|
function updateMaximumBudgets(DeliveryProviderStructs.MaximumBudgetUpdate[] memory updates)
|
|
external
|
|
onlyOwnerOrPricingWallet
|
|
{
|
|
uint256 updatesLength = updates.length;
|
|
for (uint256 i = 0; i < updatesLength;) {
|
|
DeliveryProviderStructs.MaximumBudgetUpdate memory update = updates[i];
|
|
setMaximumBudget(update.chainId, update.maximumTotalBudget);
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateAssetConversionBuffer(
|
|
uint16 targetChain,
|
|
uint16 buffer,
|
|
uint16 bufferDenominator
|
|
) external onlyOwnerOrPricingWallet {
|
|
updateAssetConversionBufferImpl(targetChain, buffer, bufferDenominator);
|
|
}
|
|
|
|
function updateAssetConversionBuffers(
|
|
DeliveryProviderStructs.AssetConversionBufferUpdate[] memory updates
|
|
) external onlyOwnerOrPricingWallet {
|
|
uint256 updatesLength = updates.length;
|
|
for (uint256 i = 0; i < updatesLength;) {
|
|
DeliveryProviderStructs.AssetConversionBufferUpdate memory update = updates[i];
|
|
updateAssetConversionBufferImpl(update.chainId, update.buffer, update.bufferDenominator);
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
function updateAssetConversionBufferImpl(
|
|
uint16 targetChain,
|
|
uint16 buffer,
|
|
uint16 bufferDenominator
|
|
) internal {
|
|
setAssetConversionBuffer(targetChain, buffer, bufferDenominator);
|
|
emit AssetConversionBufferUpdated(targetChain, buffer, bufferDenominator);
|
|
}
|
|
|
|
function updateConfig(
|
|
DeliveryProviderStructs.Update[] memory updates,
|
|
DeliveryProviderStructs.CoreConfig memory coreConfig
|
|
) external onlyOwner {
|
|
uint256 updatesLength = updates.length;
|
|
for (uint256 i = 0; i < updatesLength;) {
|
|
DeliveryProviderStructs.Update memory update = updates[i];
|
|
if (update.updatePrice) {
|
|
updatePriceImpl(update.chainId, update.gasPrice, update.nativeCurrencyPrice);
|
|
}
|
|
if (update.updateTargetChainAddress) {
|
|
updateTargetChainAddressImpl(update.chainId, update.targetChainAddress);
|
|
}
|
|
if (update.updateDeliverGasOverhead) {
|
|
updateDeliverGasOverheadImpl(update.chainId, update.newGasOverhead);
|
|
}
|
|
if (update.updateMaximumBudget) {
|
|
setMaximumBudget(update.chainId, update.maximumTotalBudget);
|
|
}
|
|
if (update.updateAssetConversionBuffer) {
|
|
updateAssetConversionBufferImpl(
|
|
update.chainId, update.buffer, update.bufferDenominator
|
|
);
|
|
}
|
|
if (update.updateSupportedChain) {
|
|
updateSupportedChainImpl(update.chainId, update.isSupported);
|
|
}
|
|
unchecked {
|
|
i += 1;
|
|
}
|
|
}
|
|
|
|
if (coreConfig.updateWormholeRelayer) {
|
|
updateWormholeRelayerImpl(coreConfig.coreRelayer);
|
|
}
|
|
|
|
if (coreConfig.updateRewardAddress) {
|
|
updateRewardAddressImpl(coreConfig.rewardAddress);
|
|
}
|
|
if(coreConfig.updateSupportedKeyTypes) {
|
|
getSupportedMessageKeyTypes().bitmap = coreConfig.supportedKeyTypesBitmap;
|
|
}
|
|
}
|
|
|
|
/// @dev upgrade serves to upgrade contract implementations
|
|
function upgrade(uint16 deliveryProviderChainId, address newImplementation) public onlyOwner {
|
|
if (deliveryProviderChainId != chainId()) {
|
|
revert WrongChainId();
|
|
}
|
|
|
|
address currentImplementation = _getImplementation();
|
|
|
|
_upgradeTo(newImplementation);
|
|
|
|
// call initialize function of the new implementation
|
|
(bool success, bytes memory reason) =
|
|
newImplementation.delegatecall(abi.encodeWithSignature("initialize()"));
|
|
|
|
if (!success) {
|
|
revert FailedToInitializeImplementation(string(reason));
|
|
}
|
|
|
|
emit ContractUpgraded(currentImplementation, newImplementation);
|
|
}
|
|
|
|
/**
|
|
* @dev submitOwnershipTransferRequest serves to begin the ownership transfer process of the contracts
|
|
* - it saves an address for the new owner in the pending state
|
|
*/
|
|
function submitOwnershipTransferRequest(
|
|
uint16 thisRelayerChainId,
|
|
address newOwner
|
|
) external onlyOwner {
|
|
if (thisRelayerChainId != chainId()) {
|
|
revert WrongChainId();
|
|
}
|
|
if (newOwner == address(0)) {
|
|
revert AddressIsZero();
|
|
}
|
|
|
|
setPendingOwner(newOwner);
|
|
}
|
|
|
|
/**
|
|
* @dev confirmOwnershipTransferRequest serves to finalize an ownership transfer
|
|
* - it checks that the caller is the pendingOwner to validate the wallet address
|
|
* - it updates the owner state variable with the pendingOwner state variable
|
|
*/
|
|
function confirmOwnershipTransferRequest() external {
|
|
// cache the new owner address
|
|
address newOwner = pendingOwner();
|
|
|
|
if (msg.sender != newOwner) {
|
|
revert CallerMustBePendingOwner();
|
|
}
|
|
|
|
// cache currentOwner for Event
|
|
address currentOwner = owner();
|
|
|
|
// update the owner in the contract state and reset the pending owner
|
|
setOwner(newOwner);
|
|
setPendingOwner(address(0));
|
|
|
|
emit OwnershipTransfered(currentOwner, newOwner);
|
|
}
|
|
|
|
modifier onlyOwner() {
|
|
if (owner() != _msgSender()) {
|
|
revert CallerMustBeOwner();
|
|
}
|
|
_;
|
|
}
|
|
|
|
modifier onlyOwnerOrPricingWallet() {
|
|
if ((pricingWallet() != _msgSender()) && (owner() != _msgSender())) {
|
|
revert CallerMustBeOwnerOrPricingWallet();
|
|
}
|
|
_;
|
|
}
|
|
}
|