Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
MachineZap
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 200 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {IWatermarkFeeManager} from "@makina-periphery/interfaces/IWatermarkFeeManager.sol";
import {IHubPeripheryFactory} from "@makina-periphery/interfaces/IHubPeripheryFactory.sol";
import {IHubCoreFactory} from "@makina-core/interfaces/IHubCoreFactory.sol";
import {IMachine} from "@makina-core/interfaces/IMachine.sol";
import {ICaliber} from "@makina-core/interfaces/ICaliber.sol";
import {IMakinaGovernable} from "@makina-core/interfaces/IMakinaGovernable.sol";
import {OwnableRoles} from "@solady/auth/OwnableRoles.sol";
import {IMakinaGovernable} from "@makina-core/interfaces/IMakinaGovernable.sol";
import {IMachineZap} from "./interfaces/IMachineZap.sol";
contract MachineZap is IMachineZap, OwnableRoles {
IHubPeripheryFactory public hubPeripheryFactory;
IHubCoreFactory public hubCoreFactory;
uint256 public constant DEPLOYER_ROLE = _ROLE_1;
uint256 public constant CONFIG_ROLE = _ROLE_2;
constructor(address _hubPeripheryFactory, address _hubCoreFactory) {
hubPeripheryFactory = IHubPeripheryFactory(_hubPeripheryFactory);
hubCoreFactory = IHubCoreFactory(_hubCoreFactory);
_initializeOwner(msg.sender);
}
function createMachine(
string calldata shareTokenName,
string calldata shareTokenSymbol,
address accountingToken,
address[] calldata baseTokens,
bytes32 salt,
uint16 depositorImplemId,
bool depositorWhitelistStatus,
uint16 redeemerImplemId,
bool redeemerWhitelistStatus,
uint256 redeemerFinalizationDelay,
uint256 redeemerMinRedeemAmount,
uint16 feeManagerImplemId,
IWatermarkFeeManager.WatermarkFeeManagerInitParams calldata feeManagerInitParams,
MachineInitParams calldata machineInitParams,
ICaliber.CaliberInitParams calldata caliberInitParams,
IMakinaGovernable.MakinaGovernableInitParams memory mgInitParams
) public onlyRolesOrOwner(DEPLOYER_ROLE) returns (address machine) {
address depositor = hubPeripheryFactory.createDepositor(depositorImplemId, abi.encode(depositorWhitelistStatus));
address redeemer = hubPeripheryFactory.createRedeemer(
redeemerImplemId, abi.encode(redeemerFinalizationDelay, redeemerMinRedeemAmount, redeemerWhitelistStatus)
);
address feeManager = hubPeripheryFactory.createFeeManager(feeManagerImplemId, abi.encode(feeManagerInitParams));
address finalRiskManager = mgInitParams.initialRiskManager;
address finalRiskManagerTimelock = mgInitParams.initialRiskManagerTimelock;
mgInitParams.initialRiskManager = address(this);
mgInitParams.initialRiskManagerTimelock = address(this);
machine = hubCoreFactory.createMachine(
IMachine.MachineInitParams({
initialDepositor: depositor,
initialRedeemer: redeemer,
initialFeeManager: feeManager,
initialCaliberStaleThreshold: machineInitParams.initialCaliberStaleThreshold,
initialMaxFixedFeeAccrualRate: machineInitParams.initialMaxFixedFeeAccrualRate,
initialMaxPerfFeeAccrualRate: machineInitParams.initialMaxPerfFeeAccrualRate,
initialFeeMintCooldown: machineInitParams.initialFeeMintCooldown,
initialShareLimit: machineInitParams.initialShareLimit
}),
caliberInitParams,
mgInitParams,
accountingToken,
shareTokenName,
shareTokenSymbol,
salt
);
ICaliber caliber = ICaliber(IMachine(machine).hubCaliber());
for (uint256 i = 0; i < baseTokens.length; i++) {
caliber.addBaseToken(baseTokens[i]);
}
IMachine(machine).setRiskManager(finalRiskManager);
IMachine(machine).setRiskManagerTimelock(finalRiskManagerTimelock);
}
function setHubPeripheryFactory(address _hubPeripheryFactory) public onlyRolesOrOwner(CONFIG_ROLE) {
hubPeripheryFactory = IHubPeripheryFactory(_hubPeripheryFactory);
}
function setHubCoreFactory(address _hubCoreFactory) public onlyRolesOrOwner(CONFIG_ROLE) {
hubCoreFactory = IHubCoreFactory(_hubCoreFactory);
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IFeeManager} from "@makina-core/interfaces/IFeeManager.sol";
import {IMachinePeriphery} from "./IMachinePeriphery.sol";
import {ISecurityModuleReference} from "./ISecurityModuleReference.sol";
interface IWatermarkFeeManager is IFeeManager, ISecurityModuleReference, IMachinePeriphery {
event MgmtFeeSplitChanged();
event MgmtFeeRatePerSecondChanged(uint256 oldRate, uint256 newRate);
event PerfFeeRateChanged(uint256 oldRate, uint256 newRate);
event PerfFeeSplitChanged();
event SmFeeRatePerSecondChanged(uint256 oldRate, uint256 newRate);
event SecurityModuleSet(address indexed securityModule);
event WatermarkReset(uint256 indexed newWatermark);
/// @notice Initialization parameters.
/// @param initialMgmtFeeRatePerSecond Management fee rate per second, in 18 decimals precision.
/// @param initialSmFeeRatePerSecond Security module fee rate per second, in 18 decimals precision.
/// @param initialPerfFeeRate Performance fee rate on profit, in 18 decimals precision.
/// @param initialMgmtFeeSplitBps Fixed fee split between receivers in basis points. Values must sum to 10_000.
/// @param initialMgmtFeeReceivers Fixed fee receivers.
/// @param initialPerfFeeSplitBps Performance fee split between receivers in basis points. Values must sum to 10_000.
/// @param initialPerfFeeReceivers Performance fee receivers.
struct WatermarkFeeManagerInitParams {
uint256 initialMgmtFeeRatePerSecond;
uint256 initialSmFeeRatePerSecond;
uint256 initialPerfFeeRate;
uint256[] initialMgmtFeeSplitBps;
address[] initialMgmtFeeReceivers;
uint256[] initialPerfFeeSplitBps;
address[] initialPerfFeeReceivers;
}
/// @notice Management fee rate per second, 1e18 = 100%.
function mgmtFeeRatePerSecond() external view returns (uint256);
/// @notice Security module fee rate per second, 1e18 = 100%.
function smFeeRatePerSecond() external view returns (uint256);
/// @notice Performance fee rate on profit, 1e18 = 100%.
function perfFeeRate() external view returns (uint256);
/// @notice Fixed fee receivers.
function mgmtFeeReceivers() external view returns (address[] memory);
/// @notice Fixed fee split between receivers in basis points. Values must sum to 10_000.
function mgmtFeeSplitBps() external view returns (uint256[] memory);
/// @notice Performance fee receivers.
function perfFeeReceivers() external view returns (address[] memory);
/// @notice Performance fee split between receivers in basis points. Values must sum to 10_000.
function perfFeeSplitBps() external view returns (uint256[] memory);
/// @notice Current share price high watermark for the associated Machine.
function sharePriceWatermark() external view returns (uint256);
/// @notice Resets the share price high watermark.
function resetSharePriceWatermark(uint256 sharePrice) external;
/// @notice Sets the management fee rate per second.
/// @param newMgmtFeeRatePerSecond The new management fee rate per second. 1e18 = 100%.
function setMgmtFeeRatePerSecond(uint256 newMgmtFeeRatePerSecond) external;
/// @notice Sets the security module fee rate per second.
/// @param newSmFeeRatePerSecond The new security module fee rate per second. 1e18 = 100%.
function setSmFeeRatePerSecond(uint256 newSmFeeRatePerSecond) external;
/// @notice Sets the performance fee rate.
/// @param newPerfFeeRate The new performance fee rate on profit. 1e18 = 100%.
function setPerfFeeRate(uint256 newPerfFeeRate) external;
/// @notice Sets the fixed fee split and receivers.
/// @param newMgmtFeeReceivers The new fixed fee receivers.
/// @param newMgmtFeeSplitBps The new fixed fee split between receivers in basis points. Values must sum to 10_000.
function setMgmtFeeSplit(address[] calldata newMgmtFeeReceivers, uint256[] calldata newMgmtFeeSplitBps) external;
/// @notice Sets the performance fee split and receivers.
/// @param newPerfFeeReceivers The new performance fee receivers.
/// @param newPerfFeeSplitBps The new performance fee split between receivers in basis points. Values must sum to 10_000.
function setPerfFeeSplit(address[] calldata newPerfFeeReceivers, uint256[] calldata newPerfFeeSplitBps) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {ISecurityModule} from "../interfaces/ISecurityModule.sol";
interface IHubPeripheryFactory {
event DepositorCreated(address indexed depositor, uint16 indexed implemId);
event RedeemerCreated(address indexed redeemer, uint16 indexed implemId);
event FeeManagerCreated(address indexed feeManager, uint16 indexed implemId);
event SecurityModuleCreated(address indexed securityModule);
/// @notice Address => Whether this is a depositor deployed by this factory
function isDepositor(address depositor) external view returns (bool);
/// @notice Address => Whether this is a redeemer deployed by this factory
function isRedeemer(address redeemer) external view returns (bool);
/// @notice Address => Whether this is a fee manager deployed by this factory
function isFeeManager(address feeManager) external view returns (bool);
/// @notice Address => Whether this is a security module deployed by this factory
function isSecurityModule(address securityModule) external view returns (bool);
/// @notice Depositor => Implementation ID
function depositorImplemId(address depositor) external view returns (uint16);
/// @notice Redeemer => Implementation ID
function redeemerImplemId(address redeemer) external view returns (uint16);
/// @notice Fee manager => Implementation ID
function feeManagerImplemId(address feeManager) external view returns (uint16);
/// @notice Sets the machine address in the machine periphery contract.
/// @param machinePeriphery The address of the machine periphery contract.
/// @param machine The address of the machine to be set.
function setMachine(address machinePeriphery, address machine) external;
/// @notice Sets the security module address in the fee manager contract.
/// @param feeManager The address of the fee manager contract.
/// @param securityModule The address of the security module to be set.
function setSecurityModule(address feeManager, address securityModule) external;
/// @notice Creates a new machine depositor using the specified implementation ID.
/// @param implemId The ID of the depositor implementation to be used.
/// @param initializationData Additional initialization data.
/// @return depositor The address of the newly created depositor.
function createDepositor(uint16 implemId, bytes calldata initializationData) external returns (address depositor);
/// @notice Creates a new machine redeemer using the specified implementation ID.
/// @param implemId The ID of the redeemer implementation to be used.
/// @param initializationData Additional initialization data.
/// @return redeemer The address of the newly created redeemer.
function createRedeemer(uint16 implemId, bytes calldata initializationData) external returns (address redeemer);
/// @notice Creates a new machine fee manager using the specified implementation ID.
/// @param implemId The ID of the fee manager implementation to be used.
/// @param initializationData Additional initialization data.
/// @return feeManager The address of the newly created fee manager.
function createFeeManager(uint16 implemId, bytes calldata initializationData)
external
returns (address feeManager);
/// @notice Creates a new security module.
/// @param smParams The security module initialization parameters.
/// @return securityModule The address of the newly created security module.
function createSecurityModule(ISecurityModule.SecurityModuleInitParams calldata smParams)
external
returns (address securityModule);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {ICaliber} from "./ICaliber.sol";
import {IMachine} from "./IMachine.sol";
import {IPreDepositVault} from "./IPreDepositVault.sol";
import {IMakinaGovernable} from "./IMakinaGovernable.sol";
import {IBridgeAdapterFactory} from "./IBridgeAdapterFactory.sol";
interface IHubCoreFactory is IBridgeAdapterFactory {
event MachineCreated(address indexed machine, address indexed shareToken);
event PreDepositVaultCreated(address indexed preDepositVault, address indexed shareToken);
event ShareTokenCreated(address indexed shareToken);
/// @notice Address => Whether this is a PreDepositVault instance deployed by this factory.
function isPreDepositVault(address preDepositVault) external view returns (bool);
/// @notice Address => Whether this is a Machine instance deployed by this factory.
function isMachine(address machine) external view returns (bool);
/// @notice Deploys a new PreDepositVault instance.
/// @param params The initialization parameters.
/// @param depositToken The address of the deposit token.
/// @param accountingToken The address of the accounting token.
/// @param tokenName The name of the share token.
/// @param tokenSymbol The symbol of the share token.
/// @return preDepositVault The address of the deployed PreDepositVault instance.
function createPreDepositVault(
IPreDepositVault.PreDepositVaultInitParams calldata params,
address depositToken,
address accountingToken,
string memory tokenName,
string memory tokenSymbol
) external returns (address preDepositVault);
/// @notice Deploys a new Machine instance and migrates an existing PreDepositVault instance to it.
/// @param mParams The machine initialization parameters.
/// @param cParams The caliber initialization parameters.
/// @param mgParams The makina governable initialization parameters.
/// @param preDepositVault The address of the PreDepositVault instance to migrate.
/// @param salt The salt used to deploy the Hub Caliber deterministically.
/// @return machine The address of the deployed Machine instance.
function createMachineFromPreDeposit(
IMachine.MachineInitParams calldata mParams,
ICaliber.CaliberInitParams calldata cParams,
IMakinaGovernable.MakinaGovernableInitParams calldata mgParams,
address preDepositVault,
bytes32 salt
) external returns (address machine);
/// @notice Deploys a new Machine instance.
/// @param mParams The machine initialization parameters.
/// @param cParams The caliber initialization parameters.
/// @param mgParams The makina governable initialization parameters.
/// @param accountingToken The address of the accounting token.
/// @param tokenName The name of the share token.
/// @param tokenSymbol The symbol of the share token.
/// @param salt The salt used to deploy the Hub Caliber deterministically.
/// @return machine The address of the deployed Machine instance.
function createMachine(
IMachine.MachineInitParams calldata mParams,
ICaliber.CaliberInitParams calldata cParams,
IMakinaGovernable.MakinaGovernableInitParams calldata mgParams,
address accountingToken,
string memory tokenName,
string memory tokenSymbol,
bytes32 salt
) external returns (address machine);
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {EnumerableMap} from "@openzeppelin/contracts/utils/structs/EnumerableMap.sol";
import {GuardianSignature} from "@wormhole/sdk/libraries/VaaLib.sol";
import {IMachineEndpoint} from "./IMachineEndpoint.sol";
interface IMachine is IMachineEndpoint {
event CaliberStaleThresholdChanged(uint256 indexed oldThreshold, uint256 indexed newThreshold);
event Deposit(address indexed sender, address indexed receiver, uint256 assets, uint256 shares);
event DepositorChanged(address indexed oldDepositor, address indexed newDepositor);
event FeeManagerChanged(address indexed oldFeeManager, address indexed newFeeManager);
event FeeMintCooldownChanged(uint256 indexed oldFeeMintCooldown, uint256 indexed newFeeMintCooldown);
event FeesMinted(uint256 shares);
event MaxFixedFeeAccrualRateChanged(uint256 indexed oldMaxAccrualRate, uint256 indexed newMaxAccrualRate);
event MaxPerfFeeAccrualRateChanged(uint256 indexed oldMaxAccrualRate, uint256 indexed newMaxAccrualRate);
event Redeem(address indexed owner, address indexed receiver, uint256 assets, uint256 shares);
event RedeemerChanged(address indexed oldRedeemer, address indexed newRedeemer);
event ShareLimitChanged(uint256 indexed oldShareLimit, uint256 indexed newShareLimit);
event SpokeBridgeAdapterSet(uint256 indexed chainId, uint256 indexed bridgeId, address indexed adapter);
event SpokeCaliberMailboxSet(uint256 indexed chainId, address indexed caliberMailbox);
event TotalAumUpdated(uint256 totalAum);
event TransferToCaliber(uint256 indexed chainId, address indexed token, uint256 amount);
/// @notice Initialization parameters.
/// @param initialDepositor The address of the initial depositor.
/// @param initialRedeemer The address of the initial redeemer.
/// @param initialFeeManager The address of the initial fee manager.
/// @param initialCaliberStaleThreshold The caliber accounting staleness threshold in seconds.
/// @param initialMaxFixedFeeAccrualRate The maximum fixed fee accrual rate per second, 1e18 = 100%.
/// @param initialMaxPerfFeeAccrualRate The maximum performance fee accrual rate per second, 1e18 = 100%.
/// @param initialFeeMintCooldown The minimum time to be elapsed between two fee minting events in seconds.
/// @param initialShareLimit The share cap value.
struct MachineInitParams {
address initialDepositor;
address initialRedeemer;
address initialFeeManager;
uint256 initialCaliberStaleThreshold;
uint256 initialMaxFixedFeeAccrualRate;
uint256 initialMaxPerfFeeAccrualRate;
uint256 initialFeeMintCooldown;
uint256 initialShareLimit;
}
/// @dev Internal state structure for a spoke caliber data.
/// @param mailbox The foreign address of the spoke caliber mailbox.
/// @param bridgeAdapters The mapping of bridge IDs to their corresponding adapters.
/// @param timestamp The timestamp of the last accounting.
/// @param netAum The net AUM of the spoke caliber.
/// @param positions The list of positions of the spoke caliber, each encoded as abi.encode(positionId, value).
/// @param baseTokens The list of base tokens of the spoke caliber, each encoded as abi.encode(token, value).
/// @param caliberBridgesIn The mapping of spoke caliber incoming bridge amounts.
/// @param caliberBridgesOut The mapping of spoke caliber outgoing bridge amounts.
/// @param machineBridgesIn The mapping of machine incoming bridge amounts.
/// @param machineBridgesOut The mapping of machine outgoing bridge amounts.
struct SpokeCaliberData {
address mailbox;
mapping(uint16 bridgeId => address adapter) bridgeAdapters;
uint256 timestamp;
uint256 netAum;
bytes[] positions;
bytes[] baseTokens;
EnumerableMap.AddressToUintMap caliberBridgesIn;
EnumerableMap.AddressToUintMap caliberBridgesOut;
EnumerableMap.AddressToUintMap machineBridgesIn;
EnumerableMap.AddressToUintMap machineBridgesOut;
}
/// @notice Initializer of the contract.
/// @param mParams The machine initialization parameters.
/// @param mgParams The makina governable initialization parameters.
/// @param _preDepositVault The address of the pre-deposit vault.
/// @param _shareToken The address of the share token.
/// @param _accountingToken The address of the accounting token.
/// @param _hubCaliber The address of the hub caliber.
function initialize(
MachineInitParams calldata mParams,
MakinaGovernableInitParams calldata mgParams,
address _preDepositVault,
address _shareToken,
address _accountingToken,
address _hubCaliber
) external;
/// @notice Address of the Wormhole Core Bridge.
function wormhole() external view returns (address);
/// @notice Address of the depositor.
function depositor() external view returns (address);
/// @notice Address of the redeemer.
function redeemer() external view returns (address);
/// @notice Address of the share token.
function shareToken() external view returns (address);
/// @notice Address of the accounting token.
function accountingToken() external view returns (address);
/// @notice Address of the hub caliber.
function hubCaliber() external view returns (address);
/// @notice Address of the fee manager.
function feeManager() external view returns (address);
/// @notice Maximum duration a caliber can remain unaccounted for before it is considered stale.
function caliberStaleThreshold() external view returns (uint256);
/// @notice Maximum fixed fee accrual rate per second used to compute an upper bound on shares to be minted, 1e18 = 100%.
function maxFixedFeeAccrualRate() external view returns (uint256);
/// @notice Maximum performance fee accrual rate per second used to compute an upper bound on shares to be minted, 1e18 = 100%.
function maxPerfFeeAccrualRate() external view returns (uint256);
/// @notice Minimum time to be elapsed between two fee minting events.
function feeMintCooldown() external view returns (uint256);
/// @notice Share token supply limit that cannot be exceeded by new deposits.
function shareLimit() external view returns (uint256);
/// @notice Maximum amount of shares that can currently be minted through asset deposits.
function maxMint() external view returns (uint256);
/// @notice Maximum amount of accounting tokens that can currently be withdrawn through share redemptions.
function maxWithdraw() external view returns (uint256);
/// @notice Last total machine AUM.
function lastTotalAum() external view returns (uint256);
/// @notice Timestamp of the last global machine accounting.
function lastGlobalAccountingTime() external view returns (uint256);
/// @notice Token => Is the token an idle token.
function isIdleToken(address token) external view returns (bool);
/// @notice Number of calibers associated with the machine.
function getSpokeCalibersLength() external view returns (uint256);
/// @notice Spoke caliber index => Spoke Chain ID.
function getSpokeChainId(uint256 idx) external view returns (uint256);
/// @notice Spoke Chain ID => Spoke caliber's AUM, individual positions values and accounting timestamp.
function getSpokeCaliberDetailedAum(uint256 chainId)
external
view
returns (uint256 aum, bytes[] memory positions, bytes[] memory baseTokens, uint256 timestamp);
/// @notice Spoke Chain ID => Spoke Caliber Mailbox Address.
function getSpokeCaliberMailbox(uint256 chainId) external view returns (address);
/// @notice Spoke Chain ID => Spoke Bridge ID => Spoke Bridge Adapter.
function getSpokeBridgeAdapter(uint256 chainId, uint16 bridgeId) external view returns (address);
/// @notice Returns the amount of shares that the Machine would exchange for the amount of accounting tokens provided.
/// @param assets The amount of accounting tokens.
/// @return shares The amount of shares.
function convertToShares(uint256 assets) external view returns (uint256);
/// @notice Returns the amount of accounting tokens that the Machine would exchange for the amount of shares provided.
/// @param shares The amount of shares.
/// @return assets The amount of accounting tokens.
function convertToAssets(uint256 shares) external view returns (uint256);
/// @notice Initiates a token transfers to the hub caliber.
/// @param token The address of the token to transfer.
/// @param amount The amount of token to transfer.
function transferToHubCaliber(address token, uint256 amount) external;
/// @notice Initiates a token transfers to the spoke caliber.
/// @param bridgeId The ID of the bridge to use for the transfer.
/// @param chainId The foreign EVM chain ID of the spoke caliber.
/// @param token The address of the token to transfer.
/// @param amount The amount of token to transfer.
/// @param minOutputAmount The minimum output amount expected from the transfer.
function transferToSpokeCaliber(
uint16 bridgeId,
uint256 chainId,
address token,
uint256 amount,
uint256 minOutputAmount
) external;
/// @notice Updates the total AUM of the machine.
/// @return totalAum The updated total AUM.
function updateTotalAum() external returns (uint256);
/// @notice Deposits accounting tokens into the machine and mints shares to the receiver.
/// @param assets The amount of accounting tokens to deposit.
/// @param receiver The receiver of minted shares.
/// @param minShares The minimum amount of shares to be minted.
/// @return shares The amount of shares minted.
function deposit(uint256 assets, address receiver, uint256 minShares) external returns (uint256);
/// @notice Redeems shares from the machine and transfers accounting tokens to the receiver.
/// @param shares The amount of shares to redeem.
/// @param receiver The receiver of the accounting tokens.
/// @param minAssets The minimum amount of accounting tokens to be transferred.
/// @return assets The amount of accounting tokens transferred.
function redeem(uint256 shares, address receiver, uint256 minAssets) external returns (uint256);
/// @notice Updates spoke caliber accounting data using Wormhole Cross-Chain Queries (CCQ).
/// @dev Validates the Wormhole CCQ response and guardian signatures before updating state.
/// @param response The Wormhole CCQ response payload containing the accounting data.
/// @param signatures The array of Wormhole guardians signatures attesting to the validity of the response.
function updateSpokeCaliberAccountingData(bytes memory response, GuardianSignature[] memory signatures) external;
/// @notice Registers a spoke caliber mailbox and related bridge adapters.
/// @param chainId The foreign EVM chain ID of the spoke caliber.
/// @param spokeCaliberMailbox The address of the spoke caliber mailbox.
/// @param bridges The list of bridges supported with the spoke caliber.
/// @param adapters The list of corresponding adapters for each bridge. Must be the same length as `bridges`.
function setSpokeCaliber(
uint256 chainId,
address spokeCaliberMailbox,
uint16[] calldata bridges,
address[] calldata adapters
) external;
/// @notice Registers a spoke bridge adapter.
/// @param chainId The foreign EVM chain ID of the adapter.
/// @param bridgeId The ID of the bridge.
/// @param adapter The foreign address of the bridge adapter.
function setSpokeBridgeAdapter(uint256 chainId, uint16 bridgeId, address adapter) external;
/// @notice Sets the depositor address.
/// @param newDepositor The address of the new depositor.
function setDepositor(address newDepositor) external;
/// @notice Sets the redeemer address.
/// @param newRedeemer The address of the new redeemer.
function setRedeemer(address newRedeemer) external;
/// @notice Sets the fee manager address.
/// @param newFeeManager The address of the new fee manager.
function setFeeManager(address newFeeManager) external;
/// @notice Sets the caliber accounting staleness threshold.
/// @param newCaliberStaleThreshold The new threshold in seconds.
function setCaliberStaleThreshold(uint256 newCaliberStaleThreshold) external;
/// @notice Sets the maximum fixed fee accrual rate.
/// @param newMaxAccrualRate The new maximum fixed fee accrual rate per second, 1e18 = 100%.
function setMaxFixedFeeAccrualRate(uint256 newMaxAccrualRate) external;
/// @notice Sets the maximum performance fee accrual rate.
/// @param newMaxAccrualRate The new maximum performance fee accrual rate per second, 1e18 = 100%.
function setMaxPerfFeeAccrualRate(uint256 newMaxAccrualRate) external;
/// @notice Sets the minimum time to be elapsed between two fee minting events.
/// @param newFeeMintCooldown The new cooldown in seconds.
function setFeeMintCooldown(uint256 newFeeMintCooldown) external;
/// @notice Sets the new share token supply limit that cannot be exceeded by new deposits.
/// @param newShareLimit The new share limit
function setShareLimit(uint256 newShareLimit) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {ISwapModule} from "./ISwapModule.sol";
interface ICaliber {
event BaseTokenAdded(address indexed token);
event BaseTokenRemoved(address indexed token);
event CooldownDurationChanged(uint256 indexed oldDuration, uint256 indexed newDuration);
event IncomingTransfer(address indexed token, uint256 amount);
event InstrRootGuardianAdded(address indexed newGuardian);
event InstrRootGuardianRemoved(address indexed guardian);
event MaxPositionDecreaseLossBpsChanged(
uint256 indexed oldMaxPositionDecreaseLossBps, uint256 indexed newMaxPositionDecreaseLossBps
);
event MaxPositionIncreaseLossBpsChanged(
uint256 indexed oldMaxPositionIncreaseLossBps, uint256 indexed newMaxPositionIncreaseLossBps
);
event MaxSwapLossBpsChanged(uint256 indexed oldMaxSwapLossBps, uint256 indexed newMaxSwapLossBps);
event NewAllowedInstrRootCancelled(bytes32 indexed cancelledMerkleRoot);
event NewAllowedInstrRootScheduled(bytes32 indexed newMerkleRoot, uint256 indexed effectiveTime);
event PositionClosed(uint256 indexed id);
event PositionCreated(uint256 indexed id, uint256 value);
event PositionUpdated(uint256 indexed id, uint256 value);
event PositionStaleThresholdChanged(uint256 indexed oldThreshold, uint256 indexed newThreshold);
event TimelockDurationChanged(uint256 indexed oldDuration, uint256 indexed newDuration);
event TransferToHubMachine(address indexed token, uint256 amount);
enum InstructionType {
MANAGEMENT,
ACCOUNTING,
HARVEST,
FLASHLOAN_MANAGEMENT
}
/// @notice Initialization parameters.
/// @param initialPositionStaleThreshold The position accounting staleness threshold in seconds.
/// @param initialAllowedInstrRoot The root of the Merkle tree containing allowed instructions.
/// @param initialTimelockDuration The duration of the allowedInstrRoot update timelock.
/// @param initialMaxPositionIncreaseLossBps The max allowed value loss (in basis point) for position increases.
/// @param initialMaxPositionDecreaseLossBps The max allowed value loss (in basis point) for position decreases.
/// @param initialMaxSwapLossBps The max allowed value loss (in basis point) for base token swaps.
/// @param initialCooldownDuration The duration of the cooldown period for swaps and position management.
struct CaliberInitParams {
uint256 initialPositionStaleThreshold;
bytes32 initialAllowedInstrRoot;
uint256 initialTimelockDuration;
uint256 initialMaxPositionIncreaseLossBps;
uint256 initialMaxPositionDecreaseLossBps;
uint256 initialMaxSwapLossBps;
uint256 initialCooldownDuration;
}
/// @notice Instruction parameters.
/// @param positionId The ID of the involved position.
/// @param isDebt Whether the position is a debt.
/// @param groupId The ID of the position accounting group.
/// Set to 0 if the instruction is not of type ACCOUNTING, or if the involved position is ungrouped.
/// @param instructionType The type of the instruction.
/// @param affectedTokens The array of affected tokens.
/// @param commands The array of commands.
/// @param state The array of state.
/// @param stateBitmap The state bitmap.
/// @param merkleProof The array of Merkle proof elements.
struct Instruction {
uint256 positionId;
bool isDebt;
uint256 groupId;
InstructionType instructionType;
address[] affectedTokens;
bytes32[] commands;
bytes[] state;
uint128 stateBitmap;
bytes32[] merkleProof;
}
/// @notice Position data.
/// @param lastAccountingTime The last block timestamp when the position was accounted for.
/// @param value The value of the position expressed in accounting token.
/// @param isDebt Whether the position is a debt.
struct Position {
uint256 lastAccountingTime;
uint256 value;
bool isDebt;
}
/// @notice Initializer of the contract.
/// @param cParams The caliber initialization parameters.
/// @param _accountingToken The address of the accounting token.
/// @param _hubMachineEndpoint The address of the hub machine endpoints.
function initialize(CaliberInitParams calldata cParams, address _accountingToken, address _hubMachineEndpoint)
external;
/// @notice Address of the Weiroll VM.
function weirollVm() external view returns (address);
/// @notice Address of the hub machine endpoint.
function hubMachineEndpoint() external view returns (address);
/// @notice Address of the accounting token.
function accountingToken() external view returns (address);
/// @notice Maximum duration a position can remain unaccounted for before it is considered stale.
function positionStaleThreshold() external view returns (uint256);
/// @notice Root of the Merkle tree containing allowed instructions.
function allowedInstrRoot() external view returns (bytes32);
/// @notice Duration of the allowedInstrRoot update timelock.
function timelockDuration() external view returns (uint256);
/// @notice Value of the pending allowedInstrRoot, if any.
function pendingAllowedInstrRoot() external view returns (bytes32);
/// @notice Effective time of the last scheduled allowedInstrRoot update.
function pendingTimelockExpiry() external view returns (uint256);
/// @notice Max allowed value loss (in basis point) when increasing a position.
function maxPositionIncreaseLossBps() external view returns (uint256);
/// @notice Max allowed value loss (in basis point) when decreasing a position.
function maxPositionDecreaseLossBps() external view returns (uint256);
/// @notice Max allowed value loss (in basis point) for base token swaps.
function maxSwapLossBps() external view returns (uint256);
/// @notice Duration of the cooldown period for swaps and position management.
function cooldownDuration() external view returns (uint256);
/// @notice Length of the position IDs list.
function getPositionsLength() external view returns (uint256);
/// @notice Position index => Position ID
/// @dev There are no guarantees on the ordering of values inside the Position ID list,
/// and it may change when values are added or removed.
function getPositionId(uint256 idx) external view returns (uint256);
/// @notice Position ID => Position data
function getPosition(uint256 id) external view returns (Position memory);
/// @notice Token => Registered as base token in this caliber
function isBaseToken(address token) external view returns (bool);
/// @notice Length of the base tokens list.
function getBaseTokensLength() external view returns (uint256);
/// @notice Base token index => Base token address
/// @dev There are no guarantees on the ordering of values inside the base tokens list,
/// and it may change when values are added or removed.
function getBaseToken(uint256 idx) external view returns (address);
/// @notice User => Whether the user is a root guardian
/// Guardians have veto power over updates of the Merkle root.
function isInstrRootGuardian(address user) external view returns (bool);
/// @notice Checks if the accounting age of each position is below the position staleness threshold.
function isAccountingFresh() external view returns (bool);
/// @notice Returns the caliber's net AUM along with detailed position and base token breakdowns.
/// @return netAum The total value of all base token balances and positive positions, minus total debts.
/// @return positions The array of encoded tuples of the form (positionId, value, isDebt).
/// @return baseTokens The array of encoded tuples of the form (token, value).
function getDetailedAum()
external
view
returns (uint256 netAum, bytes[] memory positions, bytes[] memory baseTokens);
/// @notice Adds a new base token.
/// @param token The address of the base token.
function addBaseToken(address token) external;
/// @notice Removes a base token.
/// @param token The address of the base token.
function removeBaseToken(address token) external;
/// @notice Accounts for a position.
/// @dev If the position value goes to zero, it is closed.
/// @param instruction The accounting instruction.
/// @return value The new position value.
/// @return change The change in the position value.
function accountForPosition(Instruction calldata instruction) external returns (uint256 value, int256 change);
/// @notice Accounts for a batch of positions.
/// @param instructions The array of accounting instructions.
/// @param groupIds The array of position group IDs.
/// An accounting instruction must be provided for every open position in each specified group.
/// If an instruction's groupId corresponds to a group of open positions of size greater than 1,
/// the group ID must be included in this array.
/// @return values The new position values.
/// @return changes The changes in the position values.
function accountForPositionBatch(Instruction[] calldata instructions, uint256[] calldata groupIds)
external
returns (uint256[] memory values, int256[] memory changes);
/// @notice Manages a position's state through paired management and accounting instructions
/// @dev Performs accounting updates and modifies contract storage by:
/// - Adding new positions to storage when created.
/// - Removing positions from storage when value reaches zero.
/// @dev Applies value preservation checks using a validation matrix to prevent
/// economic inconsistencies between position changes and token flows.
///
/// The matrix evaluates three factors to determine required validations:
/// - Base Token Inflow - Whether the contract's base token balance increases during operation
/// - Debt Position - Whether position represents protocol liability (true) vs asset (false)
/// - Position Δ direction - Direction of position value change (increase/decrease)
///
/// ┌───────────────────┬───────────────┬──────────────────────┬───────────────────────────┐
/// │ Base Token Inflow │ Debt Position │ Position Δ direction │ Action │
/// ├───────────────────┼───────────────┼──────────────────────┼───────────────────────────┤
/// │ No │ No │ Decrease │ Revert: Invalid direction │
/// │ No │ Yes │ Increase │ Revert: Invalid direction │
/// │ No │ No │ Increase │ Minimum Δ Check │
/// │ No │ Yes │ Decrease │ Minimum Δ Check │
/// │ Yes │ No │ Decrease │ Maximum Δ Check │
/// │ Yes │ Yes │ Increase │ Maximum Δ Check │
/// │ Yes │ No │ Increase │ No check (favorable move) │
/// │ Yes │ Yes │ Decrease │ No check (favorable move) │
/// └───────────────────┴───────────────┴──────────────────────┴───────────────────────────┘
/// @param mgmtInstruction The management instruction.
/// @param acctInstruction The accounting instruction.
/// @return value The new position value.
/// @return change The signed position value delta.
function managePosition(Instruction calldata mgmtInstruction, Instruction calldata acctInstruction)
external
returns (uint256 value, int256 change);
/// @notice Manages a batch of positions.
/// @dev Convenience function to manage multiple positions in a single transaction.
/// @param mgmtInstructions The array of management instructions.
/// @param acctInstructions The array of accounting instructions.
/// @return values The new position values.
/// @return changes The changes in the position values.
function managePositionBatch(Instruction[] calldata mgmtInstructions, Instruction[] calldata acctInstructions)
external
returns (uint256[] memory values, int256[] memory changes);
/// @notice Manages flashLoan funds.
/// @param instruction The flashLoan management instruction.
/// @param token The loan token.
/// @param amount The loan amount.
function manageFlashLoan(Instruction calldata instruction, address token, uint256 amount) external;
/// @notice Harvests one or multiple positions.
/// @param instruction The harvest instruction.
/// @param swapOrders The array of swap orders to be executed after the harvest.
function harvest(Instruction calldata instruction, ISwapModule.SwapOrder[] calldata swapOrders) external;
/// @notice Performs a swap via the swapModule module.
/// @param order The swap order parameters.
function swap(ISwapModule.SwapOrder calldata order) external;
/// @notice Initiates a token transfer to the hub machine.
/// @param token The address of the token to transfer.
/// @param amount The amount of tokens to transfer.
/// @param data ABI-encoded parameters required for bridge-related transfers. Ignored when called from a hub caliber.
function transferToHubMachine(address token, uint256 amount, bytes calldata data) external;
/// @notice Instructs the Caliber to pull the specified token amount from the calling hub machine endpoint.
/// @param token The address of the token being transferred.
/// @param amount The amount of tokens being transferred.
function notifyIncomingTransfer(address token, uint256 amount) external;
/// @notice Sets the position accounting staleness threshold.
/// @param newPositionStaleThreshold The new threshold in seconds.
function setPositionStaleThreshold(uint256 newPositionStaleThreshold) external;
/// @notice Sets the duration of the allowedInstrRoot update timelock.
/// @param newTimelockDuration The new duration in seconds.
function setTimelockDuration(uint256 newTimelockDuration) external;
/// @notice Schedules an update of the root of the Merkle tree containing allowed instructions.
/// @dev The update will take effect after the timelock duration stored in the contract
/// at the time of the call.
/// @param newMerkleRoot The new Merkle root.
function scheduleAllowedInstrRootUpdate(bytes32 newMerkleRoot) external;
/// @notice Cancels a scheduled update of the root of the Merkle tree containing allowed instructions.
/// @dev Reverts if no pending update exists or if the timelock has expired.
function cancelAllowedInstrRootUpdate() external;
/// @notice Sets the max allowed value loss for position increases.
/// @param newMaxPositionIncreaseLossBps The new max value loss in basis points.
function setMaxPositionIncreaseLossBps(uint256 newMaxPositionIncreaseLossBps) external;
/// @notice Sets the max allowed value loss for position decreases.
/// @param newMaxPositionDecreaseLossBps The new max value loss in basis points.
function setMaxPositionDecreaseLossBps(uint256 newMaxPositionDecreaseLossBps) external;
/// @notice Sets the max allowed value loss for base token swaps.
/// @param newMaxSwapLossBps The new max value loss in basis points.
function setMaxSwapLossBps(uint256 newMaxSwapLossBps) external;
/// @notice Sets the duration of the cooldown period for swaps and position management.
/// @param newCooldownDuration The new duration in seconds.
function setCooldownDuration(uint256 newCooldownDuration) external;
/// @notice Adds a new guardian for the Merkle tree containing allowed instructions.
/// @param newGuardian The address of the new guardian.
function addInstrRootGuardian(address newGuardian) external;
/// @notice Removes a guardian for the Merkle tree containing allowed instructions.
/// @param guardian The address of the guardian to remove.
function removeInstrRootGuardian(address guardian) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IMakinaGovernable {
event MechanicChanged(address indexed oldMechanic, address indexed newMechanic);
event RecoveryModeChanged(bool recoveryMode);
event RiskManagerChanged(address indexed oldRiskManager, address indexed newRiskManager);
event RiskManagerTimelockChanged(address indexed oldRiskManagerTimelock, address indexed newRiskManagerTimelock);
event SecurityCouncilChanged(address indexed oldSecurityCouncil, address indexed newSecurityCouncil);
/// @notice Initialization parameters.
/// @param initialMechanic The address of the initial mechanic.
/// @param initialSecurityCouncil The address of the initial security council.
/// @param initialRiskManager The address of the initial risk manager.
/// @param initialRiskManagerTimelock The address of the initial risk manager timelock.
/// @param initialAuthority The address of the initial authority.
struct MakinaGovernableInitParams {
address initialMechanic;
address initialSecurityCouncil;
address initialRiskManager;
address initialRiskManagerTimelock;
address initialAuthority;
}
/// @notice Address of the mechanic.
function mechanic() external view returns (address);
/// @notice Address of the security council.
function securityCouncil() external view returns (address);
/// @notice Address of the risk manager.
function riskManager() external view returns (address);
/// @notice Address of the risk manager timelock.
function riskManagerTimelock() external view returns (address);
/// @notice True if the contract is in recovery mode, false otherwise.
function recoveryMode() external view returns (bool);
/// @notice Sets a new mechanic.
/// @param newMechanic The address of new mechanic.
function setMechanic(address newMechanic) external;
/// @notice Sets a new security council.
/// @param newSecurityCouncil The address of the new security council.
function setSecurityCouncil(address newSecurityCouncil) external;
/// @notice Sets a new risk manager.
/// @param newRiskManager The address of the new risk manager.
function setRiskManager(address newRiskManager) external;
/// @notice Sets a new risk manager timelock.
/// @param newRiskManagerTimelock The address of the new risk manager timelock.
function setRiskManagerTimelock(address newRiskManagerTimelock) external;
/// @notice Sets the recovery mode.
/// @param enabled True to enable recovery mode, false to disable it.
function setRecoveryMode(bool enabled) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
import {Ownable} from "./Ownable.sol";
/// @notice Simple single owner and multiroles authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/OwnableRoles.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract OwnableRoles is Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The `user`'s roles is updated to `roles`.
/// Each bit of `roles` represents whether the role is set.
event RolesUpdated(address indexed user, uint256 indexed roles);
/// @dev `keccak256(bytes("RolesUpdated(address,uint256)"))`.
uint256 private constant _ROLES_UPDATED_EVENT_SIGNATURE =
0x715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe26;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The role slot of `user` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _ROLE_SLOT_SEED))
/// let roleSlot := keccak256(0x00, 0x20)
/// ```
/// This automatically ignores the upper bits of the `user` in case
/// they are not clean, as well as keep the `keccak256` under 32-bytes.
///
/// Note: This is equivalent to `uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))`.
uint256 private constant _ROLE_SLOT_SEED = 0x8b78c6d8;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Overwrite the roles directly without authorization guard.
function _setRoles(address user, uint256 roles) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Store the new value.
sstore(keccak256(0x0c, 0x20), roles)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), roles)
}
}
/// @dev Updates the roles directly without authorization guard.
/// If `on` is true, each set bit of `roles` will be turned on,
/// otherwise, each set bit of `roles` will be turned off.
function _updateRoles(address user, uint256 roles, bool on) internal virtual {
/// @solidity memory-safe-assembly
assembly {
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
let roleSlot := keccak256(0x0c, 0x20)
// Load the current value.
let current := sload(roleSlot)
// Compute the updated roles if `on` is true.
let updated := or(current, roles)
// Compute the updated roles if `on` is false.
// Use `and` to compute the intersection of `current` and `roles`,
// `xor` it with `current` to flip the bits in the intersection.
if iszero(on) { updated := xor(current, and(current, roles)) }
// Then, store the new value.
sstore(roleSlot, updated)
// Emit the {RolesUpdated} event.
log3(0, 0, _ROLES_UPDATED_EVENT_SIGNATURE, shr(96, mload(0x0c)), updated)
}
}
/// @dev Grants the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn on.
function _grantRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, true);
}
/// @dev Removes the roles directly without authorization guard.
/// Each bit of `roles` represents the role to turn off.
function _removeRoles(address user, uint256 roles) internal virtual {
_updateRoles(user, roles, false);
}
/// @dev Throws if the sender does not have any of the `roles`.
function _checkRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Throws if the sender is not the owner,
/// and does not have any of the `roles`.
/// Checks for ownership first, then lazily checks for roles.
function _checkOwnerOrRoles(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Throws if the sender does not have any of the `roles`,
/// and is not the owner.
/// Checks for roles first, then lazily checks for ownership.
function _checkRolesOrOwner(uint256 roles) internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, caller())
// Load the stored value, and if the `and` intersection
// of the value and `roles` is zero, revert.
if iszero(and(sload(keccak256(0x0c, 0x20)), roles)) {
// If the caller is not the stored owner.
// Note: `_ROLE_SLOT_SEED` is equal to `_OWNER_SLOT_NOT`.
if iszero(eq(caller(), sload(not(_ROLE_SLOT_SEED)))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
}
/// @dev Convenience function to return a `roles` bitmap from an array of `ordinals`.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _rolesFromOrdinals(uint8[] memory ordinals) internal pure returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
for { let i := shl(5, mload(ordinals)) } i { i := sub(i, 0x20) } {
// We don't need to mask the values of `ordinals`, as Solidity
// cleans dirty upper bits when storing variables into memory.
roles := or(shl(mload(add(ordinals, i)), 1), roles)
}
}
}
/// @dev Convenience function to return an array of `ordinals` from the `roles` bitmap.
/// This is meant for frontends like Etherscan, and is therefore not fully optimized.
/// Not recommended to be called on-chain.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ordinalsFromRoles(uint256 roles) internal pure returns (uint8[] memory ordinals) {
/// @solidity memory-safe-assembly
assembly {
// Grab the pointer to the free memory.
ordinals := mload(0x40)
let ptr := add(ordinals, 0x20)
let o := 0
// The absence of lookup tables, De Bruijn, etc., here is intentional for
// smaller bytecode, as this function is not meant to be called on-chain.
for { let t := roles } 1 {} {
mstore(ptr, o)
// `shr` 5 is equivalent to multiplying by 0x20.
// Push back into the ordinals array if the bit is set.
ptr := add(ptr, shl(5, and(t, 1)))
o := add(o, 1)
t := shr(o, roles)
if iszero(t) { break }
}
// Store the length of `ordinals`.
mstore(ordinals, shr(5, sub(ptr, add(ordinals, 0x20))))
// Allocate the memory.
mstore(0x40, ptr)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to grant `user` `roles`.
/// If the `user` already has a role, then it will be an no-op for the role.
function grantRoles(address user, uint256 roles) public payable virtual onlyOwner {
_grantRoles(user, roles);
}
/// @dev Allows the owner to remove `user` `roles`.
/// If the `user` does not have a role, then it will be an no-op for the role.
function revokeRoles(address user, uint256 roles) public payable virtual onlyOwner {
_removeRoles(user, roles);
}
/// @dev Allow the caller to remove their own roles.
/// If the caller does not have a role, then it will be an no-op for the role.
function renounceRoles(uint256 roles) public payable virtual {
_removeRoles(msg.sender, roles);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the roles of `user`.
function rolesOf(address user) public view virtual returns (uint256 roles) {
/// @solidity memory-safe-assembly
assembly {
// Compute the role slot.
mstore(0x0c, _ROLE_SLOT_SEED)
mstore(0x00, user)
// Load the stored value.
roles := sload(keccak256(0x0c, 0x20))
}
}
/// @dev Returns whether `user` has any of `roles`.
function hasAnyRole(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles != 0;
}
/// @dev Returns whether `user` has all of `roles`.
function hasAllRoles(address user, uint256 roles) public view virtual returns (bool) {
return rolesOf(user) & roles == roles;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by an account with `roles`.
modifier onlyRoles(uint256 roles) virtual {
_checkRoles(roles);
_;
}
/// @dev Marks a function as only callable by the owner or by an account
/// with `roles`. Checks for ownership first, then lazily checks for roles.
modifier onlyOwnerOrRoles(uint256 roles) virtual {
_checkOwnerOrRoles(roles);
_;
}
/// @dev Marks a function as only callable by an account with `roles`
/// or the owner. Checks for roles first, then lazily checks for ownership.
modifier onlyRolesOrOwner(uint256 roles) virtual {
_checkRolesOrOwner(roles);
_;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* ROLE CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// IYKYK
uint256 internal constant _ROLE_0 = 1 << 0;
uint256 internal constant _ROLE_1 = 1 << 1;
uint256 internal constant _ROLE_2 = 1 << 2;
uint256 internal constant _ROLE_3 = 1 << 3;
uint256 internal constant _ROLE_4 = 1 << 4;
uint256 internal constant _ROLE_5 = 1 << 5;
uint256 internal constant _ROLE_6 = 1 << 6;
uint256 internal constant _ROLE_7 = 1 << 7;
uint256 internal constant _ROLE_8 = 1 << 8;
uint256 internal constant _ROLE_9 = 1 << 9;
uint256 internal constant _ROLE_10 = 1 << 10;
uint256 internal constant _ROLE_11 = 1 << 11;
uint256 internal constant _ROLE_12 = 1 << 12;
uint256 internal constant _ROLE_13 = 1 << 13;
uint256 internal constant _ROLE_14 = 1 << 14;
uint256 internal constant _ROLE_15 = 1 << 15;
uint256 internal constant _ROLE_16 = 1 << 16;
uint256 internal constant _ROLE_17 = 1 << 17;
uint256 internal constant _ROLE_18 = 1 << 18;
uint256 internal constant _ROLE_19 = 1 << 19;
uint256 internal constant _ROLE_20 = 1 << 20;
uint256 internal constant _ROLE_21 = 1 << 21;
uint256 internal constant _ROLE_22 = 1 << 22;
uint256 internal constant _ROLE_23 = 1 << 23;
uint256 internal constant _ROLE_24 = 1 << 24;
uint256 internal constant _ROLE_25 = 1 << 25;
uint256 internal constant _ROLE_26 = 1 << 26;
uint256 internal constant _ROLE_27 = 1 << 27;
uint256 internal constant _ROLE_28 = 1 << 28;
uint256 internal constant _ROLE_29 = 1 << 29;
uint256 internal constant _ROLE_30 = 1 << 30;
uint256 internal constant _ROLE_31 = 1 << 31;
uint256 internal constant _ROLE_32 = 1 << 32;
uint256 internal constant _ROLE_33 = 1 << 33;
uint256 internal constant _ROLE_34 = 1 << 34;
uint256 internal constant _ROLE_35 = 1 << 35;
uint256 internal constant _ROLE_36 = 1 << 36;
uint256 internal constant _ROLE_37 = 1 << 37;
uint256 internal constant _ROLE_38 = 1 << 38;
uint256 internal constant _ROLE_39 = 1 << 39;
uint256 internal constant _ROLE_40 = 1 << 40;
uint256 internal constant _ROLE_41 = 1 << 41;
uint256 internal constant _ROLE_42 = 1 << 42;
uint256 internal constant _ROLE_43 = 1 << 43;
uint256 internal constant _ROLE_44 = 1 << 44;
uint256 internal constant _ROLE_45 = 1 << 45;
uint256 internal constant _ROLE_46 = 1 << 46;
uint256 internal constant _ROLE_47 = 1 << 47;
uint256 internal constant _ROLE_48 = 1 << 48;
uint256 internal constant _ROLE_49 = 1 << 49;
uint256 internal constant _ROLE_50 = 1 << 50;
uint256 internal constant _ROLE_51 = 1 << 51;
uint256 internal constant _ROLE_52 = 1 << 52;
uint256 internal constant _ROLE_53 = 1 << 53;
uint256 internal constant _ROLE_54 = 1 << 54;
uint256 internal constant _ROLE_55 = 1 << 55;
uint256 internal constant _ROLE_56 = 1 << 56;
uint256 internal constant _ROLE_57 = 1 << 57;
uint256 internal constant _ROLE_58 = 1 << 58;
uint256 internal constant _ROLE_59 = 1 << 59;
uint256 internal constant _ROLE_60 = 1 << 60;
uint256 internal constant _ROLE_61 = 1 << 61;
uint256 internal constant _ROLE_62 = 1 << 62;
uint256 internal constant _ROLE_63 = 1 << 63;
uint256 internal constant _ROLE_64 = 1 << 64;
uint256 internal constant _ROLE_65 = 1 << 65;
uint256 internal constant _ROLE_66 = 1 << 66;
uint256 internal constant _ROLE_67 = 1 << 67;
uint256 internal constant _ROLE_68 = 1 << 68;
uint256 internal constant _ROLE_69 = 1 << 69;
uint256 internal constant _ROLE_70 = 1 << 70;
uint256 internal constant _ROLE_71 = 1 << 71;
uint256 internal constant _ROLE_72 = 1 << 72;
uint256 internal constant _ROLE_73 = 1 << 73;
uint256 internal constant _ROLE_74 = 1 << 74;
uint256 internal constant _ROLE_75 = 1 << 75;
uint256 internal constant _ROLE_76 = 1 << 76;
uint256 internal constant _ROLE_77 = 1 << 77;
uint256 internal constant _ROLE_78 = 1 << 78;
uint256 internal constant _ROLE_79 = 1 << 79;
uint256 internal constant _ROLE_80 = 1 << 80;
uint256 internal constant _ROLE_81 = 1 << 81;
uint256 internal constant _ROLE_82 = 1 << 82;
uint256 internal constant _ROLE_83 = 1 << 83;
uint256 internal constant _ROLE_84 = 1 << 84;
uint256 internal constant _ROLE_85 = 1 << 85;
uint256 internal constant _ROLE_86 = 1 << 86;
uint256 internal constant _ROLE_87 = 1 << 87;
uint256 internal constant _ROLE_88 = 1 << 88;
uint256 internal constant _ROLE_89 = 1 << 89;
uint256 internal constant _ROLE_90 = 1 << 90;
uint256 internal constant _ROLE_91 = 1 << 91;
uint256 internal constant _ROLE_92 = 1 << 92;
uint256 internal constant _ROLE_93 = 1 << 93;
uint256 internal constant _ROLE_94 = 1 << 94;
uint256 internal constant _ROLE_95 = 1 << 95;
uint256 internal constant _ROLE_96 = 1 << 96;
uint256 internal constant _ROLE_97 = 1 << 97;
uint256 internal constant _ROLE_98 = 1 << 98;
uint256 internal constant _ROLE_99 = 1 << 99;
uint256 internal constant _ROLE_100 = 1 << 100;
uint256 internal constant _ROLE_101 = 1 << 101;
uint256 internal constant _ROLE_102 = 1 << 102;
uint256 internal constant _ROLE_103 = 1 << 103;
uint256 internal constant _ROLE_104 = 1 << 104;
uint256 internal constant _ROLE_105 = 1 << 105;
uint256 internal constant _ROLE_106 = 1 << 106;
uint256 internal constant _ROLE_107 = 1 << 107;
uint256 internal constant _ROLE_108 = 1 << 108;
uint256 internal constant _ROLE_109 = 1 << 109;
uint256 internal constant _ROLE_110 = 1 << 110;
uint256 internal constant _ROLE_111 = 1 << 111;
uint256 internal constant _ROLE_112 = 1 << 112;
uint256 internal constant _ROLE_113 = 1 << 113;
uint256 internal constant _ROLE_114 = 1 << 114;
uint256 internal constant _ROLE_115 = 1 << 115;
uint256 internal constant _ROLE_116 = 1 << 116;
uint256 internal constant _ROLE_117 = 1 << 117;
uint256 internal constant _ROLE_118 = 1 << 118;
uint256 internal constant _ROLE_119 = 1 << 119;
uint256 internal constant _ROLE_120 = 1 << 120;
uint256 internal constant _ROLE_121 = 1 << 121;
uint256 internal constant _ROLE_122 = 1 << 122;
uint256 internal constant _ROLE_123 = 1 << 123;
uint256 internal constant _ROLE_124 = 1 << 124;
uint256 internal constant _ROLE_125 = 1 << 125;
uint256 internal constant _ROLE_126 = 1 << 126;
uint256 internal constant _ROLE_127 = 1 << 127;
uint256 internal constant _ROLE_128 = 1 << 128;
uint256 internal constant _ROLE_129 = 1 << 129;
uint256 internal constant _ROLE_130 = 1 << 130;
uint256 internal constant _ROLE_131 = 1 << 131;
uint256 internal constant _ROLE_132 = 1 << 132;
uint256 internal constant _ROLE_133 = 1 << 133;
uint256 internal constant _ROLE_134 = 1 << 134;
uint256 internal constant _ROLE_135 = 1 << 135;
uint256 internal constant _ROLE_136 = 1 << 136;
uint256 internal constant _ROLE_137 = 1 << 137;
uint256 internal constant _ROLE_138 = 1 << 138;
uint256 internal constant _ROLE_139 = 1 << 139;
uint256 internal constant _ROLE_140 = 1 << 140;
uint256 internal constant _ROLE_141 = 1 << 141;
uint256 internal constant _ROLE_142 = 1 << 142;
uint256 internal constant _ROLE_143 = 1 << 143;
uint256 internal constant _ROLE_144 = 1 << 144;
uint256 internal constant _ROLE_145 = 1 << 145;
uint256 internal constant _ROLE_146 = 1 << 146;
uint256 internal constant _ROLE_147 = 1 << 147;
uint256 internal constant _ROLE_148 = 1 << 148;
uint256 internal constant _ROLE_149 = 1 << 149;
uint256 internal constant _ROLE_150 = 1 << 150;
uint256 internal constant _ROLE_151 = 1 << 151;
uint256 internal constant _ROLE_152 = 1 << 152;
uint256 internal constant _ROLE_153 = 1 << 153;
uint256 internal constant _ROLE_154 = 1 << 154;
uint256 internal constant _ROLE_155 = 1 << 155;
uint256 internal constant _ROLE_156 = 1 << 156;
uint256 internal constant _ROLE_157 = 1 << 157;
uint256 internal constant _ROLE_158 = 1 << 158;
uint256 internal constant _ROLE_159 = 1 << 159;
uint256 internal constant _ROLE_160 = 1 << 160;
uint256 internal constant _ROLE_161 = 1 << 161;
uint256 internal constant _ROLE_162 = 1 << 162;
uint256 internal constant _ROLE_163 = 1 << 163;
uint256 internal constant _ROLE_164 = 1 << 164;
uint256 internal constant _ROLE_165 = 1 << 165;
uint256 internal constant _ROLE_166 = 1 << 166;
uint256 internal constant _ROLE_167 = 1 << 167;
uint256 internal constant _ROLE_168 = 1 << 168;
uint256 internal constant _ROLE_169 = 1 << 169;
uint256 internal constant _ROLE_170 = 1 << 170;
uint256 internal constant _ROLE_171 = 1 << 171;
uint256 internal constant _ROLE_172 = 1 << 172;
uint256 internal constant _ROLE_173 = 1 << 173;
uint256 internal constant _ROLE_174 = 1 << 174;
uint256 internal constant _ROLE_175 = 1 << 175;
uint256 internal constant _ROLE_176 = 1 << 176;
uint256 internal constant _ROLE_177 = 1 << 177;
uint256 internal constant _ROLE_178 = 1 << 178;
uint256 internal constant _ROLE_179 = 1 << 179;
uint256 internal constant _ROLE_180 = 1 << 180;
uint256 internal constant _ROLE_181 = 1 << 181;
uint256 internal constant _ROLE_182 = 1 << 182;
uint256 internal constant _ROLE_183 = 1 << 183;
uint256 internal constant _ROLE_184 = 1 << 184;
uint256 internal constant _ROLE_185 = 1 << 185;
uint256 internal constant _ROLE_186 = 1 << 186;
uint256 internal constant _ROLE_187 = 1 << 187;
uint256 internal constant _ROLE_188 = 1 << 188;
uint256 internal constant _ROLE_189 = 1 << 189;
uint256 internal constant _ROLE_190 = 1 << 190;
uint256 internal constant _ROLE_191 = 1 << 191;
uint256 internal constant _ROLE_192 = 1 << 192;
uint256 internal constant _ROLE_193 = 1 << 193;
uint256 internal constant _ROLE_194 = 1 << 194;
uint256 internal constant _ROLE_195 = 1 << 195;
uint256 internal constant _ROLE_196 = 1 << 196;
uint256 internal constant _ROLE_197 = 1 << 197;
uint256 internal constant _ROLE_198 = 1 << 198;
uint256 internal constant _ROLE_199 = 1 << 199;
uint256 internal constant _ROLE_200 = 1 << 200;
uint256 internal constant _ROLE_201 = 1 << 201;
uint256 internal constant _ROLE_202 = 1 << 202;
uint256 internal constant _ROLE_203 = 1 << 203;
uint256 internal constant _ROLE_204 = 1 << 204;
uint256 internal constant _ROLE_205 = 1 << 205;
uint256 internal constant _ROLE_206 = 1 << 206;
uint256 internal constant _ROLE_207 = 1 << 207;
uint256 internal constant _ROLE_208 = 1 << 208;
uint256 internal constant _ROLE_209 = 1 << 209;
uint256 internal constant _ROLE_210 = 1 << 210;
uint256 internal constant _ROLE_211 = 1 << 211;
uint256 internal constant _ROLE_212 = 1 << 212;
uint256 internal constant _ROLE_213 = 1 << 213;
uint256 internal constant _ROLE_214 = 1 << 214;
uint256 internal constant _ROLE_215 = 1 << 215;
uint256 internal constant _ROLE_216 = 1 << 216;
uint256 internal constant _ROLE_217 = 1 << 217;
uint256 internal constant _ROLE_218 = 1 << 218;
uint256 internal constant _ROLE_219 = 1 << 219;
uint256 internal constant _ROLE_220 = 1 << 220;
uint256 internal constant _ROLE_221 = 1 << 221;
uint256 internal constant _ROLE_222 = 1 << 222;
uint256 internal constant _ROLE_223 = 1 << 223;
uint256 internal constant _ROLE_224 = 1 << 224;
uint256 internal constant _ROLE_225 = 1 << 225;
uint256 internal constant _ROLE_226 = 1 << 226;
uint256 internal constant _ROLE_227 = 1 << 227;
uint256 internal constant _ROLE_228 = 1 << 228;
uint256 internal constant _ROLE_229 = 1 << 229;
uint256 internal constant _ROLE_230 = 1 << 230;
uint256 internal constant _ROLE_231 = 1 << 231;
uint256 internal constant _ROLE_232 = 1 << 232;
uint256 internal constant _ROLE_233 = 1 << 233;
uint256 internal constant _ROLE_234 = 1 << 234;
uint256 internal constant _ROLE_235 = 1 << 235;
uint256 internal constant _ROLE_236 = 1 << 236;
uint256 internal constant _ROLE_237 = 1 << 237;
uint256 internal constant _ROLE_238 = 1 << 238;
uint256 internal constant _ROLE_239 = 1 << 239;
uint256 internal constant _ROLE_240 = 1 << 240;
uint256 internal constant _ROLE_241 = 1 << 241;
uint256 internal constant _ROLE_242 = 1 << 242;
uint256 internal constant _ROLE_243 = 1 << 243;
uint256 internal constant _ROLE_244 = 1 << 244;
uint256 internal constant _ROLE_245 = 1 << 245;
uint256 internal constant _ROLE_246 = 1 << 246;
uint256 internal constant _ROLE_247 = 1 << 247;
uint256 internal constant _ROLE_248 = 1 << 248;
uint256 internal constant _ROLE_249 = 1 << 249;
uint256 internal constant _ROLE_250 = 1 << 250;
uint256 internal constant _ROLE_251 = 1 << 251;
uint256 internal constant _ROLE_252 = 1 << 252;
uint256 internal constant _ROLE_253 = 1 << 253;
uint256 internal constant _ROLE_254 = 1 << 254;
uint256 internal constant _ROLE_255 = 1 << 255;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
import {IWatermarkFeeManager} from "@makina-periphery/interfaces/IWatermarkFeeManager.sol";
import {ICaliber} from "@makina-core/interfaces/ICaliber.sol";
import {IMakinaGovernable} from "@makina-core/interfaces/IMakinaGovernable.sol";
interface IMachineZap {
function createMachine(
string calldata shareTokenName,
string calldata shareTokenSymbol,
address accountingToken,
address[] calldata baseTokens,
bytes32 salt,
uint16 depositorImplemId,
bool depositorWhitelistStatus,
uint16 redeemerImplemId,
bool redeemerWhitelistStatus,
uint256 redeemerFinalizationDelay,
uint256 redeemerMinRedeemAmount,
uint16 feeManagerImplemId,
IWatermarkFeeManager.WatermarkFeeManagerInitParams calldata feeManagerInitParams,
MachineInitParams calldata machineInitParams,
ICaliber.CaliberInitParams calldata caliberInitParams,
IMakinaGovernable.MakinaGovernableInitParams calldata mgInitParams
) external returns (address machine);
struct MachineInitParams {
uint256 initialCaliberStaleThreshold;
uint256 initialMaxFixedFeeAccrualRate;
uint256 initialMaxPerfFeeAccrualRate;
uint256 initialFeeMintCooldown;
uint256 initialShareLimit;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IFeeManager {
/// @notice Calculates the fixed fee for a given share supply and elapsed time.
/// @dev May update internal state related to fee accrual or realization.
/// @param shareSupply The total supply of shares.
/// @param elapsedTime The elapsed time since the last fee realization.
/// @return fee The calculated fixed fee.
function calculateFixedFee(uint256 shareSupply, uint256 elapsedTime) external returns (uint256);
/// @notice Calculates the performance fee based on the share supply, share price performance and elapsed time.
/// @dev May update internal state related to fee accrual or realization.
/// @param currentShareSupply The current total supply of shares.
/// @param oldSharePrice The previous share price of reference.
/// @param newSharePrice The new share price of reference.
/// @param elapsedTime The elapsed time since the last fee realization.
/// @return fee The calculated performance fee.
function calculatePerformanceFee(
uint256 currentShareSupply,
uint256 oldSharePrice,
uint256 newSharePrice,
uint256 elapsedTime
) external returns (uint256);
/// @notice Distributes the fees to relevant recipients.
/// @param fixedFee The fixed fee amount to be distributed.
/// @param perfFee The performance fee amount to be distributed.
function distributeFees(uint256 fixedFee, uint256 perfFee) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IMachinePeriphery {
event MachineSet(address indexed machine);
/// @notice Initializer of the contract.
/// @param _data The initialization data, if any.
function initialize(bytes calldata _data) external;
/// @notice Address of the associated machine.
function machine() external view returns (address);
/// @notice Sets the machine address.
function setMachine(address _machine) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface ISecurityModuleReference {
/// @notice Security module address.
function securityModule() external view returns (address);
/// @notice Sets the security module address.
/// @param securityModule The address of the security module.
function setSecurityModule(address securityModule) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import {IMachinePeriphery} from "../interfaces/IMachinePeriphery.sol";
interface ISecurityModule is IERC20Metadata, IMachinePeriphery {
event Cooldown(
uint256 indexed cooldownId, address indexed account, address indexed receiver, uint256 shares, uint256 maturity
);
event CooldownCancelled(uint256 indexed cooldownId, address indexed receiver, uint256 shares);
event CooldownDurationChanged(uint256 oldCooldownDuration, uint256 newCooldownDuration);
event MaxSlashableBpsChanged(uint256 oldMaxSlashableBps, uint256 newMaxSlashableBps);
event MinBalanceAfterSlashChanged(uint256 oldMinBalanceAfterSlash, uint256 newMinBalanceAfterSlash);
event Lock(address indexed account, address indexed receiver, uint256 assets, uint256 shares);
event Redeem(uint256 indexed cooldownId, address indexed receiver, uint256 assets, uint256 shares);
event Slash(uint256 amount);
event SlashingSettled();
/// @notice Initialization parameters.
/// @param machineShare Address of the machine share token locked in this contract.
/// @param initialCooldownDuration Cooldown duration in seconds for unlocking.
/// @param initialMaxSlashableBps Maximum slashable proportion of the vault balance in basis points.
/// @param minBalanceAfterSlash Minimum balance that must remain in the vault after a slash.
struct SecurityModuleInitParams {
address machineShare;
uint256 initialCooldownDuration;
uint256 initialMaxSlashableBps;
uint256 initialMinBalanceAfterSlash;
}
/// @notice Pending cooldown parameters.
/// @param shares Amount of security shares to be redeemed.
/// @param maxAssets Maximum amount of machine shares that can be redeemed.
/// @param maturity Timestamp at which the cooldown period will end and the shares can be redeemed.
struct PendingCooldown {
uint256 shares;
uint256 maxAssets;
uint256 maturity;
}
/// @notice Address of the machine share token locked in this contract.
function machineShare() external view returns (address);
/// @notice Address of the cooldown receipt NFT.
function cooldownReceipt() external view returns (address);
/// @notice Cooldown duration in seconds for unlocking.
function cooldownDuration() external view returns (uint256);
/// @notice Maximum slashable proportion of the vault balance in basis points.
function maxSlashableBps() external view returns (uint256);
/// @notice Minimum balance that must remain in the vault after a slash.
function minBalanceAfterSlash() external view returns (uint256);
/// @notice Returns data of a pending cooldown.
/// @param cooldownId ID of the cooldown receipt NFT representing the pending cooldown.
/// @return shares Amount of security shares to be redeemed.
/// @return currentExpectedAssets Current expected amount of machine shares that can be redeemed.
/// @return maturity Timestamp at which the cooldown period will end and the shares can be redeemed.
function pendingCooldown(uint256 cooldownId)
external
view
returns (uint256 shares, uint256 currentExpectedAssets, uint256 maturity);
/// @notice Whether the security module is in slashing mode.
function slashingMode() external view returns (bool);
/// @notice Total amount of machine shares locked in the module.
function totalLockedAmount() external view returns (uint256);
/// @notice Total amount of machine shares currently slashable in the module.
function maxSlashable() external view returns (uint256);
/// @notice Converts machine shares to security shares.
/// @param assets Amount of machine shares to convert.
/// @return shares Amount of security shares corresponding to the input machine shares.
function convertToShares(uint256 assets) external view returns (uint256 shares);
/// @notice Converts security shares to machine shares.
/// @param shares Amount of security shares to convert.
/// @return assets Amount of machine shares corresponding to the input security shares.
function convertToAssets(uint256 shares) external view returns (uint256 assets);
/// @notice Estimates the amount of security shares that would be received for a given amount of machine shares.
/// @param assets Amount of machine shares to convert.
/// @return shares Estimated amount of security shares corresponding to the input machine shares.
function previewLock(uint256 assets) external view returns (uint256 shares);
/// @notice Locks machine shares in the module and mints security shares.
/// @param assets Amount of machine shares to lock.
/// @param receiver Address that will receive the security shares.
/// @param minShares Minimum amount of security shares to receive.
/// @return shares Amount of security shares minted.
function lock(uint256 assets, address receiver, uint256 minShares) external returns (uint256 shares);
/// @notice Requests a cooldown for redeeming security shares.
/// Shares are locked in the contract until the cooldown is cancelled or expires.
/// A cooldown receipt NFT is minted to the specified receiver address.
/// @param shares Amount of security shares to redeem.
/// @param receiver Address that will receive the cooldown receipt.
/// @return cooldownId ID of the minted cooldown receipt NFT representing the pending cooldown.
/// @return maxAssets Maximum amount of machine shares that can be redeemed.
/// @return maturity Timestamp at which the cooldown period will end and the shares can be redeemed.
function startCooldown(uint256 shares, address receiver)
external
returns (uint256 cooldownId, uint256 maxAssets, uint256 maturity);
/// @notice Cancels a pending cooldown.
/// Shares for which the cooldown was cancelled are transferred back to caller.
/// The associated cooldown receipt NFT is burned.
/// @param cooldownId ID of the cooldown receipt NFT representing the pending cooldown.
/// @return shares Amount of security shares for which the cooldown was cancelled.
function cancelCooldown(uint256 cooldownId) external returns (uint256 shares);
/// @notice Redeems security shares and transfers machine shares to caller.
/// @param cooldownId ID of the cooldown receipt NFT representing the pending cooldown.
/// @param minAssets Minimum amount of machine shares to receive.
/// @return assets Amount of machine shares transferred to the receiver.
function redeem(uint256 cooldownId, uint256 minAssets) external returns (uint256 assets);
/// @notice Slashes a specified amount from the total locked amount and triggers the slashing mode.
/// @param amount Amount to slash from the total locked amount.
function slash(uint256 amount) external;
/// @notice Settles the current slashing, allowing the contract to exit slashing mode and resume normal operations.
function settleSlashing() external;
/// @notice Sets the cooldown duration for unlocking.
/// @param cooldownDuration New cooldown duration in seconds.
function setCooldownDuration(uint256 cooldownDuration) external;
/// @notice Sets the maximum slashable proportion of the vault balance in basis points.
/// @param maxSlashableBps New maximum slashable proportion in basis points.
function setMaxSlashableBps(uint256 maxSlashableBps) external;
/// @notice Sets the minimum balance that must remain in the vault after a slash.
/// @param minBalanceAfterSlash New minimum balance after slash.
function setMinBalanceAfterSlash(uint256 minBalanceAfterSlash) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IPreDepositVault {
event Deposit(address indexed sender, address indexed receiver, uint256 assets, uint256 shares);
event MigrateToMachine(address indexed machine);
event Redeem(address indexed owner, address indexed receiver, uint256 assets, uint256 shares);
event RiskManagerChanged(address indexed oldRiskManager, address indexed newRiskManager);
event ShareLimitChanged(uint256 indexed oldShareLimit, uint256 indexed newShareLimit);
event UserWhitelistingChanged(address indexed user, bool indexed whitelisted);
event WhitelistModeChanged(bool indexed enabled);
struct PreDepositVaultInitParams {
uint256 initialShareLimit;
bool initialWhitelistMode;
address initialRiskManager;
address initialAuthority;
}
/// @notice Initializer of the contract.
/// @param params The initialization parameters.
/// @param shareToken The address of the share token.
/// @param depositToken The address of the deposit token.
/// @param accountingToken The address of the accounting token.
function initialize(
PreDepositVaultInitParams calldata params,
address shareToken,
address depositToken,
address accountingToken
) external;
/// @notice True if the vault has migrated to a machine instance, false otherwise.
function migrated() external view returns (bool);
/// @notice Address of the machine, set during migration.
function machine() external view returns (address);
/// @notice Address of the risk manager.
function riskManager() external view returns (address);
/// @notice True if the vault is in whitelist mode, false otherwise.
function whitelistMode() external view returns (bool);
/// @notice User => Whitelisting status.
function isWhitelistedUser(address user) external view returns (bool);
/// @notice Address of the deposit token.
function depositToken() external view returns (address);
/// @notice Address of the accounting token.
function accountingToken() external view returns (address);
/// @notice Address of the share token.
function shareToken() external view returns (address);
/// @notice Share token supply limit that cannot be exceeded by new deposits.
function shareLimit() external view returns (uint256);
/// @notice Maximum amount of deposit tokens that can currently be deposited in the vault.
function maxDeposit() external view returns (uint256);
/// @notice Total amount of deposit tokens managed by the vault.
function totalAssets() external view returns (uint256);
/// @notice Amount of shares minted against a given amount of deposit tokens.
/// @param assets The amount of deposit tokens to be deposited.
function previewDeposit(uint256 assets) external view returns (uint256);
/// @notice Amount of deposit tokens that can be withdrawn against a given amount of shares.
/// @param assets The amount of shares to be redeemed.
function previewRedeem(uint256 assets) external view returns (uint256);
/// @notice Deposits a given amount of deposit tokens and mints shares to the receiver.
/// @param assets The amount of deposit tokens to be deposited.
/// @param receiver The receiver of the shares.
/// @param minShares The minimum amount of shares to be minted.
/// @return shares The amount of shares minted.
function deposit(uint256 assets, address receiver, uint256 minShares) external returns (uint256);
/// @notice Burns exactly shares from caller and transfers the corresponding amount of deposit tokens to the receiver.
/// @param shares The amount of shares to be redeemed.
/// @param receiver The receiver of withdrawn deposit tokens.
/// @param minAssets The minimum amount of deposit tokens to be transferred.
/// @return assets The amount of deposit tokens transferred.
function redeem(uint256 shares, address receiver, uint256 minAssets) external returns (uint256);
/// @notice Migrates the pre-deposit vault to the machine.
function migrateToMachine() external;
/// @notice Sets the machine address to migrate to.
/// @param machine The address of the machine.
function setPendingMachine(address machine) external;
/// @notice Sets the risk manager address.
/// @param newRiskManager The address of the new risk manager.
function setRiskManager(address newRiskManager) external;
/// @notice Sets the new share token supply limit that cannot be exceeded by new deposits.
/// @param newShareLimit The new share limit
function setShareLimit(uint256 newShareLimit) external;
/// @notice Whitelist or unwhitelist a list of users.
/// @param users The addresses of the users to update.
/// @param whitelisted True to whitelist the users, false to unwhitelist.
function setWhitelistedUsers(address[] calldata users, bool whitelisted) external;
/// @notice Sets the whitelist mode for the vault.
/// @dev In whitelist mode, only whitelisted users can deposit.
/// @param enabled True to enable whitelist mode, false to disable.
function setWhitelistMode(bool enabled) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IBridgeAdapterFactory {
event BridgeAdapterCreated(address indexed controller, uint256 indexed bridgeId, address indexed adapter);
/// @notice Address => Whether this is a BridgeAdapter instance deployed by this factory.
function isBridgeAdapter(address adapter) external view returns (bool);
/// @notice Deploys a bridge adapter instance.
/// @param bridgeId The ID of the bridge for which the adapter is being created.
/// @param initData The optional initialization data for the bridge adapter.
/// @return adapter The address of the deployed bridge adapter.
function createBridgeAdapter(uint16 bridgeId, bytes calldata initData) external returns (address adapter);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableMap.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableMap.js.
pragma solidity ^0.8.20;
import {EnumerableSet} from "./EnumerableSet.sol";
/**
* @dev Library for managing an enumerable variant of Solidity's
* https://solidity.readthedocs.io/en/latest/types.html#mapping-types[`mapping`]
* type.
*
* Maps have the following properties:
*
* - Entries are added, removed, and checked for existence in constant time
* (O(1)).
* - Entries are enumerated in O(n). No guarantees are made on the ordering.
* - Map can be cleared (all entries removed) in O(n).
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableMap for EnumerableMap.UintToAddressMap;
*
* // Declare a set state variable
* EnumerableMap.UintToAddressMap private myMap;
* }
* ```
*
* The following map types are supported:
*
* - `uint256 -> address` (`UintToAddressMap`) since v3.0.0
* - `address -> uint256` (`AddressToUintMap`) since v4.6.0
* - `bytes32 -> bytes32` (`Bytes32ToBytes32Map`) since v4.6.0
* - `uint256 -> uint256` (`UintToUintMap`) since v4.7.0
* - `bytes32 -> uint256` (`Bytes32ToUintMap`) since v4.7.0
* - `uint256 -> bytes32` (`UintToBytes32Map`) since v5.1.0
* - `address -> address` (`AddressToAddressMap`) since v5.1.0
* - `address -> bytes32` (`AddressToBytes32Map`) since v5.1.0
* - `bytes32 -> address` (`Bytes32ToAddressMap`) since v5.1.0
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableMap, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableMap.
* ====
*/
library EnumerableMap {
using EnumerableSet for EnumerableSet.Bytes32Set;
// To implement this library for multiple types with as little code repetition as possible, we write it in
// terms of a generic Map type with bytes32 keys and values. The Map implementation uses private functions,
// and user-facing implementations such as `UintToAddressMap` are just wrappers around the underlying Map.
// This means that we can only create new EnumerableMaps for types that fit in bytes32.
/**
* @dev Query for a nonexistent map key.
*/
error EnumerableMapNonexistentKey(bytes32 key);
struct Bytes32ToBytes32Map {
// Storage of keys
EnumerableSet.Bytes32Set _keys;
mapping(bytes32 key => bytes32) _values;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) internal returns (bool) {
map._values[key] = value;
return map._keys.add(key);
}
/**
* @dev Removes a key-value pair from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToBytes32Map storage map, bytes32 key) internal returns (bool) {
delete map._values[key];
return map._keys.remove(key);
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToBytes32Map storage map) internal {
uint256 len = length(map);
for (uint256 i = 0; i < len; ++i) {
delete map._values[map._keys.at(i)];
}
map._keys.clear();
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool) {
return map._keys.contains(key);
}
/**
* @dev Returns the number of key-value pairs in the map. O(1).
*/
function length(Bytes32ToBytes32Map storage map) internal view returns (uint256) {
return map._keys.length();
}
/**
* @dev Returns the key-value pair stored at position `index` in the map. O(1).
*
* Note that there are no guarantees on the ordering of entries inside the
* array, and it may change when more entries are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToBytes32Map storage map, uint256 index) internal view returns (bytes32 key, bytes32 value) {
bytes32 atKey = map._keys.at(index);
return (atKey, map._values[atKey]);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bool exists, bytes32 value) {
bytes32 val = map._values[key];
if (val == bytes32(0)) {
return (contains(map, key), bytes32(0));
} else {
return (true, val);
}
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToBytes32Map storage map, bytes32 key) internal view returns (bytes32) {
bytes32 value = map._values[key];
if (value == 0 && !contains(map, key)) {
revert EnumerableMapNonexistentKey(key);
}
return value;
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToBytes32Map storage map) internal view returns (bytes32[] memory) {
return map._keys.values();
}
// UintToUintMap
struct UintToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToUintMap storage map, uint256 key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToUintMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintToUintMap storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToUintMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToUintMap storage map, uint256 index) internal view returns (uint256 key, uint256 value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (uint256(atKey), uint256(val));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToUintMap storage map, uint256 key) internal view returns (bool exists, uint256 value) {
(bool success, bytes32 val) = tryGet(map._inner, bytes32(key));
return (success, uint256(val));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToUintMap storage map, uint256 key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(key)));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToUintMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// UintToAddressMap
struct UintToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToAddressMap storage map, uint256 key, address value) internal returns (bool) {
return set(map._inner, bytes32(key), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToAddressMap storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintToAddressMap storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToAddressMap storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToAddressMap storage map, uint256 index) internal view returns (uint256 key, address value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (uint256(atKey), address(uint160(uint256(val))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToAddressMap storage map, uint256 key) internal view returns (bool exists, address value) {
(bool success, bytes32 val) = tryGet(map._inner, bytes32(key));
return (success, address(uint160(uint256(val))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToAddressMap storage map, uint256 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(key)))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToAddressMap storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// UintToBytes32Map
struct UintToBytes32Map {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(UintToBytes32Map storage map, uint256 key, bytes32 value) internal returns (bool) {
return set(map._inner, bytes32(key), value);
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(UintToBytes32Map storage map, uint256 key) internal returns (bool) {
return remove(map._inner, bytes32(key));
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintToBytes32Map storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(UintToBytes32Map storage map, uint256 key) internal view returns (bool) {
return contains(map._inner, bytes32(key));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(UintToBytes32Map storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintToBytes32Map storage map, uint256 index) internal view returns (uint256 key, bytes32 value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (uint256(atKey), val);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(UintToBytes32Map storage map, uint256 key) internal view returns (bool exists, bytes32 value) {
(bool success, bytes32 val) = tryGet(map._inner, bytes32(key));
return (success, val);
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(UintToBytes32Map storage map, uint256 key) internal view returns (bytes32) {
return get(map._inner, bytes32(key));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(UintToBytes32Map storage map) internal view returns (uint256[] memory) {
bytes32[] memory store = keys(map._inner);
uint256[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// AddressToUintMap
struct AddressToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(AddressToUintMap storage map, address key, uint256 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToUintMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressToUintMap storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToUintMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToUintMap storage map, uint256 index) internal view returns (address key, uint256 value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (address(uint160(uint256(atKey))), uint256(val));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToUintMap storage map, address key) internal view returns (bool exists, uint256 value) {
(bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, uint256(val));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToUintMap storage map, address key) internal view returns (uint256) {
return uint256(get(map._inner, bytes32(uint256(uint160(key)))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(AddressToUintMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// AddressToAddressMap
struct AddressToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(AddressToAddressMap storage map, address key, address value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToAddressMap storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressToAddressMap storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToAddressMap storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToAddressMap storage map, uint256 index) internal view returns (address key, address value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (address(uint160(uint256(atKey))), address(uint160(uint256(val))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToAddressMap storage map, address key) internal view returns (bool exists, address value) {
(bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, address(uint160(uint256(val))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToAddressMap storage map, address key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, bytes32(uint256(uint160(key)))))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(AddressToAddressMap storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// AddressToBytes32Map
struct AddressToBytes32Map {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(AddressToBytes32Map storage map, address key, bytes32 value) internal returns (bool) {
return set(map._inner, bytes32(uint256(uint160(key))), value);
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(AddressToBytes32Map storage map, address key) internal returns (bool) {
return remove(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressToBytes32Map storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(AddressToBytes32Map storage map, address key) internal view returns (bool) {
return contains(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(AddressToBytes32Map storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressToBytes32Map storage map, uint256 index) internal view returns (address key, bytes32 value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (address(uint160(uint256(atKey))), val);
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(AddressToBytes32Map storage map, address key) internal view returns (bool exists, bytes32 value) {
(bool success, bytes32 val) = tryGet(map._inner, bytes32(uint256(uint160(key))));
return (success, val);
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(AddressToBytes32Map storage map, address key) internal view returns (bytes32) {
return get(map._inner, bytes32(uint256(uint160(key))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(AddressToBytes32Map storage map) internal view returns (address[] memory) {
bytes32[] memory store = keys(map._inner);
address[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// Bytes32ToUintMap
struct Bytes32ToUintMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToUintMap storage map, bytes32 key, uint256 value) internal returns (bool) {
return set(map._inner, key, bytes32(value));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToUintMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToUintMap storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToUintMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToUintMap storage map, uint256 index) internal view returns (bytes32 key, uint256 value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (atKey, uint256(val));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToUintMap storage map, bytes32 key) internal view returns (bool exists, uint256 value) {
(bool success, bytes32 val) = tryGet(map._inner, key);
return (success, uint256(val));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToUintMap storage map, bytes32 key) internal view returns (uint256) {
return uint256(get(map._inner, key));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToUintMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// Bytes32ToAddressMap
struct Bytes32ToAddressMap {
Bytes32ToBytes32Map _inner;
}
/**
* @dev Adds a key-value pair to a map, or updates the value for an existing
* key. O(1).
*
* Returns true if the key was added to the map, that is if it was not
* already present.
*/
function set(Bytes32ToAddressMap storage map, bytes32 key, address value) internal returns (bool) {
return set(map._inner, key, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a map. O(1).
*
* Returns true if the key was removed from the map, that is if it was present.
*/
function remove(Bytes32ToAddressMap storage map, bytes32 key) internal returns (bool) {
return remove(map._inner, key);
}
/**
* @dev Removes all the entries from a map. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the map grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32ToAddressMap storage map) internal {
clear(map._inner);
}
/**
* @dev Returns true if the key is in the map. O(1).
*/
function contains(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool) {
return contains(map._inner, key);
}
/**
* @dev Returns the number of elements in the map. O(1).
*/
function length(Bytes32ToAddressMap storage map) internal view returns (uint256) {
return length(map._inner);
}
/**
* @dev Returns the element stored at position `index` in the map. O(1).
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32ToAddressMap storage map, uint256 index) internal view returns (bytes32 key, address value) {
(bytes32 atKey, bytes32 val) = at(map._inner, index);
return (atKey, address(uint160(uint256(val))));
}
/**
* @dev Tries to returns the value associated with `key`. O(1).
* Does not revert if `key` is not in the map.
*/
function tryGet(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (bool exists, address value) {
(bool success, bytes32 val) = tryGet(map._inner, key);
return (success, address(uint160(uint256(val))));
}
/**
* @dev Returns the value associated with `key`. O(1).
*
* Requirements:
*
* - `key` must be in the map.
*/
function get(Bytes32ToAddressMap storage map, bytes32 key) internal view returns (address) {
return address(uint160(uint256(get(map._inner, key))));
}
/**
* @dev Return the an array containing all the keys
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the map grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function keys(Bytes32ToAddressMap storage map) internal view returns (bytes32[] memory) {
bytes32[] memory store = keys(map._inner);
bytes32[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.14; //for (bugfixed) support of `using ... global;` syntax for libraries
import {IWormhole} from "wormhole-sdk/interfaces/IWormhole.sol";
import {BytesParsing} from "wormhole-sdk/libraries/BytesParsing.sol";
import {
toUniversalAddress,
keccak256Cd,
keccak256Word,
keccak256SliceUnchecked
} from "wormhole-sdk/Utils.sol";
// ╭─────────────────────────────────────────────────╮
// │ Library for encoding and decoding Wormhole VAAs │
// ╰─────────────────────────────────────────────────╯
// # VAA Format
//
// see:
// * ../interfaces/IWormhole.sol VM struct (VM = Verified Message)
// * [CoreBridge](https://github.com/wormhole-foundation/wormhole/blob/c35940ae9689f6df9e983d51425763509b74a80f/ethereum/contracts/Messages.sol#L147)
// * [Typescript SDK](https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/3cd10030b5e924f0621c7231e24410b8a0946a07/core/definitions/src/vaa/vaa.ts#L32-L51)
//
// ╭──────────┬──────────────────────────────────────────────────────────────────────────────╮
// │ Section │ Description │
// ├──────────┼──────────────────────────────────────────────────────────────────────────────┤
// │ Header │ version, guardian signature info required to verify the VAA │
// │ Envelope │ contains metadata of the emitted message, such as emitter or timestamp │
// │ Payload │ the emitted message, raw bytes, no length prefix, consumes remainder of data │
// ╰──────────┴──────────────────────────────────────────────────────────────────────────────╯
// Body = Envelope + Payload
// The VAA body is exactly the information that goes into a published message of the CoreBridge
// and is what gets keccak256-hashed when calculating the VAA hash (i.e. the header is excluded).
//
// Note:
// Guardians do _not_ sign the body directly, but rather the hash of the body, i.e. from the PoV
// of a guardian, the message itself is already only a hash.
// But [the first step of the ECDSA signature scheme](https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm#Signature_generation_algorithm)
// is to hash the message, leading to the hash being hashed a second time when signing.
// Likewise, ecrecover also operates on the hash of the message, rather than the message itself.
// This means that when verifying guardian signatures of a VAA, the hash that must be passed to
// ecrecover is the doubly-hashed body.
//
// ╭─────────────────────────────────────── WARNING ───────────────────────────────────────╮
// │ There is an unfortunate inconsistency between the implementation of the CoreBridge on │
// │ EVM, where IWormhole.VM.hash is the *doubly* hashed body [1], while everything else │
// │ only uses the singly-hashed body (see Solana CoreBridge [2] and Typescript SDK [3]) │
// ╰───────────────────────────────────────────────────────────────────────────────────────╯
// [1] https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/ethereum/contracts/Messages.sol#L178-L186
// [2] https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/solana/bridge/program/src/api/post_vaa.rs#L214C4-L244
// [3] https://github.com/wormhole-foundation/wormhole-sdk-ts/blob/3cd10030b5e924f0621c7231e24410b8a0946a07/core/definitions/src/vaa/functions.ts#L189
//
// ## Format in Detail
//
// ╭─────────────┬──────────────────┬──────────────────────────────────────────────────────────────╮
// │ Type │ Name │ Description │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │ Header │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │ uint8 │ version │ fixed value of 1 (see HEADER_VERSION below) │
// │ uint32 │ guardianSetIndex │ the guardian set that signed the VAA │
// │ uint8 │ signatureCount │ must be greater than guardian set size * 2 / 3 for quorum │
// │ Signature[] │ signatures │ signatures of the guardians that signed the VAA │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │ Signature │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │ uint8 │ guardianIndex │ position of the signing guardian in the guardian set │
// │ bytes32 │ r │ ECDSA r value │
// │ bytes32 │ s │ ECDSA s value │
// │ uint8 │ v │ encoded: 0/1, decoded: 27/28, see SIGNATURE_RECOVERY_MAGIC │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │ Envelope │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │ uint32 │ timestamp │ unix timestamp of block containing the emitted message │
// │ uint32 │ nonce │ user-defined nonce │
// │ uint16 │ emitterChainId │ Wormhole (not EVM) chain id of the emitter │
// │ bytes32 │ emitterAddress │ universal address of the emitter │
// │ uint64 │ sequence │ sequence number of the message (counter per emitter) │
// │ uint8 │ consistencyLevel │ https://wormhole.com/docs/build/reference/consistency-levels │
// ┝━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┥
// │ Payload │
// ├─────────────┬──────────────────┬──────────────────────────────────────────────────────────────┤
// │ bytes │ payload │ emitted message, consumes rest of VAA (no length prefix) │
// ╰─────────────┴──────────────────┴──────────────────────────────────────────────────────────────╯
//
// # Library
//
// This library is built on top of BytesParsing which is a lot more gas efficient than BytesLib,
// which is used in the CoreBridge.
//
// It also provides decoding functions for parsing the individual components of the VAA separately
// and returning them on the stack, rather than as a struct which requires memory allocation.
//
// ## Library Functions & Naming Conventions
//
// All library functions come in 2 flavors:
// 1. Calldata (using the Cd tag)
// 2. Memory (using the Mem tag)
//
// Additionally, most functions also have an additional struct flavor that returns the decoded
// values in the associated struct (in memory), rather than as individual values (on the stack).
//
// The parameter name `encodedVaa` is used for functions where the bytes are expected to contain
// a single, full VAA. Otherwise, i.e. for partials or multiple VAAs, the name `encoded` is used.
//
// Like in BytesParsing, the Unchecked function name suffix does not refer to Solidity's `unchecked`
// keyword, but rather to the fact that no bounds checking is performed. All math is done using
// unchecked arithmetic because overflows are impossible due to the nature of the VAA format,
// while we explicitly check for underflows where necessary.
//
// Function names, somewhat redundantly, contain the tag "Vaa" to add clarity and avoid potential
// name collisions when using the library with a `using ... for bytes` directive.
//
// Function Base Name │ Description
// ─────────────────────┼────────────────────────────────────────────────────────────────────────
// decodeVmStruct │ decodes a legacy VM struct (no non-struct flavor available)
// decodeVaaEssentials │ decodes the emitter, sequence, and payload
// decodeVaaBody │ decodes the envelope and payload
// checkVaaVersion │
// skipVaaHeader │ returns the offset to the envelope
// calcVaaSingleHash │ see explanation/WARNING box at the top
// calcVaaDoubleHash │ see explanation/WARNING box at the top
// decodeVaaEnvelope │
// decodeVaaPayload │
//
// encode functions (for testing, converts back into serialized byte array format):
// * encode (overloaded for each struct)
// * encodeVaaHeader
// * encodeVaaEnvelope
// * encodeVaaBody
// * encodeVaa
//
// other functions:
// * asIWormholeSignatures (casting between GuardianSignature and IWormhole.Signature)
// * asGuardianSignatures (casting between GuardianSignature and IWormhole.Signature)
//Annoyingly, Solidity only allows aliasing of types that are exported on the file level, but not
// of nested types, see [language grammar](https://docs.soliditylang.org/en/v0.8.28/grammar.html#a4.SolidityParser.importDirective)
//So we (re)define GuardianSignature identically to IWormhole.Signature to avoid the explicit
// dependency and to provide a better name and do the necessary casts manually using assembly.
//Without the alias, users who want to reference the GuardianSignature type would have to import
// IWormhole themselves, which breaks the intended encapsulation of this library.
struct GuardianSignature {
bytes32 r;
bytes32 s;
uint8 v;
uint8 guardianIndex;
}
struct VaaHeader {
//uint8 version;
uint32 guardianSetIndex;
GuardianSignature[] signatures;
}
struct VaaEnvelope {
uint32 timestamp;
uint32 nonce;
uint16 emitterChainId;
bytes32 emitterAddress;
uint64 sequence;
uint8 consistencyLevel;
}
struct VaaBody {
VaaEnvelope envelope;
bytes payload;
}
struct Vaa {
VaaHeader header;
VaaEnvelope envelope;
bytes payload;
}
struct VaaEssentials {
uint16 emitterChainId;
bytes32 emitterAddress;
uint64 sequence;
bytes payload;
}
library VaaLib {
using BytesParsing for bytes;
using {BytesParsing.checkBound} for uint;
error InvalidVersion(uint8 version);
uint8 internal constant HEADER_VERSION = 1;
//see https://github.com/wormhole-foundation/wormhole/blob/c35940ae9689f6df9e983d51425763509b74a80f/ethereum/contracts/Messages.sol#L174
//origin: https://bitcoin.stackexchange.com/a/102382
uint8 internal constant SIGNATURE_RECOVERY_MAGIC = 27;
//the following offsets are provided for more eclectic, manual parsing
uint internal constant HEADER_VERSION_OFFSET = 0;
uint internal constant HEADER_VERSION_SIZE = 1;
uint internal constant HEADER_GUARDIAN_SET_INDEX_OFFSET =
HEADER_VERSION_OFFSET + HEADER_VERSION_SIZE;
uint internal constant HEADER_GUARDIAN_SET_INDEX_SIZE = 4;
uint internal constant HEADER_SIGNATURE_COUNT_OFFSET =
HEADER_GUARDIAN_SET_INDEX_OFFSET + HEADER_GUARDIAN_SET_INDEX_SIZE;
uint internal constant HEADER_SIGNATURE_COUNT_SIZE = 1;
uint internal constant HEADER_SIGNATURE_ARRAY_OFFSET =
HEADER_SIGNATURE_COUNT_OFFSET + HEADER_SIGNATURE_COUNT_SIZE;
uint internal constant GUARDIAN_SIGNATURE_GUARDIAN_INDEX_OFFSET = 0;
uint internal constant GUARDIAN_SIGNATURE_GUARDIAN_INDEX_SIZE = 1;
uint internal constant GUARDIAN_SIGNATURE_R_OFFSET =
GUARDIAN_SIGNATURE_GUARDIAN_INDEX_OFFSET + GUARDIAN_SIGNATURE_GUARDIAN_INDEX_SIZE;
uint internal constant GUARDIAN_SIGNATURE_R_SIZE = 32;
uint internal constant GUARDIAN_SIGNATURE_S_OFFSET =
GUARDIAN_SIGNATURE_R_OFFSET + GUARDIAN_SIGNATURE_R_SIZE;
uint internal constant GUARDIAN_SIGNATURE_S_SIZE = 32;
uint internal constant GUARDIAN_SIGNATURE_V_OFFSET =
GUARDIAN_SIGNATURE_S_OFFSET + GUARDIAN_SIGNATURE_S_SIZE;
uint internal constant GUARDIAN_SIGNATURE_V_SIZE = 1;
uint internal constant GUARDIAN_SIGNATURE_SIZE =
GUARDIAN_SIGNATURE_V_OFFSET + GUARDIAN_SIGNATURE_V_SIZE;
uint internal constant ENVELOPE_TIMESTAMP_OFFSET = 0;
uint internal constant ENVELOPE_TIMESTAMP_SIZE = 4;
uint internal constant ENVELOPE_NONCE_OFFSET =
ENVELOPE_TIMESTAMP_OFFSET + ENVELOPE_TIMESTAMP_SIZE;
uint internal constant ENVELOPE_NONCE_SIZE = 4;
uint internal constant ENVELOPE_EMITTER_CHAIN_ID_OFFSET =
ENVELOPE_NONCE_OFFSET + ENVELOPE_NONCE_SIZE;
uint internal constant ENVELOPE_EMITTER_CHAIN_ID_SIZE = 2;
uint internal constant ENVELOPE_EMITTER_ADDRESS_OFFSET =
ENVELOPE_EMITTER_CHAIN_ID_OFFSET + ENVELOPE_EMITTER_CHAIN_ID_SIZE;
uint internal constant ENVELOPE_EMITTER_ADDRESS_SIZE = 32;
uint internal constant ENVELOPE_SEQUENCE_OFFSET =
ENVELOPE_EMITTER_ADDRESS_OFFSET + ENVELOPE_EMITTER_ADDRESS_SIZE;
uint internal constant ENVELOPE_SEQUENCE_SIZE = 8;
uint internal constant ENVELOPE_CONSISTENCY_LEVEL_OFFSET =
ENVELOPE_SEQUENCE_OFFSET + ENVELOPE_SEQUENCE_SIZE;
uint internal constant ENVELOPE_CONSISTENCY_LEVEL_SIZE = 1;
uint internal constant ENVELOPE_SIZE =
ENVELOPE_CONSISTENCY_LEVEL_OFFSET + ENVELOPE_CONSISTENCY_LEVEL_SIZE;
// ------------ Convenience Decoding Functions ------------
//legacy decoder for IWormhole.VM
function decodeVmStructCd(
bytes calldata encodedVaa
) internal pure returns (IWormhole.VM memory vm) {
vm.version = HEADER_VERSION;
uint envelopeOffset;
GuardianSignature[] memory signatures;
(vm.guardianSetIndex, signatures, envelopeOffset) = decodeVaaHeaderCdUnchecked(encodedVaa);
vm.signatures = asIWormholeSignatures(signatures);
vm.hash = calcVaaDoubleHashCd(encodedVaa, envelopeOffset);
( vm.timestamp,
vm.nonce,
vm.emitterChainId,
vm.emitterAddress,
vm.sequence,
vm.consistencyLevel,
vm.payload
) = decodeVaaBodyCd(encodedVaa, envelopeOffset);
}
function decodeVmStructMem(
bytes memory encodedVaa
) internal pure returns (IWormhole.VM memory vm) {
(vm, ) = decodeVmStructMemUnchecked(encodedVaa, 0, encodedVaa.length);
}
function decodeVaaStructCd(
bytes calldata encodedVaa
) internal pure returns (Vaa memory vaa) {
uint envelopeOffset;
(vaa.header, envelopeOffset) = decodeVaaHeaderStructCdUnchecked(encodedVaa);
uint payloadOffset;
(vaa.envelope, payloadOffset) = decodeVaaEnvelopeStructCdUnchecked(encodedVaa, envelopeOffset);
vaa.payload = decodeVaaPayloadCd(encodedVaa, payloadOffset);
}
function decodeVaaStructMem(
bytes memory encodedVaa
) internal pure returns (Vaa memory vaa) {
(vaa, ) = decodeVaaStructMemUnchecked(encodedVaa, 0, encodedVaa.length);
}
function decodeVaaEssentialsCd(
bytes calldata encodedVaa
) internal pure returns (
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
bytes calldata payload
) { unchecked {
checkVaaVersionCd(encodedVaa);
uint envelopeOffset = skipVaaHeaderCd(encodedVaa);
uint offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
(emitterChainId, offset) = encodedVaa.asUint16CdUnchecked(offset);
(emitterAddress, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(sequence, ) = encodedVaa.asUint64CdUnchecked(offset);
uint payloadOffset = envelopeOffset + ENVELOPE_SIZE;
payload = decodeVaaPayloadCd(encodedVaa, payloadOffset);
}}
function decodeVaaEssentialsStructCd(
bytes calldata encodedVaa
) internal pure returns (VaaEssentials memory ret) {
(ret.emitterChainId, ret.emitterAddress, ret.sequence, ret.payload) =
decodeVaaEssentialsCd(encodedVaa);
}
//The returned values are considered the essentials because it's important to check the emitter
// to avoid spoofing. Also, VAAs that use finalized consistency levels should leverage the
// sequence number (on a per emitter basis!) and a bitmap for replay protection rather than the
// hashed body because it is more gas efficient (storage slot is likely already dirty).
function decodeVaaEssentialsMem(
bytes memory encodedVaa
) internal pure returns (
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
bytes memory payload
) {
(emitterChainId, emitterAddress, sequence, payload, ) =
decodeVaaEssentialsMem(encodedVaa, 0, encodedVaa.length);
}
function decodeVaaEssentialsStructMem(
bytes memory encodedVaa
) internal pure returns (VaaEssentials memory ret) {
(ret.emitterChainId, ret.emitterAddress, ret.sequence, ret.payload, ) =
decodeVaaEssentialsMem(encodedVaa, 0, encodedVaa.length);
}
function decodeVaaEssentialsMem(
bytes memory encoded,
uint headerOffset,
uint vaaLength
) internal pure returns (
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
bytes memory payload,
uint newOffset
) { unchecked {
uint offset = checkVaaVersionMemUnchecked(encoded, headerOffset);
uint envelopeOffset = skipVaaHeaderMemUnchecked(encoded, offset);
offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
(emitterChainId, offset) = encoded.asUint16MemUnchecked(offset);
(emitterAddress, offset) = encoded.asBytes32MemUnchecked(offset);
(sequence, ) = encoded.asUint64MemUnchecked(offset);
uint payloadOffset = envelopeOffset + ENVELOPE_SIZE;
(payload, newOffset) = decodeVaaPayloadMemUnchecked(encoded, payloadOffset, vaaLength);
}}
function decodeVaaEssentialsStructMem(
bytes memory encodedVaa,
uint headerOffset,
uint vaaLength
) internal pure returns (VaaEssentials memory ret, uint newOffset) {
(ret.emitterChainId, ret.emitterAddress, ret.sequence, ret.payload, newOffset) =
decodeVaaEssentialsMem(encodedVaa, headerOffset, vaaLength);
}
function decodeVaaBodyCd(
bytes calldata encodedVaa
) internal pure returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes calldata payload
) {
checkVaaVersionCd(encodedVaa);
(timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payload) =
decodeVaaBodyCd(encodedVaa, skipVaaHeaderCd(encodedVaa));
}
function decodeVaaBodyStructCd(
bytes calldata encodedVaa
) internal pure returns (VaaBody memory body) {
( body.envelope.timestamp,
body.envelope.nonce,
body.envelope.emitterChainId,
body.envelope.emitterAddress,
body.envelope.sequence,
body.envelope.consistencyLevel,
body.payload
) = decodeVaaBodyCd(encodedVaa);
}
function decodeVaaBodyMem(
bytes memory encodedVaa
) internal pure returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes memory payload
) {
checkVaaVersionMemUnchecked(encodedVaa, 0);
uint envelopeOffset = skipVaaHeaderMemUnchecked(encodedVaa, 0);
(timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payload, ) =
decodeVaaBodyMemUnchecked(encodedVaa, envelopeOffset, encodedVaa.length);
}
function decodeVaaBodyStructMem(
bytes memory encodedVaa
) internal pure returns (VaaBody memory body) {
( body.envelope.timestamp,
body.envelope.nonce,
body.envelope.emitterChainId,
body.envelope.emitterAddress,
body.envelope.sequence,
body.envelope.consistencyLevel,
body.payload,
) = decodeVaaBodyMemUnchecked(encodedVaa, 0, encodedVaa.length);
}
// Convinience decoding function for token bridge Vaas
function decodeEmitterChainAndPayloadCdUnchecked(
bytes calldata encodedVaa
) internal pure returns (uint16 emitterChainId, bytes calldata payload) { unchecked {
checkVaaVersionCd(encodedVaa);
uint envelopeOffset = skipVaaHeaderCd(encodedVaa);
uint offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
(emitterChainId, offset) = encodedVaa.asUint16CdUnchecked(offset);
offset += ENVELOPE_EMITTER_ADDRESS_SIZE + ENVELOPE_SEQUENCE_SIZE + ENVELOPE_CONSISTENCY_LEVEL_SIZE;
payload = decodeVaaPayloadCd(encodedVaa, offset);
}}
function decodeEmitterChainAndPayloadMemUnchecked(
bytes memory encodedVaa
) internal pure returns (uint16 emitterChainId, bytes memory payload) { unchecked {
checkVaaVersionMemUnchecked(encodedVaa, 0);
uint envelopeOffset = skipVaaHeaderMemUnchecked(encodedVaa, 0);
uint offset = envelopeOffset + ENVELOPE_EMITTER_CHAIN_ID_OFFSET;
(emitterChainId, offset) = encodedVaa.asUint16MemUnchecked(offset);
offset += ENVELOPE_EMITTER_ADDRESS_SIZE + ENVELOPE_SEQUENCE_SIZE + ENVELOPE_CONSISTENCY_LEVEL_SIZE;
(payload, ) = decodeVaaPayloadMemUnchecked(encodedVaa, offset, encodedVaa.length);
}}
// ------------ Advanced Decoding Functions ------------
function asIWormholeSignatures(
GuardianSignature[] memory signatures
) internal pure returns (IWormhole.Signature[] memory vmSignatures) {
assembly ("memory-safe") {
vmSignatures := signatures
}
}
function asGuardianSignatures(
IWormhole.Signature[] memory vmSignatures
) internal pure returns (GuardianSignature[] memory signatures) {
assembly ("memory-safe") {
signatures := vmSignatures
}
}
function checkVaaVersionCd(bytes calldata encodedVaa) internal pure returns (uint newOffset) {
uint8 version;
(version, newOffset) = encodedVaa.asUint8CdUnchecked(0);
checkVaaVersion(version);
}
function checkVaaVersionMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint newOffset) {
uint8 version;
(version, newOffset) = encoded.asUint8MemUnchecked(offset);
checkVaaVersion(version);
}
function checkVaaVersion(uint8 version) internal pure {
if (version != HEADER_VERSION)
revert InvalidVersion(version);
}
//return the offset to the start of the envelope/body
function skipVaaHeaderCd(
bytes calldata encodedVaa
) internal pure returns (uint envelopeOffset) { unchecked {
(uint sigCount, uint offset) = encodedVaa.asUint8CdUnchecked(HEADER_SIGNATURE_COUNT_OFFSET);
envelopeOffset = offset + sigCount * GUARDIAN_SIGNATURE_SIZE;
}}
function skipVaaHeaderMemUnchecked(
bytes memory encoded,
uint headerOffset
) internal pure returns (uint envelopeOffset) { unchecked {
uint offset = headerOffset + HEADER_SIGNATURE_COUNT_OFFSET;
uint sigCount;
(sigCount, offset) = encoded.asUint8MemUnchecked(offset);
envelopeOffset = offset + sigCount * GUARDIAN_SIGNATURE_SIZE;
}}
//see WARNING box at the top
function calcVaaSingleHashCd(
bytes calldata encodedVaa,
uint envelopeOffset
) internal pure returns (bytes32) {
return keccak256Cd(_decodeRemainderCd(encodedVaa, envelopeOffset));
}
//see WARNING box at the top
function calcVaaSingleHashMem(
bytes memory encoded,
uint envelopeOffset,
uint vaaLength
) internal pure returns (bytes32) { unchecked {
envelopeOffset.checkBound(vaaLength);
return keccak256SliceUnchecked(encoded, envelopeOffset, vaaLength - envelopeOffset);
}}
//see WARNING box at the top
function calcSingleHash(Vaa memory vaa) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(encode(vaa.envelope), vaa.payload));
}
//see WARNING box at the top
function calcSingleHash(VaaBody memory body) internal pure returns (bytes32) {
return keccak256(encode(body));
}
//see WARNING box at the top
//this function matches IWormhole.VM.hash and is what's been used for (legacy) replay protection
function calcVaaDoubleHashCd(
bytes calldata encodedVaa,
uint envelopeOffset
) internal pure returns (bytes32) {
return keccak256Word(calcVaaSingleHashCd(encodedVaa, envelopeOffset));
}
//see WARNING box at the top
function calcVaaDoubleHashMem(
bytes memory encoded,
uint envelopeOffset,
uint vaaLength
) internal pure returns (bytes32) {
return keccak256Word(calcVaaSingleHashMem(encoded, envelopeOffset, vaaLength));
}
//see WARNING box at the top
function calcDoubleHash(Vaa memory vaa) internal pure returns (bytes32) {
return keccak256Word(calcSingleHash(vaa));
}
//see WARNING box at the top
function calcDoubleHash(VaaBody memory body) internal pure returns (bytes32) {
return keccak256Word(calcSingleHash(body));
}
function decodeVmStructMemUnchecked(
bytes memory encoded,
uint headerOffset,
uint vaaLength
) internal pure returns (IWormhole.VM memory vm, uint newOffset) {
vm.version = HEADER_VERSION;
uint envelopeOffset;
GuardianSignature[] memory signatures;
(vm.guardianSetIndex, signatures, envelopeOffset) =
decodeVaaHeaderMemUnchecked(encoded, headerOffset);
vm.signatures = asIWormholeSignatures(signatures);
vm.hash = calcVaaDoubleHashMem(encoded, envelopeOffset, vaaLength);
( vm.timestamp,
vm.nonce,
vm.emitterChainId,
vm.emitterAddress,
vm.sequence,
vm.consistencyLevel,
vm.payload,
newOffset
) = decodeVaaBodyMemUnchecked(encoded, envelopeOffset, vaaLength);
}
function decodeVaaStructMemUnchecked(
bytes memory encoded,
uint headerOffset,
uint vaaLength
) internal pure returns (Vaa memory vaa, uint newOffset) {
uint envelopeOffset;
(vaa.header.guardianSetIndex, vaa.header.signatures, envelopeOffset) =
decodeVaaHeaderMemUnchecked(encoded, headerOffset);
uint payloadOffset;
(vaa.envelope, payloadOffset) = decodeVaaEnvelopeStructMemUnchecked(encoded, envelopeOffset);
(vaa.payload, newOffset) = decodeVaaPayloadMemUnchecked(encoded, payloadOffset, vaaLength);
}
function decodeVaaBodyCd(
bytes calldata encodedVaa,
uint envelopeOffset
) internal pure returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes calldata payload
) {
uint payloadOffset;
(timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payloadOffset) =
decodeVaaEnvelopeCdUnchecked(encodedVaa, envelopeOffset);
payload = decodeVaaPayloadCd(encodedVaa, payloadOffset);
}
function decodeVaaBodyStructCd(
bytes calldata encodedVaa,
uint envelopeOffset
) internal pure returns (VaaBody memory body) {
( body.envelope.timestamp,
body.envelope.nonce,
body.envelope.emitterChainId,
body.envelope.emitterAddress,
body.envelope.sequence,
body.envelope.consistencyLevel,
body.payload
) = decodeVaaBodyCd(encodedVaa, envelopeOffset);
}
function decodeVaaBodyMemUnchecked(
bytes memory encoded,
uint envelopeOffset,
uint vaaLength
) internal pure returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes memory payload,
uint newOffset
) {
uint payloadOffset;
(timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payloadOffset) =
decodeVaaEnvelopeMemUnchecked(encoded, envelopeOffset);
(payload, newOffset) = decodeVaaPayloadMemUnchecked(encoded, payloadOffset, vaaLength);
}
function decodeVaaBodyStructMemUnchecked(
bytes memory encoded,
uint envelopeOffset,
uint vaaLength
) internal pure returns (VaaBody memory body, uint newOffset) {
( body.envelope.timestamp,
body.envelope.nonce,
body.envelope.emitterChainId,
body.envelope.emitterAddress,
body.envelope.sequence,
body.envelope.consistencyLevel,
body.payload,
newOffset
) = decodeVaaBodyMemUnchecked(encoded, envelopeOffset, vaaLength);
}
function decodeVaaEnvelopeCdUnchecked(
bytes calldata encodedVaa,
uint envelopeOffset
) internal pure returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
uint payloadOffset
) {
uint offset = envelopeOffset;
(timestamp, offset) = encodedVaa.asUint32CdUnchecked(offset);
(nonce, offset) = encodedVaa.asUint32CdUnchecked(offset);
(emitterChainId, offset) = encodedVaa.asUint16CdUnchecked(offset);
(emitterAddress, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(sequence, offset) = encodedVaa.asUint64CdUnchecked(offset);
(consistencyLevel, offset) = encodedVaa.asUint8CdUnchecked(offset);
payloadOffset = offset;
}
function decodeVaaEnvelopeStructCdUnchecked(
bytes calldata encodedVaa,
uint envelopeOffset
) internal pure returns (VaaEnvelope memory envelope, uint payloadOffset) {
( envelope.timestamp,
envelope.nonce,
envelope.emitterChainId,
envelope.emitterAddress,
envelope.sequence,
envelope.consistencyLevel,
payloadOffset
) = decodeVaaEnvelopeCdUnchecked(encodedVaa, envelopeOffset);
}
function decodeVaaEnvelopeMemUnchecked(
bytes memory encoded,
uint envelopeOffset
) internal pure returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
uint payloadOffset
) {
uint offset = envelopeOffset;
(timestamp, offset) = encoded.asUint32MemUnchecked(offset);
(nonce, offset) = encoded.asUint32MemUnchecked(offset);
(emitterChainId, offset) = encoded.asUint16MemUnchecked(offset);
(emitterAddress, offset) = encoded.asBytes32MemUnchecked(offset);
(sequence, offset) = encoded.asUint64MemUnchecked(offset);
(consistencyLevel, offset) = encoded.asUint8MemUnchecked(offset);
payloadOffset = offset;
}
function decodeVaaEnvelopeStructMemUnchecked(
bytes memory encoded,
uint envelopeOffset
) internal pure returns (VaaEnvelope memory envelope, uint payloadOffset) {
( envelope.timestamp,
envelope.nonce,
envelope.emitterChainId,
envelope.emitterAddress,
envelope.sequence,
envelope.consistencyLevel,
payloadOffset
) = decodeVaaEnvelopeMemUnchecked(encoded, envelopeOffset);
}
function decodeVaaHeaderCdUnchecked(
bytes calldata encodedVaa
) internal pure returns (
uint32 guardianSetIndex,
GuardianSignature[] memory signatures,
uint envelopeOffset
) { unchecked {
checkVaaVersionCd(encodedVaa);
uint offset = HEADER_GUARDIAN_SET_INDEX_OFFSET;
(guardianSetIndex, offset) = encodedVaa.asUint32CdUnchecked(offset);
uint signersLen;
(signersLen, offset) = encodedVaa.asUint8CdUnchecked(offset);
signatures = new GuardianSignature[](signersLen);
for (uint i = 0; i < signersLen; ++i)
(signatures[i], offset) = decodeGuardianSignatureStructCdUnchecked(encodedVaa, offset);
envelopeOffset = offset;
}}
function decodeVaaHeaderStructCdUnchecked(
bytes calldata encodedVaa
) internal pure returns (VaaHeader memory header, uint envelopeOffset) {
( header.guardianSetIndex,
header.signatures,
envelopeOffset
) = decodeVaaHeaderCdUnchecked(encodedVaa);
}
function decodeVaaHeaderMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (
uint32 guardianSetIndex,
GuardianSignature[] memory signatures,
uint envelopeOffset
) { unchecked {
offset = checkVaaVersionMemUnchecked(encoded, offset);
(guardianSetIndex, offset) = encoded.asUint32MemUnchecked(offset);
uint signersLen;
(signersLen, offset) = encoded.asUint8MemUnchecked(offset);
signatures = new GuardianSignature[](signersLen);
for (uint i = 0; i < signersLen; ++i)
(signatures[i], offset) = decodeGuardianSignatureStructMemUnchecked(encoded, offset);
envelopeOffset = offset;
}}
function decodeVaaHeaderStructMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (VaaHeader memory header, uint envelopeOffset) {
( header.guardianSetIndex,
header.signatures,
envelopeOffset
) = decodeVaaHeaderMemUnchecked(encoded, offset);
}
function decodeGuardianSignatureCdUnchecked(
bytes calldata encodedVaa,
uint offset
) internal pure returns (
uint8 guardianIndex,
bytes32 r,
bytes32 s,
uint8 v,
uint newOffset
) { unchecked {
(guardianIndex, offset) = encodedVaa.asUint8CdUnchecked(offset);
(r, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(s, offset) = encodedVaa.asBytes32CdUnchecked(offset);
(v, offset) = encodedVaa.asUint8CdUnchecked(offset);
v += SIGNATURE_RECOVERY_MAGIC;
newOffset = offset;
}}
function decodeGuardianSignatureStructCdUnchecked(
bytes calldata encodedVaa,
uint offset
) internal pure returns (GuardianSignature memory ret, uint newOffset) {
(ret.guardianIndex, ret.r, ret.s, ret.v, newOffset) =
decodeGuardianSignatureCdUnchecked(encodedVaa, offset);
}
function decodeGuardianSignatureMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (
uint8 guardianIndex,
bytes32 r,
bytes32 s,
uint8 v,
uint newOffset
) { unchecked {
(guardianIndex, offset) = encoded.asUint8MemUnchecked(offset);
(r, offset) = encoded.asBytes32MemUnchecked(offset);
(s, offset) = encoded.asBytes32MemUnchecked(offset);
(v, offset) = encoded.asUint8MemUnchecked(offset);
v += SIGNATURE_RECOVERY_MAGIC;
newOffset = offset;
}}
function decodeGuardianSignatureStructMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (GuardianSignature memory ret, uint newOffset) {
(ret.guardianIndex, ret.r, ret.s, ret.v, newOffset) =
decodeGuardianSignatureMemUnchecked(encoded, offset);
}
function decodeVaaPayloadCd(
bytes calldata encodedVaa,
uint payloadOffset
) internal pure returns (bytes calldata payload) {
payload = _decodeRemainderCd(encodedVaa, payloadOffset);
}
function decodeVaaPayloadMemUnchecked(
bytes memory encoded,
uint payloadOffset,
uint vaaLength
) internal pure returns (bytes memory payload, uint newOffset) { unchecked {
//check to avoid underflow in following subtraction
payloadOffset.checkBound(vaaLength);
(payload, newOffset) = encoded.sliceMemUnchecked(payloadOffset, vaaLength - payloadOffset);
}}
// ------------ Encoding ------------
function encode(IWormhole.VM memory vm) internal pure returns (bytes memory) { unchecked {
require(vm.version == HEADER_VERSION, "Invalid version");
return abi.encodePacked(
encodeVaaHeader(vm.guardianSetIndex, asGuardianSignatures(vm.signatures)),
vm.timestamp,
vm.nonce,
vm.emitterChainId,
vm.emitterAddress,
vm.sequence,
vm.consistencyLevel,
vm.payload
);
}}
function encodeVaaHeader(
uint32 guardianSetIndex,
GuardianSignature[] memory signatures
) internal pure returns (bytes memory) {
bytes memory sigs;
for (uint i = 0; i < signatures.length; ++i) {
GuardianSignature memory sig = signatures[i];
uint8 v = sig.v - SIGNATURE_RECOVERY_MAGIC; //deliberately checked
sigs = bytes.concat(sigs, abi.encodePacked(sig.guardianIndex, sig.r, sig.s, v));
}
return abi.encodePacked(
HEADER_VERSION,
guardianSetIndex,
uint8(signatures.length),
sigs
);
}
function encode(VaaHeader memory header) internal pure returns (bytes memory) {
return encodeVaaHeader(header.guardianSetIndex, header.signatures);
}
function encodeVaaEnvelope(
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel
) internal pure returns (bytes memory) {
return abi.encodePacked(
timestamp,
nonce,
emitterChainId,
emitterAddress,
sequence,
consistencyLevel
);
}
function encode(VaaEnvelope memory envelope) internal pure returns (bytes memory) {
return encodeVaaEnvelope(
envelope.timestamp,
envelope.nonce,
envelope.emitterChainId,
envelope.emitterAddress,
envelope.sequence,
envelope.consistencyLevel
);
}
function encodeVaaBody(
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes memory payload
) internal pure returns (bytes memory) {
return abi.encodePacked(
encodeVaaEnvelope(
timestamp,
nonce,
emitterChainId,
emitterAddress,
sequence,
consistencyLevel
),
payload
);
}
function encode(VaaBody memory body) internal pure returns (bytes memory) {
return abi.encodePacked(encode(body.envelope), body.payload);
}
function encodeVaa(
uint32 guardianSetIndex,
GuardianSignature[] memory signatures,
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes memory payload
) internal pure returns (bytes memory) {
return abi.encodePacked(
encodeVaaHeader(guardianSetIndex, signatures),
encodeVaaBody(
timestamp,
nonce,
emitterChainId,
emitterAddress,
sequence,
consistencyLevel,
payload
)
);
}
function encode(Vaa memory vaa) internal pure returns (bytes memory) {
return encodeVaa(
vaa.header.guardianSetIndex,
vaa.header.signatures,
vaa.envelope.timestamp,
vaa.envelope.nonce,
vaa.envelope.emitterChainId,
vaa.envelope.emitterAddress,
vaa.envelope.sequence,
vaa.envelope.consistencyLevel,
vaa.payload
);
}
// ------------ Private ------------
//we use this function over encodedVaa[offset:] to consistently get BytesParsing errors
function _decodeRemainderCd(
bytes calldata encodedVaa,
uint offset
) private pure returns (bytes calldata remainder) { unchecked {
//check to avoid underflow in following subtraction
offset.checkBound(encodedVaa.length);
(remainder, ) = encodedVaa.sliceCdUnchecked(offset, encodedVaa.length - offset);
}}
}
using VaaLib for VaaHeader global;
using VaaLib for VaaEnvelope global;
using VaaLib for VaaBody global;
using VaaLib for Vaa global;// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
import {IBridgeController} from "./IBridgeController.sol";
import {IMakinaGovernable} from "./IMakinaGovernable.sol";
interface IMachineEndpoint is IBridgeController, IMakinaGovernable {
/// @notice Manages the transfer of tokens between a machine and a caliber. The transfer direction depends on the caller.
/// @param token The address of the token.
/// @param amount The amount of tokens to transfer.
/// @param data ABI-encoded parameters required for bridge-related transfers. Ignored for transfers between a machine and its hub caliber.
function manageTransfer(address token, uint256 amount, bytes calldata data) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface ISwapModule {
event Swap(
address indexed sender,
uint16 swapperId,
address indexed inputToken,
address indexed outputToken,
uint256 inputAmount,
uint256 outputAmount
);
event SwapperTargetsSet(uint16 indexed swapper, address approvalTarget, address executionTarget);
struct SwapperTargets {
address approvalTarget;
address executionTarget;
}
/// @notice Swap order object.
/// @param swapperId The ID of the external swap protocol.
/// @param data The swap calldata to pass to the swapper's execution target.
/// @param inputToken The input token.
/// @param outputToken The output token.
/// @param inputAmount The input amount.
/// @param minOutputAmount The minimum expected output amount.
struct SwapOrder {
uint16 swapperId;
bytes data;
address inputToken;
address outputToken;
uint256 inputAmount;
uint256 minOutputAmount;
}
/// @notice Returns approval and execution targets for a given swapper ID.
/// @param swapperId The swapper ID.
/// @return approvalTarget The approval target.
/// @return executionTarget The execution target.
function getSwapperTargets(uint16 swapperId)
external
view
returns (address approvalTarget, address executionTarget);
/// @notice Swaps tokens using a given swapper.
/// @param order The swap order object.
function swap(SwapOrder calldata order) external returns (uint256);
/// @notice Sets approval and execution targets for a given swapper ID.
/// @param swapperId The swapper ID.
/// @param approvalTarget The approval target.
function setSwapperTargets(uint16 swapperId, address approvalTarget, address executionTarget) external;
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
revert(0x1c, 0x04)
}
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(_OWNER_SLOT, newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(_OWNER_SLOT)
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC-20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^0.8.20;
import {Arrays} from "../Arrays.sol";
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
* - Set can be cleared (all elements removed) in O(n).
*
* ```solidity
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position is the index of the value in the `values` array plus 1.
// Position 0 is used to mean a value is not in the set.
mapping(bytes32 value => uint256) _positions;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._positions[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We cache the value's position to prevent multiple reads from the same storage slot
uint256 position = set._positions[value];
if (position != 0) {
// Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 valueIndex = position - 1;
uint256 lastIndex = set._values.length - 1;
if (valueIndex != lastIndex) {
bytes32 lastValue = set._values[lastIndex];
// Move the lastValue to the index where the value to delete is
set._values[valueIndex] = lastValue;
// Update the tracked position of the lastValue (that was just moved)
set._positions[lastValue] = position;
}
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the tracked position for the deleted slot
delete set._positions[value];
return true;
} else {
return false;
}
}
/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function _clear(Set storage set) private {
uint256 len = _length(set);
for (uint256 i = 0; i < len; ++i) {
delete set._positions[set._values[i]];
}
Arrays.unsafeSetLength(set._values, 0);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._positions[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(Bytes32Set storage set) internal {
_clear(set._inner);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(AddressSet storage set) internal {
_clear(set._inner);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Removes all the values from a set. O(n).
*
* WARNING: Developers should keep in mind that this function has an unbounded cost and using it may render the
* function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.
*/
function clear(UintSet storage set) internal {
_clear(set._inner);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
assembly ("memory-safe") {
result := store
}
return result;
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
interface IWormhole {
struct GuardianSet {
address[] keys;
uint32 expirationTime;
}
struct Signature {
bytes32 r;
bytes32 s;
uint8 v;
uint8 guardianIndex;
}
struct VM {
uint8 version;
uint32 timestamp;
uint32 nonce;
uint16 emitterChainId;
bytes32 emitterAddress;
uint64 sequence;
uint8 consistencyLevel;
bytes payload;
uint32 guardianSetIndex;
Signature[] signatures;
bytes32 hash;
}
struct ContractUpgrade {
bytes32 module;
uint8 action;
uint16 chain;
address newContract;
}
struct GuardianSetUpgrade {
bytes32 module;
uint8 action;
uint16 chain;
GuardianSet newGuardianSet;
uint32 newGuardianSetIndex;
}
struct SetMessageFee {
bytes32 module;
uint8 action;
uint16 chain;
uint256 messageFee;
}
struct TransferFees {
bytes32 module;
uint8 action;
uint16 chain;
uint256 amount;
bytes32 recipient;
}
struct RecoverChainId {
bytes32 module;
uint8 action;
uint256 evmChainId;
uint16 newChainId;
}
event LogMessagePublished(
address indexed sender,
uint64 sequence,
uint32 nonce,
bytes payload,
uint8 consistencyLevel
);
event ContractUpgraded(address indexed oldContract, address indexed newContract);
event GuardianSetAdded(uint32 indexed index);
function publishMessage(uint32 nonce, bytes memory payload, uint8 consistencyLevel)
external
payable
returns (uint64 sequence);
function initialize() external;
function parseAndVerifyVM(bytes calldata encodedVM)
external
view
returns (VM memory vm, bool valid, string memory reason);
function verifyVM(VM memory vm) external view returns (bool valid, string memory reason);
function verifySignatures(
bytes32 hash,
Signature[] memory signatures,
GuardianSet memory guardianSet
) external pure returns (bool valid, string memory reason);
function parseVM(bytes memory encodedVM) external pure returns (VM memory vm);
function quorum(
uint256 numGuardians
) external pure returns (uint256 numSignaturesRequiredForQuorum);
function getGuardianSet(uint32 index) external view returns (GuardianSet memory);
function getCurrentGuardianSetIndex() external view returns (uint32);
function getGuardianSetExpiry() external view returns (uint32);
function governanceActionIsConsumed(bytes32 hash) external view returns (bool);
function isInitialized(address impl) external view returns (bool);
function chainId() external view returns (uint16);
function isFork() external view returns (bool);
function governanceChainId() external view returns (uint16);
function governanceContract() external view returns (bytes32);
function messageFee() external view returns (uint256);
function evmChainId() external view returns (uint256);
function nextSequence(address emitter) external view returns (uint64);
function parseContractUpgrade(
bytes memory encodedUpgrade
) external pure returns (ContractUpgrade memory cu);
function parseGuardianSetUpgrade(
bytes memory encodedUpgrade
) external pure returns (GuardianSetUpgrade memory gsu);
function parseSetMessageFee(
bytes memory encodedSetMessageFee
) external pure returns (SetMessageFee memory smf);
function parseTransferFees(
bytes memory encodedTransferFees
) external pure returns (TransferFees memory tf);
function parseRecoverChainId(
bytes memory encodedRecoverChainId
) external pure returns (RecoverChainId memory rci);
function submitContractUpgrade(bytes memory _vm) external;
function submitSetMessageFee(bytes memory _vm) external;
function submitNewGuardianSet(bytes memory _vm) external;
function submitTransferFees(bytes memory _vm) external;
function submitRecoverChainId(bytes memory _vm) external;
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;
import "wormhole-sdk/constants/Common.sol";
//This file appears comically large, but all unused functions are removed by the compiler.
library BytesParsing {
error OutOfBounds(uint256 offset, uint256 length);
error LengthMismatch(uint256 encodedLength, uint256 expectedLength);
error InvalidBoolVal(uint8 val);
/**
* Implements runtime check of logic that accesses memory.
* @param pastTheEndOffset The offset past the end relative to the accessed memory fragment.
* @param length The length of the memory fragment accessed.
*/
function checkBound(uint pastTheEndOffset, uint length) internal pure {
if (pastTheEndOffset > length)
revert OutOfBounds(pastTheEndOffset, length);
}
function checkLength(uint encodedLength, uint expectedLength) internal pure {
if (encodedLength != expectedLength)
revert LengthMismatch(encodedLength, expectedLength);
}
//Summary of all remaining functions:
//
//Each function has 2*2=4 versions:
// 1. unchecked - no bounds checking (uses suffix `Unchecked`)
// 2. checked (no suffix)
//and (since Solidity does not allow overloading based on data location)
// 1. calldata input (uses tag `Cd` )
// 2. memory input (uses tag `Mem`)
//
//The canoncial/recommended way of parsing data to be maximally gas efficient is to prefer the
// calldata variants over the memory variants and to use the unchecked variants with a manual
// length check at the end using `checkLength` to ensure that encoded data was consumed exactly.
//
//WARNING: Neither variant uses safe math! It is up to the dev to ensure that offset and length
// values are sensible. In other words, verify user inputs before passing them on. Preferably,
// the format that's being parsed does not allow for such overflows in the first place by e.g.
// encoding lengths using at most 4 bytes, etc.
//
//Functions:
// Unless stated otherwise, all functions take an `encoded` bytes calldata/memory and an `offset`
// as input and return the parsed value and the next offset (i.e. the offset pointing to the
// next, unparsed byte).
//
// * slice(encoded, offset, length)
// * sliceUint<n>Prefixed - n in {8, 16, 32} - parses n bytes of length prefix followed by data
// * asAddress
// * asBool
// * asUint<8*n> - n in {1, ..., 32}, i.e. asUint8, asUint16, ..., asUint256
// * asBytes<n> - n in {1, ..., 32}, i.e. asBytes1, asBytes2, ..., asBytes32
function sliceCdUnchecked(
bytes calldata encoded,
uint offset,
uint length
) internal pure returns (bytes calldata ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret.offset := add(encoded.offset, offset)
ret.length := length
nextOffset := add(offset, length)
}
}
function sliceMemUnchecked(
bytes memory encoded,
uint offset,
uint length
) internal pure returns (bytes memory ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, length)
ret := mload(FREE_MEMORY_PTR)
//Explanation on how we copy data here:
// The bytes type has the following layout in memory:
// [length: 32 bytes, data: length bytes]
// So if we allocate `bytes memory foo = new bytes(1);` then `foo` will be a pointer to 33
// bytes where the first 32 bytes contain the length and the last byte is the actual data.
// Since mload always loads 32 bytes of memory at once, we use our shift variable to align
// our reads so that our last read lines up exactly with the last 32 bytes of `encoded`.
// However this also means that if the length of `encoded` is not a multiple of 32 bytes, our
// first read will necessarily partly contain bytes from `encoded`'s 32 length bytes that
// will be written into the length part of our `ret` slice.
// We remedy this issue by writing the length of our `ret` slice at the end, thus
// overwritting those garbage bytes.
//and(length, 31) is equivalent to `mod(length, 32)`, but 2 gas cheaper
let shift := and(length, WORD_SIZE_MINUS_ONE)
if iszero(shift) {
shift := WORD_SIZE
}
let dest := add(ret, shift)
let end := add(dest, length)
for {
let src := add(add(encoded, shift), offset)
} lt(dest, end) {
src := add(src, WORD_SIZE)
dest := add(dest, WORD_SIZE)
} {
mstore(dest, mload(src))
}
mstore(ret, length)
//When compiling with --via-ir then normally allocated memory (i.e. via new) will have 32 byte
// memory alignment and so we enforce the same memory alignment here.
mstore(
FREE_MEMORY_PTR,
and(add(dest, WORD_SIZE_MINUS_ONE), not(WORD_SIZE_MINUS_ONE))
)
}
}
/* -------------------------------------------------------------------------------------------------
Remaining library code below was auto-generated via the following js/node code:
const dlTag = dl => dl ? "Cd" : "Mem";
const dlType = dl =>dl ? "calldata" : "memory";
const funcs = [
...[8,16,32].map(n => [
`sliceUint${n}Prefixed`,
dl => [
`uint${n} len;`,
`(len, nextOffset) = asUint${n}${dlTag(dl)}Unchecked(encoded, offset);`,
`(ret, nextOffset) = slice${dlTag(dl)}Unchecked(encoded, nextOffset, uint(len));`
],
dl => `bytes ${dlType(dl)}`,
]), [
`asAddress`,
dl => [
`uint160 tmp;`,
`(tmp, nextOffset) = asUint160${dlTag(dl)}Unchecked(encoded, offset);`,
`ret = address(tmp);`
],
_ => `address`
], [
`asBool`,
dl => [
`uint8 val;`,
`(val, nextOffset) = asUint8${dlTag(dl)}Unchecked(encoded, offset);`,
`if (val & 0xfe != 0)`,
` revert InvalidBoolVal(val);`,
`uint cleanedVal = uint(val);`,
`//skip 2x iszero opcode`,
`/// @solidity memory-safe-assembly`,
`assembly { ret := cleanedVal }`
],
_ => `bool`
],
...Array.from({length: 32}, (_, i) => [
`asUint${(i+1)*8}`,
dl => [
`/// @solidity memory-safe-assembly`,
`assembly {`,
` nextOffset := add(offset, ${i+1})`,
dl ? ` ret := shr(${256-(i+1)*8}, calldataload(add(encoded.offset, offset)))`
: ` ret := mload(add(encoded, nextOffset))`,
`}`
],
_ => `uint${(i+1)*8}`
]),
...Array.from({length: 32}, (_, i) => [
`asBytes${i+1}`,
dl => [
`/// @solidity memory-safe-assembly`,
`assembly {`,
` ret := ${dl ? "calldataload" : "mload"}(add(encoded${dl ? ".offset" :""}, ${dl ? "offset" : "add(offset, WORD_SIZE)"}))`,
` nextOffset := add(offset, ${i+1})`,
`}`
],
_ => `bytes${i+1}`
]),
];
for (const dl of [true, false])
console.log(
`function slice${dlTag(dl)}(
bytes ${dlType(dl)} encoded,
uint offset,
uint length
) internal pure returns (bytes ${dlType(dl)} ret, uint nextOffset) {
(ret, nextOffset) = slice${dlTag(dl)}Unchecked(encoded, offset, length);
checkBound(nextOffset, encoded.length);
}
`);
for (const [name, code, ret] of funcs) {
for (const dl of [true, false])
console.log(
`function ${name}${dlTag(dl)}Unchecked(
bytes ${dlType(dl)} encoded,
uint offset
) internal pure returns (${ret(dl)} ret, uint nextOffset) {
${code(dl).join("\n ")}
}
function ${name}${dlTag(dl)}(
bytes ${dlType(dl)} encoded,
uint offset
) internal pure returns (${ret(dl)} ret, uint nextOffset) {
(ret, nextOffset) = ${name}${dlTag(dl)}Unchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
`);
}
------------------------------------------------------------------------------------------------- */
function sliceCd(
bytes calldata encoded,
uint offset,
uint length
) internal pure returns (bytes calldata ret, uint nextOffset) {
(ret, nextOffset) = sliceCdUnchecked(encoded, offset, length);
checkBound(nextOffset, encoded.length);
}
function sliceMem(
bytes memory encoded,
uint offset,
uint length
) internal pure returns (bytes memory ret, uint nextOffset) {
(ret, nextOffset) = sliceMemUnchecked(encoded, offset, length);
checkBound(nextOffset, encoded.length);
}
function sliceUint8PrefixedCdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes calldata ret, uint nextOffset) {
uint8 len;
(len, nextOffset) = asUint8CdUnchecked(encoded, offset);
(ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len));
}
function sliceUint8PrefixedCd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes calldata ret, uint nextOffset) {
(ret, nextOffset) = sliceUint8PrefixedCdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function sliceUint8PrefixedMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes memory ret, uint nextOffset) {
uint8 len;
(len, nextOffset) = asUint8MemUnchecked(encoded, offset);
(ret, nextOffset) = sliceMemUnchecked(encoded, nextOffset, uint(len));
}
function sliceUint8PrefixedMem(
bytes memory encoded,
uint offset
) internal pure returns (bytes memory ret, uint nextOffset) {
(ret, nextOffset) = sliceUint8PrefixedMemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function sliceUint16PrefixedCdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes calldata ret, uint nextOffset) {
uint16 len;
(len, nextOffset) = asUint16CdUnchecked(encoded, offset);
(ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len));
}
function sliceUint16PrefixedCd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes calldata ret, uint nextOffset) {
(ret, nextOffset) = sliceUint16PrefixedCdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function sliceUint16PrefixedMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes memory ret, uint nextOffset) {
uint16 len;
(len, nextOffset) = asUint16MemUnchecked(encoded, offset);
(ret, nextOffset) = sliceMemUnchecked(encoded, nextOffset, uint(len));
}
function sliceUint16PrefixedMem(
bytes memory encoded,
uint offset
) internal pure returns (bytes memory ret, uint nextOffset) {
(ret, nextOffset) = sliceUint16PrefixedMemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function sliceUint32PrefixedCdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes calldata ret, uint nextOffset) {
uint32 len;
(len, nextOffset) = asUint32CdUnchecked(encoded, offset);
(ret, nextOffset) = sliceCdUnchecked(encoded, nextOffset, uint(len));
}
function sliceUint32PrefixedCd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes calldata ret, uint nextOffset) {
(ret, nextOffset) = sliceUint32PrefixedCdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function sliceUint32PrefixedMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes memory ret, uint nextOffset) {
uint32 len;
(len, nextOffset) = asUint32MemUnchecked(encoded, offset);
(ret, nextOffset) = sliceMemUnchecked(encoded, nextOffset, uint(len));
}
function sliceUint32PrefixedMem(
bytes memory encoded,
uint offset
) internal pure returns (bytes memory ret, uint nextOffset) {
(ret, nextOffset) = sliceUint32PrefixedMemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asAddressCdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (address ret, uint nextOffset) {
uint160 tmp;
(tmp, nextOffset) = asUint160CdUnchecked(encoded, offset);
ret = address(tmp);
}
function asAddressCd(
bytes calldata encoded,
uint offset
) internal pure returns (address ret, uint nextOffset) {
(ret, nextOffset) = asAddressCdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asAddressMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (address ret, uint nextOffset) {
uint160 tmp;
(tmp, nextOffset) = asUint160MemUnchecked(encoded, offset);
ret = address(tmp);
}
function asAddressMem(
bytes memory encoded,
uint offset
) internal pure returns (address ret, uint nextOffset) {
(ret, nextOffset) = asAddressMemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBoolCdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bool ret, uint nextOffset) {
uint8 val;
(val, nextOffset) = asUint8CdUnchecked(encoded, offset);
if (val & 0xfe != 0)
revert InvalidBoolVal(val);
uint cleanedVal = uint(val);
//skip 2x iszero opcode
/// @solidity memory-safe-assembly
assembly { ret := cleanedVal }
}
function asBoolCd(
bytes calldata encoded,
uint offset
) internal pure returns (bool ret, uint nextOffset) {
(ret, nextOffset) = asBoolCdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBoolMemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bool ret, uint nextOffset) {
uint8 val;
(val, nextOffset) = asUint8MemUnchecked(encoded, offset);
if (val & 0xfe != 0)
revert InvalidBoolVal(val);
uint cleanedVal = uint(val);
//skip 2x iszero opcode
/// @solidity memory-safe-assembly
assembly { ret := cleanedVal }
}
function asBoolMem(
bytes memory encoded,
uint offset
) internal pure returns (bool ret, uint nextOffset) {
(ret, nextOffset) = asBoolMemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint8CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint8 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 1)
ret := shr(248, calldataload(add(encoded.offset, offset)))
}
}
function asUint8Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint8 ret, uint nextOffset) {
(ret, nextOffset) = asUint8CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint8MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint8 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 1)
ret := mload(add(encoded, nextOffset))
}
}
function asUint8Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint8 ret, uint nextOffset) {
(ret, nextOffset) = asUint8MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint16CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint16 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 2)
ret := shr(240, calldataload(add(encoded.offset, offset)))
}
}
function asUint16Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint16 ret, uint nextOffset) {
(ret, nextOffset) = asUint16CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint16MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint16 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 2)
ret := mload(add(encoded, nextOffset))
}
}
function asUint16Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint16 ret, uint nextOffset) {
(ret, nextOffset) = asUint16MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint24CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint24 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 3)
ret := shr(232, calldataload(add(encoded.offset, offset)))
}
}
function asUint24Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint24 ret, uint nextOffset) {
(ret, nextOffset) = asUint24CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint24MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint24 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 3)
ret := mload(add(encoded, nextOffset))
}
}
function asUint24Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint24 ret, uint nextOffset) {
(ret, nextOffset) = asUint24MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint32CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint32 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 4)
ret := shr(224, calldataload(add(encoded.offset, offset)))
}
}
function asUint32Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint32 ret, uint nextOffset) {
(ret, nextOffset) = asUint32CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint32MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint32 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 4)
ret := mload(add(encoded, nextOffset))
}
}
function asUint32Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint32 ret, uint nextOffset) {
(ret, nextOffset) = asUint32MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint40CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint40 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 5)
ret := shr(216, calldataload(add(encoded.offset, offset)))
}
}
function asUint40Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint40 ret, uint nextOffset) {
(ret, nextOffset) = asUint40CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint40MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint40 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 5)
ret := mload(add(encoded, nextOffset))
}
}
function asUint40Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint40 ret, uint nextOffset) {
(ret, nextOffset) = asUint40MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint48CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint48 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 6)
ret := shr(208, calldataload(add(encoded.offset, offset)))
}
}
function asUint48Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint48 ret, uint nextOffset) {
(ret, nextOffset) = asUint48CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint48MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint48 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 6)
ret := mload(add(encoded, nextOffset))
}
}
function asUint48Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint48 ret, uint nextOffset) {
(ret, nextOffset) = asUint48MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint56CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint56 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 7)
ret := shr(200, calldataload(add(encoded.offset, offset)))
}
}
function asUint56Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint56 ret, uint nextOffset) {
(ret, nextOffset) = asUint56CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint56MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint56 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 7)
ret := mload(add(encoded, nextOffset))
}
}
function asUint56Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint56 ret, uint nextOffset) {
(ret, nextOffset) = asUint56MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint64CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint64 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 8)
ret := shr(192, calldataload(add(encoded.offset, offset)))
}
}
function asUint64Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint64 ret, uint nextOffset) {
(ret, nextOffset) = asUint64CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint64MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint64 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 8)
ret := mload(add(encoded, nextOffset))
}
}
function asUint64Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint64 ret, uint nextOffset) {
(ret, nextOffset) = asUint64MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint72CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint72 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 9)
ret := shr(184, calldataload(add(encoded.offset, offset)))
}
}
function asUint72Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint72 ret, uint nextOffset) {
(ret, nextOffset) = asUint72CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint72MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint72 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 9)
ret := mload(add(encoded, nextOffset))
}
}
function asUint72Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint72 ret, uint nextOffset) {
(ret, nextOffset) = asUint72MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint80CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint80 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 10)
ret := shr(176, calldataload(add(encoded.offset, offset)))
}
}
function asUint80Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint80 ret, uint nextOffset) {
(ret, nextOffset) = asUint80CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint80MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint80 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 10)
ret := mload(add(encoded, nextOffset))
}
}
function asUint80Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint80 ret, uint nextOffset) {
(ret, nextOffset) = asUint80MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint88CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint88 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 11)
ret := shr(168, calldataload(add(encoded.offset, offset)))
}
}
function asUint88Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint88 ret, uint nextOffset) {
(ret, nextOffset) = asUint88CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint88MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint88 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 11)
ret := mload(add(encoded, nextOffset))
}
}
function asUint88Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint88 ret, uint nextOffset) {
(ret, nextOffset) = asUint88MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint96CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint96 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 12)
ret := shr(160, calldataload(add(encoded.offset, offset)))
}
}
function asUint96Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint96 ret, uint nextOffset) {
(ret, nextOffset) = asUint96CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint96MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint96 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 12)
ret := mload(add(encoded, nextOffset))
}
}
function asUint96Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint96 ret, uint nextOffset) {
(ret, nextOffset) = asUint96MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint104CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint104 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 13)
ret := shr(152, calldataload(add(encoded.offset, offset)))
}
}
function asUint104Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint104 ret, uint nextOffset) {
(ret, nextOffset) = asUint104CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint104MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint104 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 13)
ret := mload(add(encoded, nextOffset))
}
}
function asUint104Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint104 ret, uint nextOffset) {
(ret, nextOffset) = asUint104MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint112CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint112 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 14)
ret := shr(144, calldataload(add(encoded.offset, offset)))
}
}
function asUint112Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint112 ret, uint nextOffset) {
(ret, nextOffset) = asUint112CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint112MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint112 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 14)
ret := mload(add(encoded, nextOffset))
}
}
function asUint112Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint112 ret, uint nextOffset) {
(ret, nextOffset) = asUint112MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint120CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint120 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 15)
ret := shr(136, calldataload(add(encoded.offset, offset)))
}
}
function asUint120Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint120 ret, uint nextOffset) {
(ret, nextOffset) = asUint120CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint120MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint120 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 15)
ret := mload(add(encoded, nextOffset))
}
}
function asUint120Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint120 ret, uint nextOffset) {
(ret, nextOffset) = asUint120MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint128CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint128 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 16)
ret := shr(128, calldataload(add(encoded.offset, offset)))
}
}
function asUint128Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint128 ret, uint nextOffset) {
(ret, nextOffset) = asUint128CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint128MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint128 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 16)
ret := mload(add(encoded, nextOffset))
}
}
function asUint128Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint128 ret, uint nextOffset) {
(ret, nextOffset) = asUint128MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint136CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint136 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 17)
ret := shr(120, calldataload(add(encoded.offset, offset)))
}
}
function asUint136Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint136 ret, uint nextOffset) {
(ret, nextOffset) = asUint136CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint136MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint136 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 17)
ret := mload(add(encoded, nextOffset))
}
}
function asUint136Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint136 ret, uint nextOffset) {
(ret, nextOffset) = asUint136MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint144CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint144 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 18)
ret := shr(112, calldataload(add(encoded.offset, offset)))
}
}
function asUint144Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint144 ret, uint nextOffset) {
(ret, nextOffset) = asUint144CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint144MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint144 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 18)
ret := mload(add(encoded, nextOffset))
}
}
function asUint144Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint144 ret, uint nextOffset) {
(ret, nextOffset) = asUint144MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint152CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint152 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 19)
ret := shr(104, calldataload(add(encoded.offset, offset)))
}
}
function asUint152Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint152 ret, uint nextOffset) {
(ret, nextOffset) = asUint152CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint152MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint152 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 19)
ret := mload(add(encoded, nextOffset))
}
}
function asUint152Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint152 ret, uint nextOffset) {
(ret, nextOffset) = asUint152MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint160CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint160 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 20)
ret := shr(96, calldataload(add(encoded.offset, offset)))
}
}
function asUint160Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint160 ret, uint nextOffset) {
(ret, nextOffset) = asUint160CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint160MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint160 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 20)
ret := mload(add(encoded, nextOffset))
}
}
function asUint160Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint160 ret, uint nextOffset) {
(ret, nextOffset) = asUint160MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint168CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint168 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 21)
ret := shr(88, calldataload(add(encoded.offset, offset)))
}
}
function asUint168Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint168 ret, uint nextOffset) {
(ret, nextOffset) = asUint168CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint168MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint168 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 21)
ret := mload(add(encoded, nextOffset))
}
}
function asUint168Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint168 ret, uint nextOffset) {
(ret, nextOffset) = asUint168MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint176CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint176 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 22)
ret := shr(80, calldataload(add(encoded.offset, offset)))
}
}
function asUint176Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint176 ret, uint nextOffset) {
(ret, nextOffset) = asUint176CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint176MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint176 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 22)
ret := mload(add(encoded, nextOffset))
}
}
function asUint176Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint176 ret, uint nextOffset) {
(ret, nextOffset) = asUint176MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint184CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint184 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 23)
ret := shr(72, calldataload(add(encoded.offset, offset)))
}
}
function asUint184Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint184 ret, uint nextOffset) {
(ret, nextOffset) = asUint184CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint184MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint184 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 23)
ret := mload(add(encoded, nextOffset))
}
}
function asUint184Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint184 ret, uint nextOffset) {
(ret, nextOffset) = asUint184MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint192CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint192 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 24)
ret := shr(64, calldataload(add(encoded.offset, offset)))
}
}
function asUint192Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint192 ret, uint nextOffset) {
(ret, nextOffset) = asUint192CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint192MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint192 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 24)
ret := mload(add(encoded, nextOffset))
}
}
function asUint192Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint192 ret, uint nextOffset) {
(ret, nextOffset) = asUint192MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint200CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint200 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 25)
ret := shr(56, calldataload(add(encoded.offset, offset)))
}
}
function asUint200Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint200 ret, uint nextOffset) {
(ret, nextOffset) = asUint200CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint200MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint200 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 25)
ret := mload(add(encoded, nextOffset))
}
}
function asUint200Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint200 ret, uint nextOffset) {
(ret, nextOffset) = asUint200MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint208CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint208 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 26)
ret := shr(48, calldataload(add(encoded.offset, offset)))
}
}
function asUint208Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint208 ret, uint nextOffset) {
(ret, nextOffset) = asUint208CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint208MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint208 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 26)
ret := mload(add(encoded, nextOffset))
}
}
function asUint208Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint208 ret, uint nextOffset) {
(ret, nextOffset) = asUint208MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint216CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint216 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 27)
ret := shr(40, calldataload(add(encoded.offset, offset)))
}
}
function asUint216Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint216 ret, uint nextOffset) {
(ret, nextOffset) = asUint216CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint216MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint216 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 27)
ret := mload(add(encoded, nextOffset))
}
}
function asUint216Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint216 ret, uint nextOffset) {
(ret, nextOffset) = asUint216MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint224CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint224 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 28)
ret := shr(32, calldataload(add(encoded.offset, offset)))
}
}
function asUint224Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint224 ret, uint nextOffset) {
(ret, nextOffset) = asUint224CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint224MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint224 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 28)
ret := mload(add(encoded, nextOffset))
}
}
function asUint224Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint224 ret, uint nextOffset) {
(ret, nextOffset) = asUint224MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint232CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint232 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 29)
ret := shr(24, calldataload(add(encoded.offset, offset)))
}
}
function asUint232Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint232 ret, uint nextOffset) {
(ret, nextOffset) = asUint232CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint232MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint232 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 29)
ret := mload(add(encoded, nextOffset))
}
}
function asUint232Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint232 ret, uint nextOffset) {
(ret, nextOffset) = asUint232MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint240CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint240 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 30)
ret := shr(16, calldataload(add(encoded.offset, offset)))
}
}
function asUint240Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint240 ret, uint nextOffset) {
(ret, nextOffset) = asUint240CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint240MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint240 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 30)
ret := mload(add(encoded, nextOffset))
}
}
function asUint240Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint240 ret, uint nextOffset) {
(ret, nextOffset) = asUint240MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint248CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint248 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 31)
ret := shr(8, calldataload(add(encoded.offset, offset)))
}
}
function asUint248Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint248 ret, uint nextOffset) {
(ret, nextOffset) = asUint248CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint248MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint248 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 31)
ret := mload(add(encoded, nextOffset))
}
}
function asUint248Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint248 ret, uint nextOffset) {
(ret, nextOffset) = asUint248MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint256CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (uint256 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 32)
ret := shr(0, calldataload(add(encoded.offset, offset)))
}
}
function asUint256Cd(
bytes calldata encoded,
uint offset
) internal pure returns (uint256 ret, uint nextOffset) {
(ret, nextOffset) = asUint256CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asUint256MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (uint256 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
nextOffset := add(offset, 32)
ret := mload(add(encoded, nextOffset))
}
}
function asUint256Mem(
bytes memory encoded,
uint offset
) internal pure returns (uint256 ret, uint nextOffset) {
(ret, nextOffset) = asUint256MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes1CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes1 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 1)
}
}
function asBytes1Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes1 ret, uint nextOffset) {
(ret, nextOffset) = asBytes1CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes1MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes1 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 1)
}
}
function asBytes1Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes1 ret, uint nextOffset) {
(ret, nextOffset) = asBytes1MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes2CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes2 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 2)
}
}
function asBytes2Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes2 ret, uint nextOffset) {
(ret, nextOffset) = asBytes2CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes2MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes2 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 2)
}
}
function asBytes2Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes2 ret, uint nextOffset) {
(ret, nextOffset) = asBytes2MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes3CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes3 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 3)
}
}
function asBytes3Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes3 ret, uint nextOffset) {
(ret, nextOffset) = asBytes3CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes3MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes3 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 3)
}
}
function asBytes3Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes3 ret, uint nextOffset) {
(ret, nextOffset) = asBytes3MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes4CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes4 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 4)
}
}
function asBytes4Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes4 ret, uint nextOffset) {
(ret, nextOffset) = asBytes4CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes4MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes4 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 4)
}
}
function asBytes4Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes4 ret, uint nextOffset) {
(ret, nextOffset) = asBytes4MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes5CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes5 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 5)
}
}
function asBytes5Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes5 ret, uint nextOffset) {
(ret, nextOffset) = asBytes5CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes5MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes5 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 5)
}
}
function asBytes5Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes5 ret, uint nextOffset) {
(ret, nextOffset) = asBytes5MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes6CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes6 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 6)
}
}
function asBytes6Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes6 ret, uint nextOffset) {
(ret, nextOffset) = asBytes6CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes6MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes6 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 6)
}
}
function asBytes6Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes6 ret, uint nextOffset) {
(ret, nextOffset) = asBytes6MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes7CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes7 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 7)
}
}
function asBytes7Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes7 ret, uint nextOffset) {
(ret, nextOffset) = asBytes7CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes7MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes7 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 7)
}
}
function asBytes7Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes7 ret, uint nextOffset) {
(ret, nextOffset) = asBytes7MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes8CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes8 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 8)
}
}
function asBytes8Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes8 ret, uint nextOffset) {
(ret, nextOffset) = asBytes8CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes8MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes8 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 8)
}
}
function asBytes8Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes8 ret, uint nextOffset) {
(ret, nextOffset) = asBytes8MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes9CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes9 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 9)
}
}
function asBytes9Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes9 ret, uint nextOffset) {
(ret, nextOffset) = asBytes9CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes9MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes9 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 9)
}
}
function asBytes9Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes9 ret, uint nextOffset) {
(ret, nextOffset) = asBytes9MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes10CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes10 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 10)
}
}
function asBytes10Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes10 ret, uint nextOffset) {
(ret, nextOffset) = asBytes10CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes10MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes10 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 10)
}
}
function asBytes10Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes10 ret, uint nextOffset) {
(ret, nextOffset) = asBytes10MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes11CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes11 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 11)
}
}
function asBytes11Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes11 ret, uint nextOffset) {
(ret, nextOffset) = asBytes11CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes11MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes11 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 11)
}
}
function asBytes11Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes11 ret, uint nextOffset) {
(ret, nextOffset) = asBytes11MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes12CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes12 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 12)
}
}
function asBytes12Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes12 ret, uint nextOffset) {
(ret, nextOffset) = asBytes12CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes12MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes12 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 12)
}
}
function asBytes12Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes12 ret, uint nextOffset) {
(ret, nextOffset) = asBytes12MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes13CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes13 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 13)
}
}
function asBytes13Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes13 ret, uint nextOffset) {
(ret, nextOffset) = asBytes13CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes13MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes13 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 13)
}
}
function asBytes13Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes13 ret, uint nextOffset) {
(ret, nextOffset) = asBytes13MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes14CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes14 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 14)
}
}
function asBytes14Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes14 ret, uint nextOffset) {
(ret, nextOffset) = asBytes14CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes14MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes14 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 14)
}
}
function asBytes14Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes14 ret, uint nextOffset) {
(ret, nextOffset) = asBytes14MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes15CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes15 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 15)
}
}
function asBytes15Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes15 ret, uint nextOffset) {
(ret, nextOffset) = asBytes15CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes15MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes15 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 15)
}
}
function asBytes15Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes15 ret, uint nextOffset) {
(ret, nextOffset) = asBytes15MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes16CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes16 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 16)
}
}
function asBytes16Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes16 ret, uint nextOffset) {
(ret, nextOffset) = asBytes16CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes16MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes16 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 16)
}
}
function asBytes16Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes16 ret, uint nextOffset) {
(ret, nextOffset) = asBytes16MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes17CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes17 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 17)
}
}
function asBytes17Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes17 ret, uint nextOffset) {
(ret, nextOffset) = asBytes17CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes17MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes17 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 17)
}
}
function asBytes17Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes17 ret, uint nextOffset) {
(ret, nextOffset) = asBytes17MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes18CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes18 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 18)
}
}
function asBytes18Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes18 ret, uint nextOffset) {
(ret, nextOffset) = asBytes18CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes18MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes18 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 18)
}
}
function asBytes18Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes18 ret, uint nextOffset) {
(ret, nextOffset) = asBytes18MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes19CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes19 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 19)
}
}
function asBytes19Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes19 ret, uint nextOffset) {
(ret, nextOffset) = asBytes19CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes19MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes19 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 19)
}
}
function asBytes19Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes19 ret, uint nextOffset) {
(ret, nextOffset) = asBytes19MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes20CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes20 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 20)
}
}
function asBytes20Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes20 ret, uint nextOffset) {
(ret, nextOffset) = asBytes20CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes20MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes20 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 20)
}
}
function asBytes20Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes20 ret, uint nextOffset) {
(ret, nextOffset) = asBytes20MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes21CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes21 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 21)
}
}
function asBytes21Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes21 ret, uint nextOffset) {
(ret, nextOffset) = asBytes21CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes21MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes21 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 21)
}
}
function asBytes21Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes21 ret, uint nextOffset) {
(ret, nextOffset) = asBytes21MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes22CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes22 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 22)
}
}
function asBytes22Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes22 ret, uint nextOffset) {
(ret, nextOffset) = asBytes22CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes22MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes22 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 22)
}
}
function asBytes22Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes22 ret, uint nextOffset) {
(ret, nextOffset) = asBytes22MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes23CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes23 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 23)
}
}
function asBytes23Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes23 ret, uint nextOffset) {
(ret, nextOffset) = asBytes23CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes23MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes23 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 23)
}
}
function asBytes23Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes23 ret, uint nextOffset) {
(ret, nextOffset) = asBytes23MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes24CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes24 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 24)
}
}
function asBytes24Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes24 ret, uint nextOffset) {
(ret, nextOffset) = asBytes24CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes24MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes24 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 24)
}
}
function asBytes24Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes24 ret, uint nextOffset) {
(ret, nextOffset) = asBytes24MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes25CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes25 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 25)
}
}
function asBytes25Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes25 ret, uint nextOffset) {
(ret, nextOffset) = asBytes25CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes25MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes25 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 25)
}
}
function asBytes25Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes25 ret, uint nextOffset) {
(ret, nextOffset) = asBytes25MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes26CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes26 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 26)
}
}
function asBytes26Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes26 ret, uint nextOffset) {
(ret, nextOffset) = asBytes26CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes26MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes26 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 26)
}
}
function asBytes26Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes26 ret, uint nextOffset) {
(ret, nextOffset) = asBytes26MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes27CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes27 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 27)
}
}
function asBytes27Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes27 ret, uint nextOffset) {
(ret, nextOffset) = asBytes27CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes27MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes27 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 27)
}
}
function asBytes27Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes27 ret, uint nextOffset) {
(ret, nextOffset) = asBytes27MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes28CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes28 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 28)
}
}
function asBytes28Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes28 ret, uint nextOffset) {
(ret, nextOffset) = asBytes28CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes28MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes28 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 28)
}
}
function asBytes28Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes28 ret, uint nextOffset) {
(ret, nextOffset) = asBytes28MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes29CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes29 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 29)
}
}
function asBytes29Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes29 ret, uint nextOffset) {
(ret, nextOffset) = asBytes29CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes29MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes29 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 29)
}
}
function asBytes29Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes29 ret, uint nextOffset) {
(ret, nextOffset) = asBytes29MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes30CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes30 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 30)
}
}
function asBytes30Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes30 ret, uint nextOffset) {
(ret, nextOffset) = asBytes30CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes30MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes30 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 30)
}
}
function asBytes30Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes30 ret, uint nextOffset) {
(ret, nextOffset) = asBytes30MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes31CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes31 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 31)
}
}
function asBytes31Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes31 ret, uint nextOffset) {
(ret, nextOffset) = asBytes31CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes31MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes31 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 31)
}
}
function asBytes31Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes31 ret, uint nextOffset) {
(ret, nextOffset) = asBytes31MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes32CdUnchecked(
bytes calldata encoded,
uint offset
) internal pure returns (bytes32 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := calldataload(add(encoded.offset, offset))
nextOffset := add(offset, 32)
}
}
function asBytes32Cd(
bytes calldata encoded,
uint offset
) internal pure returns (bytes32 ret, uint nextOffset) {
(ret, nextOffset) = asBytes32CdUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
function asBytes32MemUnchecked(
bytes memory encoded,
uint offset
) internal pure returns (bytes32 ret, uint nextOffset) {
/// @solidity memory-safe-assembly
assembly {
ret := mload(add(encoded, add(offset, WORD_SIZE)))
nextOffset := add(offset, 32)
}
}
function asBytes32Mem(
bytes memory encoded,
uint offset
) internal pure returns (bytes32 ret, uint nextOffset) {
(ret, nextOffset) = asBytes32MemUnchecked(encoded, offset);
checkBound(nextOffset, encoded.length);
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;
import {
tokenOrNativeTransfer
} from "wormhole-sdk/utils/Transfer.sol";
import {
reRevert
} from "wormhole-sdk/utils/Revert.sol";
import {
NotAnEvmAddress,
toUniversalAddress,
fromUniversalAddress
} from "wormhole-sdk/utils/UniversalAddress.sol";
import {
keccak256Word,
keccak256SliceUnchecked,
keccak256Cd
} from "wormhole-sdk/utils/Keccak.sol";
import {
eagerAnd,
eagerOr
} from "wormhole-sdk/utils/EagerOps.sol";// SPDX-License-Identifier: MIT
pragma solidity 0.8.28;
interface IBridgeController {
event BridgeAdapterCreated(uint16 indexed bridgeId, address indexed adapter);
event MaxBridgeLossBpsChanged(
uint16 indexed bridgeId, uint256 indexed oldMaxBridgeLossBps, uint256 indexed newMaxBridgeLossBps
);
event BridgingStateReset(address indexed token);
event OutTransferEnabledSet(uint256 indexed bridgeId, bool enabled);
/// @notice Bridge ID => Is bridge adapter deployed.
function isBridgeSupported(uint16 bridgeId) external view returns (bool);
/// @notice Bridge ID => Is outgoing transfer enabled.
function isOutTransferEnabled(uint16 bridgeId) external view returns (bool);
/// @notice Bridge ID => Address of the associated bridge adapter.
function getBridgeAdapter(uint16 bridgeId) external view returns (address);
/// @notice Bridge ID => Max allowed value loss in basis points for transfers via this bridge.
function getMaxBridgeLossBps(uint16 bridgeId) external view returns (uint256);
/// @notice Deploys a new BridgeAdapter instance.
/// @param bridgeId The ID of the bridge.
/// @param initialMaxBridgeLossBps The initial maximum allowed value loss in basis points for transfers via this bridge.
/// @param initData The optional initialization data for the bridge adapter.
/// @return The address of the deployed BridgeAdapter.
function createBridgeAdapter(uint16 bridgeId, uint256 initialMaxBridgeLossBps, bytes calldata initData)
external
returns (address);
/// @notice Sets the maximum allowed value loss in basis points for transfers via this bridge.
/// @param bridgeId The ID of the bridge.
/// @param maxBridgeLossBps The maximum allowed value loss in basis points.
function setMaxBridgeLossBps(uint16 bridgeId, uint256 maxBridgeLossBps) external;
/// @notice Sets the outgoing transfer enabled status for a bridge.
/// @param bridgeId The ID of the bridge.
/// @param enabled True to enable outgoing transfer for the given bridge ID, false to disable.
function setOutTransferEnabled(uint16 bridgeId, bool enabled) external;
/// @notice Executes a scheduled outgoing bridge transfer.
/// @param bridgeId The ID of the bridge.
/// @param transferId The ID of the transfer to execute.
/// @param data The optional data needed to execute the transfer.
function sendOutBridgeTransfer(uint16 bridgeId, uint256 transferId, bytes calldata data) external;
/// @notice Registers a message hash as authorized for an incoming bridge transfer.
/// @param bridgeId The ID of the bridge.
/// @param messageHash The hash of the message to authorize.
function authorizeInBridgeTransfer(uint16 bridgeId, bytes32 messageHash) external;
/// @notice Transfers a received bridge transfer out of the adapter.
/// @param bridgeId The ID of the bridge.
/// @param transferId The ID of the transfer to claim.
function claimInBridgeTransfer(uint16 bridgeId, uint256 transferId) external;
/// @notice Cancels an outgoing bridge transfer.
/// @param bridgeId The ID of the bridge.
/// @param transferId The ID of the transfer to cancel.
function cancelOutBridgeTransfer(uint16 bridgeId, uint256 transferId) external;
/// @notice Resets internal bridge counters for a given token, and withdraw token balances held by all bridge adapters.
/// @dev This function is intended to be used by the DAO to realign bridge accounting state and maintain protocol consistency,
/// typically in response to operator deviations, external bridge discrepancies, or unbounded counter growth.
/// @param token The address of the token.
function resetBridgingState(address token) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/Arrays.sol)
// This file was procedurally generated from scripts/generate/templates/Arrays.js.
pragma solidity ^0.8.20;
import {Comparators} from "./Comparators.sol";
import {SlotDerivation} from "./SlotDerivation.sol";
import {StorageSlot} from "./StorageSlot.sol";
import {Math} from "./math/Math.sol";
/**
* @dev Collection of functions related to array types.
*/
library Arrays {
using SlotDerivation for bytes32;
using StorageSlot for bytes32;
/**
* @dev Sort an array of uint256 (in memory) following the provided comparator function.
*
* This function does the sorting "in place", meaning that it overrides the input. The object is returned for
* convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
*
* NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
* array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
* when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
* consume more gas than is available in a block, leading to potential DoS.
*
* IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
*/
function sort(
uint256[] memory array,
function(uint256, uint256) pure returns (bool) comp
) internal pure returns (uint256[] memory) {
_quickSort(_begin(array), _end(array), comp);
return array;
}
/**
* @dev Variant of {sort} that sorts an array of uint256 in increasing order.
*/
function sort(uint256[] memory array) internal pure returns (uint256[] memory) {
sort(array, Comparators.lt);
return array;
}
/**
* @dev Sort an array of address (in memory) following the provided comparator function.
*
* This function does the sorting "in place", meaning that it overrides the input. The object is returned for
* convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
*
* NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
* array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
* when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
* consume more gas than is available in a block, leading to potential DoS.
*
* IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
*/
function sort(
address[] memory array,
function(address, address) pure returns (bool) comp
) internal pure returns (address[] memory) {
sort(_castToUint256Array(array), _castToUint256Comp(comp));
return array;
}
/**
* @dev Variant of {sort} that sorts an array of address in increasing order.
*/
function sort(address[] memory array) internal pure returns (address[] memory) {
sort(_castToUint256Array(array), Comparators.lt);
return array;
}
/**
* @dev Sort an array of bytes32 (in memory) following the provided comparator function.
*
* This function does the sorting "in place", meaning that it overrides the input. The object is returned for
* convenience, but that returned value can be discarded safely if the caller has a memory pointer to the array.
*
* NOTE: this function's cost is `O(n · log(n))` in average and `O(n²)` in the worst case, with n the length of the
* array. Using it in view functions that are executed through `eth_call` is safe, but one should be very careful
* when executing this as part of a transaction. If the array being sorted is too large, the sort operation may
* consume more gas than is available in a block, leading to potential DoS.
*
* IMPORTANT: Consider memory side-effects when using custom comparator functions that access memory in an unsafe way.
*/
function sort(
bytes32[] memory array,
function(bytes32, bytes32) pure returns (bool) comp
) internal pure returns (bytes32[] memory) {
sort(_castToUint256Array(array), _castToUint256Comp(comp));
return array;
}
/**
* @dev Variant of {sort} that sorts an array of bytes32 in increasing order.
*/
function sort(bytes32[] memory array) internal pure returns (bytes32[] memory) {
sort(_castToUint256Array(array), Comparators.lt);
return array;
}
/**
* @dev Performs a quick sort of a segment of memory. The segment sorted starts at `begin` (inclusive), and stops
* at end (exclusive). Sorting follows the `comp` comparator.
*
* Invariant: `begin <= end`. This is the case when initially called by {sort} and is preserved in subcalls.
*
* IMPORTANT: Memory locations between `begin` and `end` are not validated/zeroed. This function should
* be used only if the limits are within a memory array.
*/
function _quickSort(uint256 begin, uint256 end, function(uint256, uint256) pure returns (bool) comp) private pure {
unchecked {
if (end - begin < 0x40) return;
// Use first element as pivot
uint256 pivot = _mload(begin);
// Position where the pivot should be at the end of the loop
uint256 pos = begin;
for (uint256 it = begin + 0x20; it < end; it += 0x20) {
if (comp(_mload(it), pivot)) {
// If the value stored at the iterator's position comes before the pivot, we increment the
// position of the pivot and move the value there.
pos += 0x20;
_swap(pos, it);
}
}
_swap(begin, pos); // Swap pivot into place
_quickSort(begin, pos, comp); // Sort the left side of the pivot
_quickSort(pos + 0x20, end, comp); // Sort the right side of the pivot
}
}
/**
* @dev Pointer to the memory location of the first element of `array`.
*/
function _begin(uint256[] memory array) private pure returns (uint256 ptr) {
assembly ("memory-safe") {
ptr := add(array, 0x20)
}
}
/**
* @dev Pointer to the memory location of the first memory word (32bytes) after `array`. This is the memory word
* that comes just after the last element of the array.
*/
function _end(uint256[] memory array) private pure returns (uint256 ptr) {
unchecked {
return _begin(array) + array.length * 0x20;
}
}
/**
* @dev Load memory word (as a uint256) at location `ptr`.
*/
function _mload(uint256 ptr) private pure returns (uint256 value) {
assembly {
value := mload(ptr)
}
}
/**
* @dev Swaps the elements memory location `ptr1` and `ptr2`.
*/
function _swap(uint256 ptr1, uint256 ptr2) private pure {
assembly {
let value1 := mload(ptr1)
let value2 := mload(ptr2)
mstore(ptr1, value2)
mstore(ptr2, value1)
}
}
/// @dev Helper: low level cast address memory array to uint256 memory array
function _castToUint256Array(address[] memory input) private pure returns (uint256[] memory output) {
assembly {
output := input
}
}
/// @dev Helper: low level cast bytes32 memory array to uint256 memory array
function _castToUint256Array(bytes32[] memory input) private pure returns (uint256[] memory output) {
assembly {
output := input
}
}
/// @dev Helper: low level cast address comp function to uint256 comp function
function _castToUint256Comp(
function(address, address) pure returns (bool) input
) private pure returns (function(uint256, uint256) pure returns (bool) output) {
assembly {
output := input
}
}
/// @dev Helper: low level cast bytes32 comp function to uint256 comp function
function _castToUint256Comp(
function(bytes32, bytes32) pure returns (bool) input
) private pure returns (function(uint256, uint256) pure returns (bool) output) {
assembly {
output := input
}
}
/**
* @dev Searches a sorted `array` and returns the first index that contains
* a value greater or equal to `element`. If no such index exists (i.e. all
* values in the array are strictly less than `element`), the array length is
* returned. Time complexity O(log n).
*
* NOTE: The `array` is expected to be sorted in ascending order, and to
* contain no repeated elements.
*
* IMPORTANT: Deprecated. This implementation behaves as {lowerBound} but lacks
* support for repeated elements in the array. The {lowerBound} function should
* be used instead.
*/
function findUpperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
low = mid + 1;
}
}
// At this point `low` is the exclusive upper bound. We will return the inclusive upper bound.
if (low > 0 && unsafeAccess(array, low - 1).value == element) {
return low - 1;
} else {
return low;
}
}
/**
* @dev Searches an `array` sorted in ascending order and returns the first
* index that contains a value greater or equal than `element`. If no such index
* exists (i.e. all values in the array are strictly less than `element`), the array
* length is returned. Time complexity O(log n).
*
* See C++'s https://en.cppreference.com/w/cpp/algorithm/lower_bound[lower_bound].
*/
function lowerBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value < element) {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
} else {
high = mid;
}
}
return low;
}
/**
* @dev Searches an `array` sorted in ascending order and returns the first
* index that contains a value strictly greater than `element`. If no such index
* exists (i.e. all values in the array are strictly less than `element`), the array
* length is returned. Time complexity O(log n).
*
* See C++'s https://en.cppreference.com/w/cpp/algorithm/upper_bound[upper_bound].
*/
function upperBound(uint256[] storage array, uint256 element) internal view returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeAccess(array, mid).value > element) {
high = mid;
} else {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
}
}
return low;
}
/**
* @dev Same as {lowerBound}, but with an array in memory.
*/
function lowerBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeMemoryAccess(array, mid) < element) {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
} else {
high = mid;
}
}
return low;
}
/**
* @dev Same as {upperBound}, but with an array in memory.
*/
function upperBoundMemory(uint256[] memory array, uint256 element) internal pure returns (uint256) {
uint256 low = 0;
uint256 high = array.length;
if (high == 0) {
return 0;
}
while (low < high) {
uint256 mid = Math.average(low, high);
// Note that mid will always be strictly less than high (i.e. it will be a valid array index)
// because Math.average rounds towards zero (it does integer division with truncation).
if (unsafeMemoryAccess(array, mid) > element) {
high = mid;
} else {
// this cannot overflow because mid < high
unchecked {
low = mid + 1;
}
}
}
return low;
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(address[] storage arr, uint256 pos) internal pure returns (StorageSlot.AddressSlot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getAddressSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes32[] storage arr, uint256 pos) internal pure returns (StorageSlot.Bytes32Slot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getBytes32Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(uint256[] storage arr, uint256 pos) internal pure returns (StorageSlot.Uint256Slot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getUint256Slot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(bytes[] storage arr, uint256 pos) internal pure returns (StorageSlot.BytesSlot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getBytesSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeAccess(string[] storage arr, uint256 pos) internal pure returns (StorageSlot.StringSlot storage) {
bytes32 slot;
assembly ("memory-safe") {
slot := arr.slot
}
return slot.deriveArray().offset(pos).getStringSlot();
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(address[] memory arr, uint256 pos) internal pure returns (address res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(bytes32[] memory arr, uint256 pos) internal pure returns (bytes32 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(uint256[] memory arr, uint256 pos) internal pure returns (uint256 res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(bytes[] memory arr, uint256 pos) internal pure returns (bytes memory res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Access an array in an "unsafe" way. Skips solidity "index-out-of-range" check.
*
* WARNING: Only use if you are certain `pos` is lower than the array length.
*/
function unsafeMemoryAccess(string[] memory arr, uint256 pos) internal pure returns (string memory res) {
assembly {
res := mload(add(add(arr, 0x20), mul(pos, 0x20)))
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(address[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(bytes32[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(uint256[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(bytes[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
/**
* @dev Helper to set the length of a dynamic array. Directly writing to `.length` is forbidden.
*
* WARNING: this does not clear elements if length is reduced, of initialize elements if length is increased.
*/
function unsafeSetLength(string[] storage array, uint256 len) internal {
assembly ("memory-safe") {
sstore(array.slot, len)
}
}
}// SPDX-License-Identifier: Apache 2 pragma solidity ^0.8.4; // ┌──────────────────────────────────────────────────────────────────────────────┐ // │ NOTE: We can't define e.g. WORD_SIZE_MINUS_ONE via WORD_SIZE - 1 because │ // │ of solc restrictions on what constants can be used in inline assembly. │ // └──────────────────────────────────────────────────────────────────────────────┘ uint256 constant WORD_SIZE = 32; uint256 constant WORD_SIZE_MINUS_ONE = 31; //=0x1f=0b00011111 //see section "prefer `< MAX + 1` over `<= MAX` for const comparison" in docs/Optimization.md uint256 constant WORD_SIZE_PLUS_ONE = 33; uint256 constant SCRATCH_SPACE_PTR = 0x00; uint256 constant SCRATCH_SPACE_SIZE = 64; uint256 constant FREE_MEMORY_PTR = 0x40;
// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;
import {IERC20} from "IERC20/IERC20.sol";
import {SafeERC20} from "SafeERC20/SafeERC20.sol";
error PaymentFailure(address target);
//Note: Always forwards all gas, so consider gas griefing attack opportunities by the recipient.
//Note: Don't use this method if you need events for 0 amount transfers.
function tokenOrNativeTransfer(address tokenOrZeroForNative, address to, uint256 amount) {
if (amount == 0)
return;
if (tokenOrZeroForNative == address(0)) {
(bool success, ) = to.call{value: amount}(new bytes(0));
if (!success)
revert PaymentFailure(to);
}
else
SafeERC20.safeTransfer(IERC20(tokenOrZeroForNative), to, amount);
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;
import {WORD_SIZE} from "wormhole-sdk/constants/Common.sol";
//bubble up errors from low level calls
function reRevert(bytes memory err) pure {
assembly ("memory-safe") {
revert(add(err, WORD_SIZE), mload(err))
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.19;
error NotAnEvmAddress(bytes32);
function toUniversalAddress(address addr) pure returns (bytes32 universalAddr) {
universalAddr = bytes32(uint256(uint160(addr)));
}
function fromUniversalAddress(bytes32 universalAddr) pure returns (address addr) {
if (bytes12(universalAddr) != 0)
revert NotAnEvmAddress(universalAddr);
assembly ("memory-safe") {
addr := universalAddr
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;
import {WORD_SIZE, SCRATCH_SPACE_PTR, FREE_MEMORY_PTR} from "wormhole-sdk/constants/Common.sol";
function keccak256Word(bytes32 word) pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
mstore(SCRATCH_SPACE_PTR, word)
hash := keccak256(SCRATCH_SPACE_PTR, WORD_SIZE)
}
}
function keccak256SliceUnchecked(
bytes memory encoded,
uint offset,
uint length
) pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
// The length of the bytes type `length` field is that of a word in memory
let ptr := add(add(encoded, offset), WORD_SIZE)
hash := keccak256(ptr, length)
}
}
function keccak256Cd(
bytes calldata encoded
) pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
let freeMemory := mload(FREE_MEMORY_PTR)
calldatacopy(freeMemory, encoded.offset, encoded.length)
hash := keccak256(freeMemory, encoded.length)
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;
//see Optimization.md for rationale on avoiding short-circuiting
function eagerAnd(bool lhs, bool rhs) pure returns (bool ret) {
/// @solidity memory-safe-assembly
assembly {
ret := and(lhs, rhs)
}
}
//see Optimization.md for rationale on avoiding short-circuiting
function eagerOr(bool lhs, bool rhs) pure returns (bool ret) {
/// @solidity memory-safe-assembly
assembly {
ret := or(lhs, rhs)
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Comparators.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides a set of functions to compare values.
*
* _Available since v5.1._
*/
library Comparators {
function lt(uint256 a, uint256 b) internal pure returns (bool) {
return a < b;
}
function gt(uint256 a, uint256 b) internal pure returns (bool) {
return a > b;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/SlotDerivation.sol)
// This file was procedurally generated from scripts/generate/templates/SlotDerivation.js.
pragma solidity ^0.8.20;
/**
* @dev Library for computing storage (and transient storage) locations from namespaces and deriving slots
* corresponding to standard patterns. The derivation method for array and mapping matches the storage layout used by
* the solidity language / compiler.
*
* See https://docs.soliditylang.org/en/v0.8.20/internals/layout_in_storage.html#mappings-and-dynamic-arrays[Solidity docs for mappings and dynamic arrays.].
*
* Example usage:
* ```solidity
* contract Example {
* // Add the library methods
* using StorageSlot for bytes32;
* using SlotDerivation for bytes32;
*
* // Declare a namespace
* string private constant _NAMESPACE = "<namespace>"; // eg. OpenZeppelin.Slot
*
* function setValueInNamespace(uint256 key, address newValue) internal {
* _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value = newValue;
* }
*
* function getValueInNamespace(uint256 key) internal view returns (address) {
* return _NAMESPACE.erc7201Slot().deriveMapping(key).getAddressSlot().value;
* }
* }
* ```
*
* TIP: Consider using this library along with {StorageSlot}.
*
* NOTE: This library provides a way to manipulate storage locations in a non-standard way. Tooling for checking
* upgrade safety will ignore the slots accessed through this library.
*
* _Available since v5.1._
*/
library SlotDerivation {
/**
* @dev Derive an ERC-7201 slot from a string (namespace).
*/
function erc7201Slot(string memory namespace) internal pure returns (bytes32 slot) {
assembly ("memory-safe") {
mstore(0x00, sub(keccak256(add(namespace, 0x20), mload(namespace)), 1))
slot := and(keccak256(0x00, 0x20), not(0xff))
}
}
/**
* @dev Add an offset to a slot to get the n-th element of a structure or an array.
*/
function offset(bytes32 slot, uint256 pos) internal pure returns (bytes32 result) {
unchecked {
return bytes32(uint256(slot) + pos);
}
}
/**
* @dev Derive the location of the first element in an array from the slot where the length is stored.
*/
function deriveArray(bytes32 slot) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, slot)
result := keccak256(0x00, 0x20)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, address key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, and(key, shr(96, not(0))))
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, bool key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, iszero(iszero(key)))
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, bytes32 key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, key)
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, uint256 key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, key)
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, int256 key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
mstore(0x00, key)
mstore(0x20, slot)
result := keccak256(0x00, 0x40)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, string memory key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
let length := mload(key)
let begin := add(key, 0x20)
let end := add(begin, length)
let cache := mload(end)
mstore(end, slot)
result := keccak256(begin, add(length, 0x20))
mstore(end, cache)
}
}
/**
* @dev Derive the location of a mapping element from the key.
*/
function deriveMapping(bytes32 slot, bytes memory key) internal pure returns (bytes32 result) {
assembly ("memory-safe") {
let length := mload(key)
let begin := add(key, 0x20)
let end := add(begin, length)
let cache := mload(end)
mstore(end, slot)
result := keccak256(begin, add(length, 0x20))
mstore(end, cache)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
pragma solidity ^0.8.20;
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/
library StorageSlot {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
struct Int256Slot {
int256 value;
}
struct StringSlot {
string value;
}
struct BytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `Int256Slot` with member `value` located at `slot`.
*/
function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns a `StringSlot` with member `value` located at `slot`.
*/
function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/
function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
/**
* @dev Returns a `BytesSlot` with member `value` located at `slot`.
*/
function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/
function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
assembly ("memory-safe") {
r.slot := store.slot
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.3.0) (utils/math/Math.sol)
pragma solidity ^0.8.20;
import {Panic} from "../Panic.sol";
import {SafeCast} from "./SafeCast.sol";
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Floor, // Toward negative infinity
Ceil, // Toward positive infinity
Trunc, // Toward zero
Expand // Away from zero
}
/**
* @dev Return the 512-bit addition of two uint256.
*
* The result is stored in two 256 variables such that sum = high * 2²⁵⁶ + low.
*/
function add512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
assembly ("memory-safe") {
low := add(a, b)
high := lt(low, a)
}
}
/**
* @dev Return the 512-bit multiplication of two uint256.
*
* The result is stored in two 256 variables such that product = high * 2²⁵⁶ + low.
*/
function mul512(uint256 a, uint256 b) internal pure returns (uint256 high, uint256 low) {
// 512-bit multiply [high low] = x * y. Compute the product mod 2²⁵⁶ and mod 2²⁵⁶ - 1, then use
// the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = high * 2²⁵⁶ + low.
assembly ("memory-safe") {
let mm := mulmod(a, b, not(0))
low := mul(a, b)
high := sub(sub(mm, low), lt(mm, low))
}
}
/**
* @dev Returns the addition of two unsigned integers, with a success flag (no overflow).
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a + b;
success = c >= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the subtraction of two unsigned integers, with a success flag (no overflow).
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a - b;
success = c <= a;
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the multiplication of two unsigned integers, with a success flag (no overflow).
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
uint256 c = a * b;
assembly ("memory-safe") {
// Only true when the multiplication doesn't overflow
// (c / a == b) || (a == 0)
success := or(eq(div(c, a), b), iszero(a))
}
// equivalent to: success ? c : 0
result = c * SafeCast.toUint(success);
}
}
/**
* @dev Returns the division of two unsigned integers, with a success flag (no division by zero).
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `DIV` opcode returns zero when the denominator is 0.
result := div(a, b)
}
}
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a success flag (no division by zero).
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool success, uint256 result) {
unchecked {
success = b > 0;
assembly ("memory-safe") {
// The `MOD` opcode returns zero when the denominator is 0.
result := mod(a, b)
}
}
}
/**
* @dev Unsigned saturating addition, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingAdd(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryAdd(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Unsigned saturating subtraction, bounds to zero instead of overflowing.
*/
function saturatingSub(uint256 a, uint256 b) internal pure returns (uint256) {
(, uint256 result) = trySub(a, b);
return result;
}
/**
* @dev Unsigned saturating multiplication, bounds to `2²⁵⁶ - 1` instead of overflowing.
*/
function saturatingMul(uint256 a, uint256 b) internal pure returns (uint256) {
(bool success, uint256 result) = tryMul(a, b);
return ternary(success, result, type(uint256).max);
}
/**
* @dev Branchless ternary evaluation for `a ? b : c`. Gas costs are constant.
*
* IMPORTANT: This function may reduce bytecode size and consume less gas when used standalone.
* However, the compiler may optimize Solidity ternary operations (i.e. `a ? b : c`) to only compute
* one branch when needed, making this function more expensive.
*/
function ternary(bool condition, uint256 a, uint256 b) internal pure returns (uint256) {
unchecked {
// branchless ternary works because:
// b ^ (a ^ b) == a
// b ^ 0 == b
return b ^ ((a ^ b) * SafeCast.toUint(condition));
}
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a > b, a, b);
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return ternary(a < b, a, b);
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds towards infinity instead
* of rounding towards zero.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
// Guarantee the same behavior as in a regular Solidity division.
Panic.panic(Panic.DIVISION_BY_ZERO);
}
// The following calculation ensures accurate ceiling division without overflow.
// Since a is non-zero, (a - 1) / b will not overflow.
// The largest possible result occurs when (a - 1) / b is type(uint256).max,
// but the largest value we can obtain is type(uint256).max - 1, which happens
// when a = type(uint256).max and b = 1.
unchecked {
return SafeCast.toUint(a > 0) * ((a - 1) / b + 1);
}
}
/**
* @dev Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or
* denominator == 0.
*
* Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) with further edits by
* Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
// Handle non-overflow cases, 256 by 256 division.
if (high == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return low / denominator;
}
// Make sure the result is less than 2²⁵⁶. Also prevents denominator == 0.
if (denominator <= high) {
Panic.panic(ternary(denominator == 0, Panic.DIVISION_BY_ZERO, Panic.UNDER_OVERFLOW));
}
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [high low].
uint256 remainder;
assembly ("memory-safe") {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
high := sub(high, gt(remainder, low))
low := sub(low, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator.
// Always >= 1. See https://cs.stackexchange.com/q/138556/92363.
uint256 twos = denominator & (0 - denominator);
assembly ("memory-safe") {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [high low] by twos.
low := div(low, twos)
// Flip twos such that it is 2²⁵⁶ / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from high into low.
low |= high * twos;
// Invert denominator mod 2²⁵⁶. Now that denominator is an odd number, it has an inverse modulo 2²⁵⁶ such
// that denominator * inv ≡ 1 mod 2²⁵⁶. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv ≡ 1 mod 2⁴.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also
// works in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2⁸
inverse *= 2 - denominator * inverse; // inverse mod 2¹⁶
inverse *= 2 - denominator * inverse; // inverse mod 2³²
inverse *= 2 - denominator * inverse; // inverse mod 2⁶⁴
inverse *= 2 - denominator * inverse; // inverse mod 2¹²⁸
inverse *= 2 - denominator * inverse; // inverse mod 2²⁵⁶
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2²⁵⁶. Since the preconditions guarantee that the outcome is
// less than 2²⁵⁶, this is the final result. We don't need to compute the high bits of the result and high
// is no longer required.
result = low * inverse;
return result;
}
}
/**
* @dev Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
return mulDiv(x, y, denominator) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0);
}
/**
* @dev Calculates floor(x * y >> n) with full precision. Throws if result overflows a uint256.
*/
function mulShr(uint256 x, uint256 y, uint8 n) internal pure returns (uint256 result) {
unchecked {
(uint256 high, uint256 low) = mul512(x, y);
if (high >= 1 << n) {
Panic.panic(Panic.UNDER_OVERFLOW);
}
return (high << (256 - n)) | (low >> n);
}
}
/**
* @dev Calculates x * y >> n with full precision, following the selected rounding direction.
*/
function mulShr(uint256 x, uint256 y, uint8 n, Rounding rounding) internal pure returns (uint256) {
return mulShr(x, y, n) + SafeCast.toUint(unsignedRoundsUp(rounding) && mulmod(x, y, 1 << n) > 0);
}
/**
* @dev Calculate the modular multiplicative inverse of a number in Z/nZ.
*
* If n is a prime, then Z/nZ is a field. In that case all elements are inversible, except 0.
* If n is not a prime, then Z/nZ is not a field, and some elements might not be inversible.
*
* If the input value is not inversible, 0 is returned.
*
* NOTE: If you know for sure that n is (big) a prime, it may be cheaper to use Fermat's little theorem and get the
* inverse using `Math.modExp(a, n - 2, n)`. See {invModPrime}.
*/
function invMod(uint256 a, uint256 n) internal pure returns (uint256) {
unchecked {
if (n == 0) return 0;
// The inverse modulo is calculated using the Extended Euclidean Algorithm (iterative version)
// Used to compute integers x and y such that: ax + ny = gcd(a, n).
// When the gcd is 1, then the inverse of a modulo n exists and it's x.
// ax + ny = 1
// ax = 1 + (-y)n
// ax ≡ 1 (mod n) # x is the inverse of a modulo n
// If the remainder is 0 the gcd is n right away.
uint256 remainder = a % n;
uint256 gcd = n;
// Therefore the initial coefficients are:
// ax + ny = gcd(a, n) = n
// 0a + 1n = n
int256 x = 0;
int256 y = 1;
while (remainder != 0) {
uint256 quotient = gcd / remainder;
(gcd, remainder) = (
// The old remainder is the next gcd to try.
remainder,
// Compute the next remainder.
// Can't overflow given that (a % gcd) * (gcd // (a % gcd)) <= gcd
// where gcd is at most n (capped to type(uint256).max)
gcd - remainder * quotient
);
(x, y) = (
// Increment the coefficient of a.
y,
// Decrement the coefficient of n.
// Can overflow, but the result is casted to uint256 so that the
// next value of y is "wrapped around" to a value between 0 and n - 1.
x - y * int256(quotient)
);
}
if (gcd != 1) return 0; // No inverse exists.
return ternary(x < 0, n - uint256(-x), uint256(x)); // Wrap the result if it's negative.
}
}
/**
* @dev Variant of {invMod}. More efficient, but only works if `p` is known to be a prime greater than `2`.
*
* From https://en.wikipedia.org/wiki/Fermat%27s_little_theorem[Fermat's little theorem], we know that if p is
* prime, then `a**(p-1) ≡ 1 mod p`. As a consequence, we have `a * a**(p-2) ≡ 1 mod p`, which means that
* `a**(p-2)` is the modular multiplicative inverse of a in Fp.
*
* NOTE: this function does NOT check that `p` is a prime greater than `2`.
*/
function invModPrime(uint256 a, uint256 p) internal view returns (uint256) {
unchecked {
return Math.modExp(a, p - 2, p);
}
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m)
*
* Requirements:
* - modulus can't be zero
* - underlying staticcall to precompile must succeed
*
* IMPORTANT: The result is only valid if the underlying call succeeds. When using this function, make
* sure the chain you're using it on supports the precompiled contract for modular exponentiation
* at address 0x05 as specified in https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise,
* the underlying function will succeed given the lack of a revert, but the result may be incorrectly
* interpreted as 0.
*/
function modExp(uint256 b, uint256 e, uint256 m) internal view returns (uint256) {
(bool success, uint256 result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Returns the modular exponentiation of the specified base, exponent and modulus (b ** e % m).
* It includes a success flag indicating if the operation succeeded. Operation will be marked as failed if trying
* to operate modulo 0 or if the underlying precompile reverted.
*
* IMPORTANT: The result is only valid if the success flag is true. When using this function, make sure the chain
* you're using it on supports the precompiled contract for modular exponentiation at address 0x05 as specified in
* https://eips.ethereum.org/EIPS/eip-198[EIP-198]. Otherwise, the underlying function will succeed given the lack
* of a revert, but the result may be incorrectly interpreted as 0.
*/
function tryModExp(uint256 b, uint256 e, uint256 m) internal view returns (bool success, uint256 result) {
if (m == 0) return (false, 0);
assembly ("memory-safe") {
let ptr := mload(0x40)
// | Offset | Content | Content (Hex) |
// |-----------|------------|--------------------------------------------------------------------|
// | 0x00:0x1f | size of b | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x20:0x3f | size of e | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x40:0x5f | size of m | 0x0000000000000000000000000000000000000000000000000000000000000020 |
// | 0x60:0x7f | value of b | 0x<.............................................................b> |
// | 0x80:0x9f | value of e | 0x<.............................................................e> |
// | 0xa0:0xbf | value of m | 0x<.............................................................m> |
mstore(ptr, 0x20)
mstore(add(ptr, 0x20), 0x20)
mstore(add(ptr, 0x40), 0x20)
mstore(add(ptr, 0x60), b)
mstore(add(ptr, 0x80), e)
mstore(add(ptr, 0xa0), m)
// Given the result < m, it's guaranteed to fit in 32 bytes,
// so we can use the memory scratch space located at offset 0.
success := staticcall(gas(), 0x05, ptr, 0xc0, 0x00, 0x20)
result := mload(0x00)
}
}
/**
* @dev Variant of {modExp} that supports inputs of arbitrary length.
*/
function modExp(bytes memory b, bytes memory e, bytes memory m) internal view returns (bytes memory) {
(bool success, bytes memory result) = tryModExp(b, e, m);
if (!success) {
Panic.panic(Panic.DIVISION_BY_ZERO);
}
return result;
}
/**
* @dev Variant of {tryModExp} that supports inputs of arbitrary length.
*/
function tryModExp(
bytes memory b,
bytes memory e,
bytes memory m
) internal view returns (bool success, bytes memory result) {
if (_zeroBytes(m)) return (false, new bytes(0));
uint256 mLen = m.length;
// Encode call args in result and move the free memory pointer
result = abi.encodePacked(b.length, e.length, mLen, b, e, m);
assembly ("memory-safe") {
let dataPtr := add(result, 0x20)
// Write result on top of args to avoid allocating extra memory.
success := staticcall(gas(), 0x05, dataPtr, mload(result), dataPtr, mLen)
// Overwrite the length.
// result.length > returndatasize() is guaranteed because returndatasize() == m.length
mstore(result, mLen)
// Set the memory pointer after the returned data.
mstore(0x40, add(dataPtr, mLen))
}
}
/**
* @dev Returns whether the provided byte array is zero.
*/
function _zeroBytes(bytes memory byteArray) private pure returns (bool) {
for (uint256 i = 0; i < byteArray.length; ++i) {
if (byteArray[i] != 0) {
return false;
}
}
return true;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded
* towards zero.
*
* This method is based on Newton's method for computing square roots; the algorithm is restricted to only
* using integer operations.
*/
function sqrt(uint256 a) internal pure returns (uint256) {
unchecked {
// Take care of easy edge cases when a == 0 or a == 1
if (a <= 1) {
return a;
}
// In this function, we use Newton's method to get a root of `f(x) := x² - a`. It involves building a
// sequence x_n that converges toward sqrt(a). For each iteration x_n, we also define the error between
// the current value as `ε_n = | x_n - sqrt(a) |`.
//
// For our first estimation, we consider `e` the smallest power of 2 which is bigger than the square root
// of the target. (i.e. `2**(e-1) ≤ sqrt(a) < 2**e`). We know that `e ≤ 128` because `(2¹²⁸)² = 2²⁵⁶` is
// bigger than any uint256.
//
// By noticing that
// `2**(e-1) ≤ sqrt(a) < 2**e → (2**(e-1))² ≤ a < (2**e)² → 2**(2*e-2) ≤ a < 2**(2*e)`
// we can deduce that `e - 1` is `log2(a) / 2`. We can thus compute `x_n = 2**(e-1)` using a method similar
// to the msb function.
uint256 aa = a;
uint256 xn = 1;
if (aa >= (1 << 128)) {
aa >>= 128;
xn <<= 64;
}
if (aa >= (1 << 64)) {
aa >>= 64;
xn <<= 32;
}
if (aa >= (1 << 32)) {
aa >>= 32;
xn <<= 16;
}
if (aa >= (1 << 16)) {
aa >>= 16;
xn <<= 8;
}
if (aa >= (1 << 8)) {
aa >>= 8;
xn <<= 4;
}
if (aa >= (1 << 4)) {
aa >>= 4;
xn <<= 2;
}
if (aa >= (1 << 2)) {
xn <<= 1;
}
// We now have x_n such that `x_n = 2**(e-1) ≤ sqrt(a) < 2**e = 2 * x_n`. This implies ε_n ≤ 2**(e-1).
//
// We can refine our estimation by noticing that the middle of that interval minimizes the error.
// If we move x_n to equal 2**(e-1) + 2**(e-2), then we reduce the error to ε_n ≤ 2**(e-2).
// This is going to be our x_0 (and ε_0)
xn = (3 * xn) >> 1; // ε_0 := | x_0 - sqrt(a) | ≤ 2**(e-2)
// From here, Newton's method give us:
// x_{n+1} = (x_n + a / x_n) / 2
//
// One should note that:
// x_{n+1}² - a = ((x_n + a / x_n) / 2)² - a
// = ((x_n² + a) / (2 * x_n))² - a
// = (x_n⁴ + 2 * a * x_n² + a²) / (4 * x_n²) - a
// = (x_n⁴ + 2 * a * x_n² + a² - 4 * a * x_n²) / (4 * x_n²)
// = (x_n⁴ - 2 * a * x_n² + a²) / (4 * x_n²)
// = (x_n² - a)² / (2 * x_n)²
// = ((x_n² - a) / (2 * x_n))²
// ≥ 0
// Which proves that for all n ≥ 1, sqrt(a) ≤ x_n
//
// This gives us the proof of quadratic convergence of the sequence:
// ε_{n+1} = | x_{n+1} - sqrt(a) |
// = | (x_n + a / x_n) / 2 - sqrt(a) |
// = | (x_n² + a - 2*x_n*sqrt(a)) / (2 * x_n) |
// = | (x_n - sqrt(a))² / (2 * x_n) |
// = | ε_n² / (2 * x_n) |
// = ε_n² / | (2 * x_n) |
//
// For the first iteration, we have a special case where x_0 is known:
// ε_1 = ε_0² / | (2 * x_0) |
// ≤ (2**(e-2))² / (2 * (2**(e-1) + 2**(e-2)))
// ≤ 2**(2*e-4) / (3 * 2**(e-1))
// ≤ 2**(e-3) / 3
// ≤ 2**(e-3-log2(3))
// ≤ 2**(e-4.5)
//
// For the following iterations, we use the fact that, 2**(e-1) ≤ sqrt(a) ≤ x_n:
// ε_{n+1} = ε_n² / | (2 * x_n) |
// ≤ (2**(e-k))² / (2 * 2**(e-1))
// ≤ 2**(2*e-2*k) / 2**e
// ≤ 2**(e-2*k)
xn = (xn + a / xn) >> 1; // ε_1 := | x_1 - sqrt(a) | ≤ 2**(e-4.5) -- special case, see above
xn = (xn + a / xn) >> 1; // ε_2 := | x_2 - sqrt(a) | ≤ 2**(e-9) -- general case with k = 4.5
xn = (xn + a / xn) >> 1; // ε_3 := | x_3 - sqrt(a) | ≤ 2**(e-18) -- general case with k = 9
xn = (xn + a / xn) >> 1; // ε_4 := | x_4 - sqrt(a) | ≤ 2**(e-36) -- general case with k = 18
xn = (xn + a / xn) >> 1; // ε_5 := | x_5 - sqrt(a) | ≤ 2**(e-72) -- general case with k = 36
xn = (xn + a / xn) >> 1; // ε_6 := | x_6 - sqrt(a) | ≤ 2**(e-144) -- general case with k = 72
// Because e ≤ 128 (as discussed during the first estimation phase), we know have reached a precision
// ε_6 ≤ 2**(e-144) < 1. Given we're operating on integers, then we can ensure that xn is now either
// sqrt(a) or sqrt(a) + 1.
return xn - SafeCast.toUint(xn > a / xn);
}
}
/**
* @dev Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && result * result < a);
}
}
/**
* @dev Return the log in base 2 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log2(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// If upper 8 bits of 16-bit half set, add 8 to result
r |= SafeCast.toUint((x >> r) > 0xff) << 3;
// If upper 4 bits of 8-bit half set, add 4 to result
r |= SafeCast.toUint((x >> r) > 0xf) << 2;
// Shifts value right by the current result and use it as an index into this lookup table:
//
// | x (4 bits) | index | table[index] = MSB position |
// |------------|---------|-----------------------------|
// | 0000 | 0 | table[0] = 0 |
// | 0001 | 1 | table[1] = 0 |
// | 0010 | 2 | table[2] = 1 |
// | 0011 | 3 | table[3] = 1 |
// | 0100 | 4 | table[4] = 2 |
// | 0101 | 5 | table[5] = 2 |
// | 0110 | 6 | table[6] = 2 |
// | 0111 | 7 | table[7] = 2 |
// | 1000 | 8 | table[8] = 3 |
// | 1001 | 9 | table[9] = 3 |
// | 1010 | 10 | table[10] = 3 |
// | 1011 | 11 | table[11] = 3 |
// | 1100 | 12 | table[12] = 3 |
// | 1101 | 13 | table[13] = 3 |
// | 1110 | 14 | table[14] = 3 |
// | 1111 | 15 | table[15] = 3 |
//
// The lookup table is represented as a 32-byte value with the MSB positions for 0-15 in the last 16 bytes.
assembly ("memory-safe") {
r := or(r, byte(shr(r, x), 0x0000010102020202030303030303030300000000000000000000000000000000))
}
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << result < value);
}
}
/**
* @dev Return the log in base 10 of a positive value rounded towards zero.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 10 ** result < value);
}
}
/**
* @dev Return the log in base 256 of a positive value rounded towards zero.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 x) internal pure returns (uint256 r) {
// If value has upper 128 bits set, log2 result is at least 128
r = SafeCast.toUint(x > 0xffffffffffffffffffffffffffffffff) << 7;
// If upper 64 bits of 128-bit half set, add 64 to result
r |= SafeCast.toUint((x >> r) > 0xffffffffffffffff) << 6;
// If upper 32 bits of 64-bit half set, add 32 to result
r |= SafeCast.toUint((x >> r) > 0xffffffff) << 5;
// If upper 16 bits of 32-bit half set, add 16 to result
r |= SafeCast.toUint((x >> r) > 0xffff) << 4;
// Add 1 if upper 8 bits of 16-bit half set, and divide accumulated result by 8
return (r >> 3) | SafeCast.toUint((x >> r) > 0xff);
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + SafeCast.toUint(unsignedRoundsUp(rounding) && 1 << (result << 3) < value);
}
}
/**
* @dev Returns whether a provided rounding mode is considered rounding up for unsigned integers.
*/
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.0;
//https://eips.ethereum.org/EIPS/eip-20
interface IERC20 {
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function allowance(address owner, address spender) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address from, address to, uint256 amount) external returns (bool);
}// SPDX-License-Identifier: Apache 2
pragma solidity ^0.8.4;
import {IERC20} from "IERC20/IERC20.sol";
import {WORD_SIZE, SCRATCH_SPACE_PTR} from "wormhole-sdk/constants/Common.sol";
//Like OpenZeppelin's SafeERC20.sol, but slimmed down and more gas efficient.
//
//The main difference to OZ's implementation (besides the missing functions) is that we skip the
// EXTCODESIZE check that OZ does upon successful calls to ensure that an actual contract was
// called. The rationale for omitting this check is that ultimately the contract using the token
// has to verify that it "makes sense" for its use case regardless. Otherwise, a random token, or
// even just a contract that always returns true, could be passed, which makes this check
// superfluous in the final analysis.
//
//We also save on code size by not duplicating the assembly code in two separate functions.
// Otoh, we simply swallow revert reasons of failing token operations instead of bubbling them up.
// This is less clean and makes debugging harder, but is likely still a worthwhile trade-off
// given the cost in gas and code size.
library SafeERC20 {
error SafeERC20FailedOperation(address token);
function safeTransfer(IERC20 token, address to, uint256 value) internal {
_revertOnFailure(token, abi.encodeCall(token.transfer, (to, value)));
}
function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
_revertOnFailure(token, abi.encodeCall(token.transferFrom, (from, to, value)));
}
function forceApprove(IERC20 token, address spender, uint256 value) internal {
bytes memory approveCall = abi.encodeCall(token.approve, (spender, value));
if (!_callWithOptionalReturnCheck(token, approveCall)) {
_revertOnFailure(token, abi.encodeCall(token.approve, (spender, 0)));
_revertOnFailure(token, approveCall);
}
}
function _callWithOptionalReturnCheck(
IERC20 token,
bytes memory encodedCall
) private returns (bool success) {
/// @solidity memory-safe-assembly
assembly {
mstore(SCRATCH_SPACE_PTR, 0)
success := call( //see https://www.evm.codes/?fork=cancun#f1
gas(), //gas
token, //callee
0, //value
add(encodedCall, WORD_SIZE), //input ptr
mload(encodedCall), //input size
SCRATCH_SPACE_PTR, //output ptr
WORD_SIZE //output size
)
//calls to addresses without code are always successful
if success {
success := or(iszero(returndatasize()), mload(SCRATCH_SPACE_PTR))
}
}
}
function _revertOnFailure(IERC20 token, bytes memory encodedCall) private {
if (!_callWithOptionalReturnCheck(token, encodedCall))
revert SafeERC20FailedOperation(address(token));
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/Panic.sol)
pragma solidity ^0.8.20;
/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*
* _Available since v5.1._
*/
// slither-disable-next-line unused-state
library Panic {
/// @dev generic / unspecified error
uint256 internal constant GENERIC = 0x00;
/// @dev used by the assert() builtin
uint256 internal constant ASSERT = 0x01;
/// @dev arithmetic underflow or overflow
uint256 internal constant UNDER_OVERFLOW = 0x11;
/// @dev division or modulo by zero
uint256 internal constant DIVISION_BY_ZERO = 0x12;
/// @dev enum conversion error
uint256 internal constant ENUM_CONVERSION_ERROR = 0x21;
/// @dev invalid encoding in storage
uint256 internal constant STORAGE_ENCODING_ERROR = 0x22;
/// @dev empty array pop
uint256 internal constant EMPTY_ARRAY_POP = 0x31;
/// @dev array out of bounds access
uint256 internal constant ARRAY_OUT_OF_BOUNDS = 0x32;
/// @dev resource error (too large allocation or too large array)
uint256 internal constant RESOURCE_ERROR = 0x41;
/// @dev calling invalid internal function
uint256 internal constant INVALID_INTERNAL_FUNCTION = 0x51;
/// @dev Reverts with a panic code. Recommended to use with
/// the internal constants with predefined codes.
function panic(uint256 code) internal pure {
assembly ("memory-safe") {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol)
// This file was procedurally generated from scripts/generate/templates/SafeCast.js.
pragma solidity ^0.8.20;
/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeCast {
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/
error SafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/
error SafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toUint248(uint256 value) internal pure returns (uint248) {
if (value > type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
return uint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toUint240(uint256 value) internal pure returns (uint240) {
if (value > type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
return uint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toUint232(uint256 value) internal pure returns (uint232) {
if (value > type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
return uint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toUint224(uint256 value) internal pure returns (uint224) {
if (value > type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
return uint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toUint216(uint256 value) internal pure returns (uint216) {
if (value > type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
return uint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toUint208(uint256 value) internal pure returns (uint208) {
if (value > type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
return uint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toUint200(uint256 value) internal pure returns (uint200) {
if (value > type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
return uint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toUint192(uint256 value) internal pure returns (uint192) {
if (value > type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
return uint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toUint184(uint256 value) internal pure returns (uint184) {
if (value > type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
return uint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toUint176(uint256 value) internal pure returns (uint176) {
if (value > type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
return uint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toUint168(uint256 value) internal pure returns (uint168) {
if (value > type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
return uint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toUint160(uint256 value) internal pure returns (uint160) {
if (value > type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
return uint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toUint152(uint256 value) internal pure returns (uint152) {
if (value > type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
return uint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toUint144(uint256 value) internal pure returns (uint144) {
if (value > type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
return uint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toUint136(uint256 value) internal pure returns (uint136) {
if (value > type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
return uint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toUint128(uint256 value) internal pure returns (uint128) {
if (value > type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
return uint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toUint120(uint256 value) internal pure returns (uint120) {
if (value > type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
return uint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toUint112(uint256 value) internal pure returns (uint112) {
if (value > type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
return uint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toUint104(uint256 value) internal pure returns (uint104) {
if (value > type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
return uint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toUint96(uint256 value) internal pure returns (uint96) {
if (value > type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
return uint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toUint88(uint256 value) internal pure returns (uint88) {
if (value > type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
return uint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toUint80(uint256 value) internal pure returns (uint80) {
if (value > type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
return uint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toUint72(uint256 value) internal pure returns (uint72) {
if (value > type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
return uint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toUint64(uint256 value) internal pure returns (uint64) {
if (value > type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
return uint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toUint56(uint256 value) internal pure returns (uint56) {
if (value > type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
return uint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toUint48(uint256 value) internal pure returns (uint48) {
if (value > type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
return uint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toUint40(uint256 value) internal pure returns (uint40) {
if (value > type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
return uint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toUint32(uint256 value) internal pure returns (uint32) {
if (value > type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
return uint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toUint24(uint256 value) internal pure returns (uint24) {
if (value > type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
return uint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toUint16(uint256 value) internal pure returns (uint16) {
if (value > type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
return uint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toUint8(uint256 value) internal pure returns (uint8) {
if (value > type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
return uint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/
function toUint256(int256 value) internal pure returns (uint256) {
if (value < 0) {
revert SafeCastOverflowedIntToUint(value);
}
return uint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/
function toInt248(int256 value) internal pure returns (int248 downcasted) {
downcasted = int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/
function toInt240(int256 value) internal pure returns (int240 downcasted) {
downcasted = int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/
function toInt232(int256 value) internal pure returns (int232 downcasted) {
downcasted = int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/
function toInt224(int256 value) internal pure returns (int224 downcasted) {
downcasted = int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/
function toInt216(int256 value) internal pure returns (int216 downcasted) {
downcasted = int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/
function toInt208(int256 value) internal pure returns (int208 downcasted) {
downcasted = int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/
function toInt200(int256 value) internal pure returns (int200 downcasted) {
downcasted = int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/
function toInt192(int256 value) internal pure returns (int192 downcasted) {
downcasted = int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/
function toInt184(int256 value) internal pure returns (int184 downcasted) {
downcasted = int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/
function toInt176(int256 value) internal pure returns (int176 downcasted) {
downcasted = int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/
function toInt168(int256 value) internal pure returns (int168 downcasted) {
downcasted = int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/
function toInt160(int256 value) internal pure returns (int160 downcasted) {
downcasted = int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/
function toInt152(int256 value) internal pure returns (int152 downcasted) {
downcasted = int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/
function toInt144(int256 value) internal pure returns (int144 downcasted) {
downcasted = int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/
function toInt136(int256 value) internal pure returns (int136 downcasted) {
downcasted = int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/
function toInt128(int256 value) internal pure returns (int128 downcasted) {
downcasted = int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/
function toInt120(int256 value) internal pure returns (int120 downcasted) {
downcasted = int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/
function toInt112(int256 value) internal pure returns (int112 downcasted) {
downcasted = int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/
function toInt104(int256 value) internal pure returns (int104 downcasted) {
downcasted = int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/
function toInt96(int256 value) internal pure returns (int96 downcasted) {
downcasted = int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/
function toInt88(int256 value) internal pure returns (int88 downcasted) {
downcasted = int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/
function toInt80(int256 value) internal pure returns (int80 downcasted) {
downcasted = int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/
function toInt72(int256 value) internal pure returns (int72 downcasted) {
downcasted = int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/
function toInt64(int256 value) internal pure returns (int64 downcasted) {
downcasted = int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/
function toInt56(int256 value) internal pure returns (int56 downcasted) {
downcasted = int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/
function toInt48(int256 value) internal pure returns (int48 downcasted) {
downcasted = int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/
function toInt40(int256 value) internal pure returns (int40 downcasted) {
downcasted = int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/
function toInt32(int256 value) internal pure returns (int32 downcasted) {
downcasted = int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/
function toInt24(int256 value) internal pure returns (int24 downcasted) {
downcasted = int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/
function toInt16(int256 value) internal pure returns (int16 downcasted) {
downcasted = int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/
function toInt8(int256 value) internal pure returns (int8 downcasted) {
downcasted = int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/
function toInt256(uint256 value) internal pure returns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive
if (value > uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
return int256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/
function toUint(bool b) internal pure returns (uint256 u) {
assembly ("memory-safe") {
u := iszero(iszero(b))
}
}
}{
"remappings": [
"@makina-periphery/=lib/makina-periphery/src/",
"@makina-core/=lib/makina-core/src/",
"@solady/=lib/solady/src/",
"@aave/=lib/makina-periphery/lib/aave-v3-origin/src/contracts/",
"@balancer-labs/=lib/makina-periphery/lib/balancer-v2-monorepo/../../node_modules/@balancer-labs/",
"@balancer-v2-interfaces/=lib/makina-periphery/lib/balancer-v2-monorepo/pkg/interfaces/contracts/",
"@balancer-v3-interfaces/=lib/makina-periphery/lib/balancer-v3-monorepo/pkg/interfaces/contracts/",
"@enso-weiroll/=lib/makina-core/lib/enso-weiroll/contracts/",
"@makina-core-script/=lib/makina-periphery/lib/makina-core/script/",
"@makina-core-test/=lib/makina-periphery/lib/makina-core/test/",
"@morpho/=lib/makina-periphery/lib/morpho-blue/src/",
"@openzeppelin/contracts-upgradeable/=lib/makina-periphery/lib/openzeppelin-contracts-upgradeable/contracts/",
"@openzeppelin/contracts/=lib/makina-periphery/lib/openzeppelin-contracts/contracts/",
"@wormhole/sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/",
"IERC20/=lib/makina-core/lib/wormhole-solidity-sdk/src/interfaces/token/",
"SafeERC20/=lib/makina-core/lib/wormhole-solidity-sdk/src/libraries/",
"aave-v3-origin/=lib/makina-periphery/lib/aave-v3-origin/",
"balancer-v2-monorepo/=lib/makina-periphery/lib/",
"balancer-v3-monorepo/=lib/makina-periphery/lib/",
"ds-test/=lib/makina-periphery/lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/",
"enso-weiroll/=lib/makina-core/lib/enso-weiroll/contracts/",
"erc4626-tests/=lib/makina-periphery/lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/makina-periphery/lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"makina-core/=lib/makina-core/",
"makina-periphery/=lib/makina-periphery/",
"morpho-blue/=lib/makina-periphery/lib/morpho-blue/",
"openzeppelin-contracts-upgradeable/=lib/makina-periphery/lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/makina-periphery/lib/openzeppelin-contracts/",
"solady/=lib/solady/src/",
"solidity-utils/=lib/makina-periphery/lib/aave-v3-origin/lib/solidity-utils/",
"wormhole-sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/",
"wormhole-solidity-sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/"
],
"optimizer": {
"enabled": true,
"runs": 200
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": true
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_hubPeripheryFactory","type":"address"},{"internalType":"address","name":"_hubCoreFactory","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":true,"internalType":"uint256","name":"roles","type":"uint256"}],"name":"RolesUpdated","type":"event"},{"inputs":[],"name":"CONFIG_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEPLOYER_ROLE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"shareTokenName","type":"string"},{"internalType":"string","name":"shareTokenSymbol","type":"string"},{"internalType":"address","name":"accountingToken","type":"address"},{"internalType":"address[]","name":"baseTokens","type":"address[]"},{"internalType":"bytes32","name":"salt","type":"bytes32"},{"internalType":"uint16","name":"depositorImplemId","type":"uint16"},{"internalType":"bool","name":"depositorWhitelistStatus","type":"bool"},{"internalType":"uint16","name":"redeemerImplemId","type":"uint16"},{"internalType":"bool","name":"redeemerWhitelistStatus","type":"bool"},{"internalType":"uint256","name":"redeemerFinalizationDelay","type":"uint256"},{"internalType":"uint256","name":"redeemerMinRedeemAmount","type":"uint256"},{"internalType":"uint16","name":"feeManagerImplemId","type":"uint16"},{"components":[{"internalType":"uint256","name":"initialMgmtFeeRatePerSecond","type":"uint256"},{"internalType":"uint256","name":"initialSmFeeRatePerSecond","type":"uint256"},{"internalType":"uint256","name":"initialPerfFeeRate","type":"uint256"},{"internalType":"uint256[]","name":"initialMgmtFeeSplitBps","type":"uint256[]"},{"internalType":"address[]","name":"initialMgmtFeeReceivers","type":"address[]"},{"internalType":"uint256[]","name":"initialPerfFeeSplitBps","type":"uint256[]"},{"internalType":"address[]","name":"initialPerfFeeReceivers","type":"address[]"}],"internalType":"struct IWatermarkFeeManager.WatermarkFeeManagerInitParams","name":"feeManagerInitParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"initialCaliberStaleThreshold","type":"uint256"},{"internalType":"uint256","name":"initialMaxFixedFeeAccrualRate","type":"uint256"},{"internalType":"uint256","name":"initialMaxPerfFeeAccrualRate","type":"uint256"},{"internalType":"uint256","name":"initialFeeMintCooldown","type":"uint256"},{"internalType":"uint256","name":"initialShareLimit","type":"uint256"}],"internalType":"struct IMachineZap.MachineInitParams","name":"machineInitParams","type":"tuple"},{"components":[{"internalType":"uint256","name":"initialPositionStaleThreshold","type":"uint256"},{"internalType":"bytes32","name":"initialAllowedInstrRoot","type":"bytes32"},{"internalType":"uint256","name":"initialTimelockDuration","type":"uint256"},{"internalType":"uint256","name":"initialMaxPositionIncreaseLossBps","type":"uint256"},{"internalType":"uint256","name":"initialMaxPositionDecreaseLossBps","type":"uint256"},{"internalType":"uint256","name":"initialMaxSwapLossBps","type":"uint256"},{"internalType":"uint256","name":"initialCooldownDuration","type":"uint256"}],"internalType":"struct ICaliber.CaliberInitParams","name":"caliberInitParams","type":"tuple"},{"components":[{"internalType":"address","name":"initialMechanic","type":"address"},{"internalType":"address","name":"initialSecurityCouncil","type":"address"},{"internalType":"address","name":"initialRiskManager","type":"address"},{"internalType":"address","name":"initialRiskManagerTimelock","type":"address"},{"internalType":"address","name":"initialAuthority","type":"address"}],"internalType":"struct IMakinaGovernable.MakinaGovernableInitParams","name":"mgInitParams","type":"tuple"}],"name":"createMachine","outputs":[{"internalType":"address","name":"machine","type":"address"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"grantRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAllRoles","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"hasAnyRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubCoreFactory","outputs":[{"internalType":"contract IHubCoreFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"hubPeripheryFactory","outputs":[{"internalType":"contract IHubPeripheryFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"renounceRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"uint256","name":"roles","type":"uint256"}],"name":"revokeRoles","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"rolesOf","outputs":[{"internalType":"uint256","name":"roles","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_hubCoreFactory","type":"address"}],"name":"setHubCoreFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_hubPeripheryFactory","type":"address"}],"name":"setHubPeripheryFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"}]Contract Creation Code
60803460b757601f61105c38819003918201601f19168301916001600160401b0383118484101760bb57808492604094855283398101031260b757604b602060458360cf565b920160cf565b5f80546001600160a01b03199081166001600160a01b03948516178255600180549091169390921692909217905533638b78c6d819819055907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a3604051610f7990816100e38239f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b51906001600160a01b038216820360b75756fe60806040526004361015610011575f80fd5b5f3560e01c80631346d50914610504578063183a4f6e146104ec5780631c10893f1461048c5780631cd64df414610453578063256929621461040a5780632de94807146103d85780634a4ee7b1146103b0578063514e62fc1461037857806354d1f13d14610334578063715018a6146102eb5780638da5cb5b146102bf578063957348b01461027c578063a4d19feb14610261578063aae496fc1461023a578063b683b768146101f8578063e23c47ab146101d0578063ecd00261146101b5578063f04e283e14610168578063f2fde38b1461012b5763fee81cf4146100f5575f80fd5b346101275760203660031901126101275761010e610d4d565b63389a75e1600c525f52602080600c2054604051908152f35b5f80fd5b60203660031901126101275761013f610d4d565b610147610eb2565b8060601b1561015b5761015990610ec1565b005b637448fbae5f526004601cfd5b60203660031901126101275761017c610d4d565b610184610eb2565b63389a75e1600c52805f526020600c2090815442116101a8575f6101599255610ec1565b636f5e88185f526004601cfd5b34610127575f36600319011261012757602060405160028152f35b34610127575f366003190112610127576001546040516001600160a01b039091168152602090f35b3461012757602036600319011261012757610211610d4d565b610219610e97565b5f80546001600160a01b0319166001600160a01b0392909216919091179055005b34610127575f366003190112610127575f546040516001600160a01b039091168152602090f35b34610127575f36600319011261012757602060405160048152f35b3461012757602036600319011261012757610295610d4d565b61029d610e97565b600180546001600160a01b0319166001600160a01b0392909216919091179055005b34610127575f36600319011261012757638b78c6d819546040516001600160a01b039091168152602090f35b5f366003190112610127576102fe610eb2565b5f638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35f638b78c6d81955005b5f3660031901126101275763389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2005b3461012757604036600319011261012757610391610d4d565b638b78c6d8600c525f52602060243581600c2054161515604051908152f35b6040366003190112610127576101596103c7610d4d565b6103cf610eb2565b60243590610efe565b34610127576020366003190112610127576103f1610d4d565b638b78c6d8600c525f52602080600c2054604051908152f35b5f3660031901126101275763389a75e1600c52335f526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a2005b3461012757604036600319011261012757602061046e610d4d565b60243590638b78c6d8600c525f528082600c20541614604051908152f35b6040366003190112610127576104a0610d4d565b6104a8610eb2565b638b78c6d8600c525f526020600c20602435815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3005b60203660031901126101275761015960043533610efe565b34610127576103c03660031901126101275760043567ffffffffffffffff811161012757610536903690600401610d1f565b60243567ffffffffffffffff811161012757610556903690600401610d1f565b90929091906044356001600160a01b03811681036101275767ffffffffffffffff60643511610127573660236064350112156101275767ffffffffffffffff6064356004013511610127573660246064356004013560051b6064350101116101275760a4359461ffff861686036101275760c4359586151587036101275760e43561ffff81168103610127576101043590811515820361012757610164359261ffff841684036101275767ffffffffffffffff61018435116101275760e061018435360360031901126101275760a0366101a31901126101275760e0366102431901126101275760a03661032319011261012757610120604052610324356001600160a01b038116810361012757608052610344356001600160a01b03811681036101275760a052610364356001600160a01b03811681036101275760c052610384356001600160a01b03811681036101275760e0526103a4356001600160a01b0381168103610127576080800152638b78c6d8600c52335f5260026020600c20541615610d04575b6107269960209160018060a01b035f54169060405192151584840152838352610709604084610d63565b5f604051809e81958294634b8c20af60e01b845260048401610da4565b03925af1988915610b9e575f99610cda575b50610794929160209160018060a01b035f5416906040519261012435858501526101443560408501521515606084015260608352610777608084610d63565b5f60405180978195829463e987b82760e01b845260048401610da4565b03925af1908115610b9e576108c4925f92610cb8575b5060209060018060a01b035f54166040519183808401526101843560040135604084015260246101843501356060840152604461018435013560808401526108a78361089961087061084861082061080e6064610184350161018435600401610dda565b60e060a0880152610120870191610e0f565b6108366084610184350161018435600401610dda565b868303603f190160c088015290610e33565b61085e60a4610184350161018435600401610dda565b858303603f190160e087015290610e0f565b61088660c4610184350161018435600401610dda565b848303603f190161010086015290610e33565b03601f198101855284610d63565b5f604051809781958294633361cf7160e01b845260048401610da4565b03925af1918215610b9e575f92610c97575b5060c0805160e0805130938490529290526001546040516001600160a01b039384169b9284169a919093169590610100840167ffffffffffffffff811185821017610c835760209960e0975f97610acc96610ab99460405260018060a01b0316885260018060a01b03168c88015260018060a01b031660408701526101a43560608701526101c43560808701526101e43560a08701526102043560c087015261022435888701526040519b8c9a898c9a9863bc5d11c98c9a1b8a5260018060a01b0381511660048b015260018060a01b038f8201511660248b015260018060a01b0360408201511660448b0152606081015160648b0152608081015160848b015260a081015160a48b015260c081015160c48b0152015160e48901526102443561010489015261026435610124890152610284356101448901526102a4356101648901526102c4356101848901526102e4356101a4890152610304356101c489015260018060a01b03608051166101e489015260018060a01b038d608001511661020489015260018060a01b036040608001511661022489015260018060a01b036060608001511661024489015260018060a01b0360808001511661026489015260018060a01b03166102848801526103006102a4880152610304870191610e77565b848103600319016102c486015291610e77565b6084356102e483015203925af1908115610b9e575f91610c64575b50604051630694823160e31b81526001600160a01b03919091169290602081600481875afa908115610b9e575f91610c35575b506001600160a01b0316925f5b60643560040135811015610ba9576024600582901b6064350101356001600160a01b038116919082900361012757853b1561012757604051916383e280d960e01b835260048301525f82602481838a5af1918215610b9e57600192610b8e575b5001610b27565b5f610b9891610d63565b86610b87565b6040513d5f823e3d90fd5b5082813b156101275760405190630316542360e51b825260048201525f8160248183865af18015610b9e57610c25575b50803b156101275760405191634ccc3df160e01b835260048301525f8260248183855af1918215610b9e57602092610c15575b50604051908152f35b5f610c1f91610d63565b82610c0c565b5f610c2f91610d63565b82610bd9565b610c57915060203d602011610c5d575b610c4f8183610d63565b810190610d85565b84610b1a565b503d610c45565b610c7d915060203d602011610c5d57610c4f8183610d63565b83610ae7565b634e487b7160e01b5f52604160045260245ffd5b610cb191925060203d602011610c5d57610c4f8183610d63565b90886108d6565b6020919250610cd390823d8411610c5d57610c4f8183610d63565b91906107aa565b602091995091610cfa6107949493833d8511610c5d57610c4f8183610d63565b9991509192610738565b638b78c6d8195433146106df575b6382b429005f526004601cfd5b9181601f840112156101275782359167ffffffffffffffff8311610127576020838186019501011161012757565b600435906001600160a01b038216820361012757565b90601f8019910116810190811067ffffffffffffffff821117610c8357604052565b9081602091031261012757516001600160a01b03811681036101275790565b9060609261ffff6020921683526040828401528051918291826040860152018484015e5f828201840152601f01601f1916010190565b9035601e198236030181121561012757016020813591019167ffffffffffffffff8211610127578160051b3603831361012757565b81835290916001600160fb1b0383116101275760209260051b809284830137010190565b916020908281520191905f905b808210610e4d5750505090565b90919283359060018060a01b03821680920361012757602081600193829352019401920190610e40565b908060209392818452848401375f828201840152601f01601f1916010190565b638b78c6d8600c52335f5260046020600c20541615610eb257565b638b78c6d819543303610d1257565b60018060a01b031680638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3638b78c6d81955565b638b78c6d8600c525f526020600c2090815490811618809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a356fea2646970667358221220eba376283f7e0277aa0d90b63d439d3492f6f01f26619c6a07df34c745a149b264736f6c634300081c00330000000000000000000000009b4e525f665709c4ee31da676b83d824d3b34d6c0000000000000000000000004bad075188d11f513497a28aca6f6dcfee293bb5
Deployed Bytecode
0x60806040526004361015610011575f80fd5b5f3560e01c80631346d50914610504578063183a4f6e146104ec5780631c10893f1461048c5780631cd64df414610453578063256929621461040a5780632de94807146103d85780634a4ee7b1146103b0578063514e62fc1461037857806354d1f13d14610334578063715018a6146102eb5780638da5cb5b146102bf578063957348b01461027c578063a4d19feb14610261578063aae496fc1461023a578063b683b768146101f8578063e23c47ab146101d0578063ecd00261146101b5578063f04e283e14610168578063f2fde38b1461012b5763fee81cf4146100f5575f80fd5b346101275760203660031901126101275761010e610d4d565b63389a75e1600c525f52602080600c2054604051908152f35b5f80fd5b60203660031901126101275761013f610d4d565b610147610eb2565b8060601b1561015b5761015990610ec1565b005b637448fbae5f526004601cfd5b60203660031901126101275761017c610d4d565b610184610eb2565b63389a75e1600c52805f526020600c2090815442116101a8575f6101599255610ec1565b636f5e88185f526004601cfd5b34610127575f36600319011261012757602060405160028152f35b34610127575f366003190112610127576001546040516001600160a01b039091168152602090f35b3461012757602036600319011261012757610211610d4d565b610219610e97565b5f80546001600160a01b0319166001600160a01b0392909216919091179055005b34610127575f366003190112610127575f546040516001600160a01b039091168152602090f35b34610127575f36600319011261012757602060405160048152f35b3461012757602036600319011261012757610295610d4d565b61029d610e97565b600180546001600160a01b0319166001600160a01b0392909216919091179055005b34610127575f36600319011261012757638b78c6d819546040516001600160a01b039091168152602090f35b5f366003190112610127576102fe610eb2565b5f638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a35f638b78c6d81955005b5f3660031901126101275763389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2005b3461012757604036600319011261012757610391610d4d565b638b78c6d8600c525f52602060243581600c2054161515604051908152f35b6040366003190112610127576101596103c7610d4d565b6103cf610eb2565b60243590610efe565b34610127576020366003190112610127576103f1610d4d565b638b78c6d8600c525f52602080600c2054604051908152f35b5f3660031901126101275763389a75e1600c52335f526202a30042016020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a2005b3461012757604036600319011261012757602061046e610d4d565b60243590638b78c6d8600c525f528082600c20541614604051908152f35b6040366003190112610127576104a0610d4d565b6104a8610eb2565b638b78c6d8600c525f526020600c20602435815417809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a3005b60203660031901126101275761015960043533610efe565b34610127576103c03660031901126101275760043567ffffffffffffffff811161012757610536903690600401610d1f565b60243567ffffffffffffffff811161012757610556903690600401610d1f565b90929091906044356001600160a01b03811681036101275767ffffffffffffffff60643511610127573660236064350112156101275767ffffffffffffffff6064356004013511610127573660246064356004013560051b6064350101116101275760a4359461ffff861686036101275760c4359586151587036101275760e43561ffff81168103610127576101043590811515820361012757610164359261ffff841684036101275767ffffffffffffffff61018435116101275760e061018435360360031901126101275760a0366101a31901126101275760e0366102431901126101275760a03661032319011261012757610120604052610324356001600160a01b038116810361012757608052610344356001600160a01b03811681036101275760a052610364356001600160a01b03811681036101275760c052610384356001600160a01b03811681036101275760e0526103a4356001600160a01b0381168103610127576080800152638b78c6d8600c52335f5260026020600c20541615610d04575b6107269960209160018060a01b035f54169060405192151584840152838352610709604084610d63565b5f604051809e81958294634b8c20af60e01b845260048401610da4565b03925af1988915610b9e575f99610cda575b50610794929160209160018060a01b035f5416906040519261012435858501526101443560408501521515606084015260608352610777608084610d63565b5f60405180978195829463e987b82760e01b845260048401610da4565b03925af1908115610b9e576108c4925f92610cb8575b5060209060018060a01b035f54166040519183808401526101843560040135604084015260246101843501356060840152604461018435013560808401526108a78361089961087061084861082061080e6064610184350161018435600401610dda565b60e060a0880152610120870191610e0f565b6108366084610184350161018435600401610dda565b868303603f190160c088015290610e33565b61085e60a4610184350161018435600401610dda565b858303603f190160e087015290610e0f565b61088660c4610184350161018435600401610dda565b848303603f190161010086015290610e33565b03601f198101855284610d63565b5f604051809781958294633361cf7160e01b845260048401610da4565b03925af1918215610b9e575f92610c97575b5060c0805160e0805130938490529290526001546040516001600160a01b039384169b9284169a919093169590610100840167ffffffffffffffff811185821017610c835760209960e0975f97610acc96610ab99460405260018060a01b0316885260018060a01b03168c88015260018060a01b031660408701526101a43560608701526101c43560808701526101e43560a08701526102043560c087015261022435888701526040519b8c9a898c9a9863bc5d11c98c9a1b8a5260018060a01b0381511660048b015260018060a01b038f8201511660248b015260018060a01b0360408201511660448b0152606081015160648b0152608081015160848b015260a081015160a48b015260c081015160c48b0152015160e48901526102443561010489015261026435610124890152610284356101448901526102a4356101648901526102c4356101848901526102e4356101a4890152610304356101c489015260018060a01b03608051166101e489015260018060a01b038d608001511661020489015260018060a01b036040608001511661022489015260018060a01b036060608001511661024489015260018060a01b0360808001511661026489015260018060a01b03166102848801526103006102a4880152610304870191610e77565b848103600319016102c486015291610e77565b6084356102e483015203925af1908115610b9e575f91610c64575b50604051630694823160e31b81526001600160a01b03919091169290602081600481875afa908115610b9e575f91610c35575b506001600160a01b0316925f5b60643560040135811015610ba9576024600582901b6064350101356001600160a01b038116919082900361012757853b1561012757604051916383e280d960e01b835260048301525f82602481838a5af1918215610b9e57600192610b8e575b5001610b27565b5f610b9891610d63565b86610b87565b6040513d5f823e3d90fd5b5082813b156101275760405190630316542360e51b825260048201525f8160248183865af18015610b9e57610c25575b50803b156101275760405191634ccc3df160e01b835260048301525f8260248183855af1918215610b9e57602092610c15575b50604051908152f35b5f610c1f91610d63565b82610c0c565b5f610c2f91610d63565b82610bd9565b610c57915060203d602011610c5d575b610c4f8183610d63565b810190610d85565b84610b1a565b503d610c45565b610c7d915060203d602011610c5d57610c4f8183610d63565b83610ae7565b634e487b7160e01b5f52604160045260245ffd5b610cb191925060203d602011610c5d57610c4f8183610d63565b90886108d6565b6020919250610cd390823d8411610c5d57610c4f8183610d63565b91906107aa565b602091995091610cfa6107949493833d8511610c5d57610c4f8183610d63565b9991509192610738565b638b78c6d8195433146106df575b6382b429005f526004601cfd5b9181601f840112156101275782359167ffffffffffffffff8311610127576020838186019501011161012757565b600435906001600160a01b038216820361012757565b90601f8019910116810190811067ffffffffffffffff821117610c8357604052565b9081602091031261012757516001600160a01b03811681036101275790565b9060609261ffff6020921683526040828401528051918291826040860152018484015e5f828201840152601f01601f1916010190565b9035601e198236030181121561012757016020813591019167ffffffffffffffff8211610127578160051b3603831361012757565b81835290916001600160fb1b0383116101275760209260051b809284830137010190565b916020908281520191905f905b808210610e4d5750505090565b90919283359060018060a01b03821680920361012757602081600193829352019401920190610e40565b908060209392818452848401375f828201840152601f01601f1916010190565b638b78c6d8600c52335f5260046020600c20541615610eb257565b638b78c6d819543303610d1257565b60018060a01b031680638b78c6d819547f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a3638b78c6d81955565b638b78c6d8600c525f526020600c2090815490811618809155600c5160601c7f715ad5ce61fc9595c7b415289d59cf203f23a94fa06f04af7e489a0a76e1fe265f80a356fea2646970667358221220eba376283f7e0277aa0d90b63d439d3492f6f01f26619c6a07df34c745a149b264736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009b4e525f665709c4ee31da676b83d824d3b34d6c0000000000000000000000004bad075188d11f513497a28aca6f6dcfee293bb5
-----Decoded View---------------
Arg [0] : _hubPeripheryFactory (address): 0x9b4e525f665709C4Ee31DA676B83D824D3b34D6C
Arg [1] : _hubCoreFactory (address): 0x4bAD075188d11f513497A28AcA6f6DcfEE293BB5
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009b4e525f665709c4ee31da676b83d824d3b34d6c
Arg [1] : 0000000000000000000000004bad075188d11f513497a28aca6f6dcfee293bb5
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.