Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x6118d061 | 24298701 | 67 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
CaliberAccountingCCQ
Compiler Version
v0.8.28+commit.7893614a
Optimization Enabled:
Yes with 150 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 {IWormhole} from "@wormhole/sdk/interfaces/IWormhole.sol";
import {
EthCallQueryResponse,
PerChainQueryResponse,
QueryResponse,
QueryResponseLib
} from "@wormhole/sdk/libraries/QueryResponse.sol";
import {GuardianSignature} from "@wormhole/sdk/libraries/VaaLib.sol";
import {ICaliberMailbox} from "../interfaces/ICaliberMailbox.sol";
import {Errors} from "./Errors.sol";
library CaliberAccountingCCQ {
function decodeAndVerifyQueryResponse(
address wormhole,
bytes calldata response,
GuardianSignature[] calldata signatures
) external view returns (QueryResponse memory ret) {
return QueryResponseLib.decodeAndVerifyQueryResponseCd(
wormhole, response, signatures, IWormhole(wormhole).getCurrentGuardianSetIndex()
);
}
/// @dev Parses the PerChainQueryResponse and retrieves the accounting data for the given caliber mailbox.
/// @param pcr The PerChainQueryResponse containing the query results.
/// @param caliberMailbox The address of the queried caliber mailbox.
/// @return data The accounting data for the given caliber mailbox
/// @return responseTimestamp The timestamp of the response.
function getAccountingData(PerChainQueryResponse memory pcr, address caliberMailbox)
external
pure
returns (ICaliberMailbox.SpokeCaliberAccountingData memory, uint256)
{
EthCallQueryResponse memory eqr = QueryResponseLib.decodeEthCallQueryResponse(pcr);
// Validate that only one result is returned.
if (eqr.results.length != 1) {
revert Errors.UnexpectedResultLength();
}
// Validate addresses and function signatures.
address[] memory validAddresses = new address[](1);
bytes4[] memory validFunctionSignatures = new bytes4[](1);
validAddresses[0] = caliberMailbox;
validFunctionSignatures[0] = ICaliberMailbox.getSpokeCaliberAccountingData.selector;
QueryResponseLib.validateEthCallRecord(eqr.results[0], validAddresses, validFunctionSignatures);
return (
abi.decode(eqr.results[0].result, (ICaliberMailbox.SpokeCaliberAccountingData)),
eqr.blockTime / QueryResponseLib.MICROSECONDS_PER_SECOND
);
}
}// 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 {BytesParsing} from "wormhole-sdk/libraries/BytesParsing.sol";
import {CoreBridgeLib} from "wormhole-sdk/libraries/CoreBridge.sol";
import {GuardianSignature} from "wormhole-sdk/libraries/VaaLib.sol";
import {eagerAnd, eagerOr, keccak256Cd} from "wormhole-sdk/Utils.sol";
library QueryType {
error UnsupportedQueryType(uint8 received);
//Solidity enums don't permit custom values (i.e. can't start from 1)
//Also invalid enum conversions result in panics and manual range checking requires assembly
// to avoid superfluous double checking.
//So we're sticking with uint8 constants instead.
uint8 internal constant ETH_CALL = 1;
uint8 internal constant ETH_CALL_BY_TIMESTAMP = 2;
uint8 internal constant ETH_CALL_WITH_FINALITY = 3;
uint8 internal constant SOLANA_ACCOUNT = 4;
uint8 internal constant SOLANA_PDA = 5;
//emulate type(enum).min/max for external consumers (mainly tests)
function min() internal pure returns (uint8) { return ETH_CALL; }
function max() internal pure returns (uint8) { return SOLANA_PDA; }
function checkValid(uint8 queryType) internal pure {
//slightly more gas efficient than calling `isValid`
if (eagerOr(queryType == 0, queryType > SOLANA_PDA))
revert UnsupportedQueryType(queryType);
}
function isValid(uint8 queryType) internal pure returns (bool) {
//see docs/Optimization.md why `< CONST + 1` rather than `<= CONST`
//see docs/Optimization.md for rationale behind `eagerAnd`
return eagerAnd(queryType > 0, queryType < SOLANA_PDA + 1);
}
}
struct QueryResponse {
uint8 version;
uint16 senderChainId;
uint32 nonce;
bytes requestId; // 65 byte sig for off-chain, 32 byte vaaHash for on-chain
PerChainQueryResponse[] responses;
}
struct PerChainQueryResponse {
uint16 chainId;
uint8 queryType;
bytes request;
bytes response;
}
struct EthCallQueryResponse {
bytes requestBlockId;
uint64 blockNum;
uint64 blockTime;
bytes32 blockHash;
EthCallRecord[] results;
}
struct EthCallByTimestampQueryResponse {
bytes requestTargetBlockIdHint;
bytes requestFollowingBlockIdHint;
uint64 requestTargetTimestamp;
uint64 targetBlockNum;
uint64 targetBlockTime;
uint64 followingBlockNum;
bytes32 targetBlockHash;
bytes32 followingBlockHash;
uint64 followingBlockTime;
EthCallRecord[] results;
}
struct EthCallWithFinalityQueryResponse {
bytes requestBlockId;
bytes requestFinality;
uint64 blockNum;
uint64 blockTime;
bytes32 blockHash;
EthCallRecord[] results;
}
struct EthCallRecord {
address contractAddress;
bytes callData;
bytes result;
}
struct SolanaAccountQueryResponse {
bytes requestCommitment;
uint64 requestMinContextSlot;
uint64 requestDataSliceOffset;
uint64 requestDataSliceLength;
uint64 slotNumber;
uint64 blockTime;
bytes32 blockHash;
SolanaAccountResult[] results;
}
struct SolanaAccountResult {
bytes32 account;
uint64 lamports;
uint64 rentEpoch;
bool executable;
bytes32 owner;
bytes data;
}
struct SolanaPdaQueryResponse {
bytes requestCommitment;
uint64 requestMinContextSlot;
uint64 requestDataSliceOffset;
uint64 requestDataSliceLength;
uint64 slotNumber;
uint64 blockTime;
bytes32 blockHash;
SolanaPdaResult[] results;
}
struct SolanaPdaResult {
bytes32 programId;
bytes[] seeds;
bytes32 account;
uint64 lamports;
uint64 rentEpoch;
bool executable;
bytes32 owner;
bytes data;
uint8 bump;
}
//QueryResponse is a library that implements the decoding and verification of
// Cross Chain Query (CCQ) responses.
//
//For a detailed discussion of these query responses, please see the white paper:
// https://github.com/wormhole-foundation/wormhole/blob/main/whitepapers/0013_ccq.md
//
//We only implement Cd and Mem decoding variants for the QueryResponse struct itself because all
// further decoding will have to operate on the memory bytes anyway since there's no way in plain
// Solidity to have structs with mixed data location, i.e. a struct in memory that references bytes
// in calldata.
// This will at least help cut down the gas cost of decoding/slicing the outer most layer.
library QueryResponseLib {
using BytesParsing for bytes;
error WrongQueryType(uint8 received, uint8 expected);
error InvalidResponseVersion();
error VersionMismatch();
error ZeroQueries();
error NumberOfResponsesMismatch();
error ChainIdMismatch();
error RequestTypeMismatch();
error UnexpectedNumberOfResults();
error InvalidPayloadLength(uint256 received, uint256 expected);
error InvalidContractAddress();
error InvalidFunctionSignature();
error InvalidChainId();
error StaleBlockNum();
error StaleBlockTime();
error VerificationFailed();
bytes internal constant RESPONSE_PREFIX = bytes("query_response_0000000000000000000|");
uint8 internal constant VERSION = 1;
uint64 internal constant MICROSECONDS_PER_SECOND = 1_000_000;
function calcPrefixedResponseHashCd(bytes calldata response) internal pure returns (bytes32) {
return calcPrefixedResponseHash(keccak256Cd(response));
}
function calcPrefixedResponseHashMem(bytes memory response) internal pure returns (bytes32) {
return calcPrefixedResponseHash(keccak256(response));
}
function calcPrefixedResponseHash(bytes32 responseHash) internal pure returns (bytes32) {
return keccak256(abi.encodePacked(RESPONSE_PREFIX, responseHash));
}
// -------- decodeAndVerifyQueryResponse --------
// ---- guardian set index variants
// will look up the guardian set internally and also try to verify against the latest
// guardian set, if the specified guardian set is expired.
function decodeAndVerifyQueryResponseCd(
address wormhole,
bytes calldata response,
GuardianSignature[] calldata guardianSignatures,
uint32 guardianSetIndex
) internal view returns (QueryResponse memory ret) {
verifyQueryResponseCd(wormhole, response, guardianSignatures, guardianSetIndex);
return decodeQueryResponseCd(response);
}
function decodeAndVerifyQueryResponseMem(
address wormhole,
bytes memory response,
GuardianSignature[] memory guardianSignatures,
uint32 guardianSetIndex
) internal view returns (QueryResponse memory ret) {
verifyQueryResponseMem(wormhole, response, guardianSignatures, guardianSetIndex);
return decodeQueryResponseMem(response);
}
function verifyQueryResponseCd(
address wormhole,
bytes calldata response,
GuardianSignature[] calldata guardianSignatures,
uint32 guardianSetIndex
) internal view {
if (!CoreBridgeLib.isVerifiedByQuorumCd(
wormhole,
calcPrefixedResponseHashCd(response),
guardianSignatures,
guardianSetIndex
))
revert VerificationFailed();
}
function verifyQueryResponseMem(
address wormhole,
bytes memory response,
GuardianSignature[] memory guardianSignatures,
uint32 guardianSetIndex
) internal view {
if (!CoreBridgeLib.isVerifiedByQuorumMem(
wormhole,
calcPrefixedResponseHashMem(response),
guardianSignatures,
guardianSetIndex
))
revert VerificationFailed();
}
// ---- guardian address variants
// will only try to verify against the specified guardian addresses only
function decodeAndVerifyQueryResponseCd(
bytes calldata response,
GuardianSignature[] calldata guardianSignatures,
address[] memory guardians
) internal pure returns (QueryResponse memory ret) {
verifyQueryResponseCd(response, guardianSignatures, guardians);
return decodeQueryResponseCd(response);
}
function decodeAndVerifyQueryResponseMem(
bytes memory response,
GuardianSignature[] memory guardianSignatures,
address[] memory guardians
) internal pure returns (QueryResponse memory ret) {
verifyQueryResponseMem(response, guardianSignatures, guardians);
return decodeQueryResponseMem(response);
}
function verifyQueryResponseCd(
bytes calldata response,
GuardianSignature[] calldata guardianSignatures,
address[] memory guardians
) internal pure {
if (!CoreBridgeLib.isVerifiedByQuorumCd(
calcPrefixedResponseHashCd(response),
guardianSignatures,
guardians
))
revert VerificationFailed();
}
function verifyQueryResponseMem(
bytes memory response,
GuardianSignature[] memory guardianSignatures,
address[] memory guardians
) internal pure {
if (!CoreBridgeLib.isVerifiedByQuorumMem(
calcPrefixedResponseHashMem(response),
guardianSignatures,
guardians
))
revert VerificationFailed();
}
// -------- decode functions --------
function decodeQueryResponseCd(
bytes calldata response
) internal pure returns (QueryResponse memory ret) { unchecked {
uint offset;
(ret.version, offset) = response.asUint8CdUnchecked(offset);
if (ret.version != VERSION)
revert InvalidResponseVersion();
(ret.senderChainId, offset) = response.asUint16CdUnchecked(offset);
//for off-chain requests (chainID zero), the requestId is the 65 byte signature
//for on-chain requests, it is the 32 byte VAA hash
(ret.requestId, offset) = response.sliceCdUnchecked(offset, ret.senderChainId == 0 ? 65 : 32);
uint32 queryReqLen;
(queryReqLen, offset) = response.asUint32CdUnchecked(offset);
uint reqOff = offset;
{
uint8 version;
(version, reqOff) = response.asUint8CdUnchecked(reqOff);
if (version != ret.version)
revert VersionMismatch();
}
(ret.nonce, reqOff) = response.asUint32CdUnchecked(reqOff);
uint8 numPerChainQueries;
(numPerChainQueries, reqOff) = response.asUint8CdUnchecked(reqOff);
//a valid query request must have at least one per-chain-query
if (numPerChainQueries == 0)
revert ZeroQueries();
//The response starts after the request.
uint respOff = offset + queryReqLen;
uint startOfResponse = respOff;
uint8 respNumPerChainQueries;
(respNumPerChainQueries, respOff) = response.asUint8CdUnchecked(respOff);
if (respNumPerChainQueries != numPerChainQueries)
revert NumberOfResponsesMismatch();
ret.responses = new PerChainQueryResponse[](numPerChainQueries);
//walk through the requests and responses in lock step.
for (uint i; i < numPerChainQueries; ++i) {
(ret.responses[i].chainId, reqOff) = response.asUint16CdUnchecked(reqOff);
uint16 respChainId;
(respChainId, respOff) = response.asUint16CdUnchecked(respOff);
if (respChainId != ret.responses[i].chainId)
revert ChainIdMismatch();
(ret.responses[i].queryType, reqOff) = response.asUint8CdUnchecked(reqOff);
QueryType.checkValid(ret.responses[i].queryType);
uint8 respQueryType;
(respQueryType, respOff) = response.asUint8CdUnchecked(respOff);
if (respQueryType != ret.responses[i].queryType)
revert RequestTypeMismatch();
(ret.responses[i].request, reqOff) = response.sliceUint32PrefixedCdUnchecked(reqOff);
(ret.responses[i].response, respOff) = response.sliceUint32PrefixedCdUnchecked(respOff);
}
//end of request body should align with start of response body
if (startOfResponse != reqOff)
revert InvalidPayloadLength(startOfResponse, reqOff);
_checkLength(response.length, respOff);
return ret;
}}
function decodeQueryResponseMem(
bytes memory response
) internal pure returns (QueryResponse memory ret) { unchecked {
uint offset;
(ret.version, offset) = response.asUint8MemUnchecked(offset);
if (ret.version != VERSION)
revert InvalidResponseVersion();
(ret.senderChainId, offset) = response.asUint16MemUnchecked(offset);
//for off-chain requests (chainID zero), the requestId is the 65 byte signature
//for on-chain requests, it is the 32 byte VAA hash
(ret.requestId, offset) = response.sliceMemUnchecked(offset, ret.senderChainId == 0 ? 65 : 32);
uint32 queryReqLen;
(queryReqLen, offset) = response.asUint32MemUnchecked(offset);
uint reqOff = offset;
{
uint8 version;
(version, reqOff) = response.asUint8MemUnchecked(reqOff);
if (version != ret.version)
revert VersionMismatch();
}
(ret.nonce, reqOff) = response.asUint32MemUnchecked(reqOff);
uint8 numPerChainQueries;
(numPerChainQueries, reqOff) = response.asUint8MemUnchecked(reqOff);
//a valid query request must have at least one per-chain-query
if (numPerChainQueries == 0)
revert ZeroQueries();
//The response starts after the request.
uint respOff = offset + queryReqLen;
uint startOfResponse = respOff;
uint8 respNumPerChainQueries;
(respNumPerChainQueries, respOff) = response.asUint8MemUnchecked(respOff);
if (respNumPerChainQueries != numPerChainQueries)
revert NumberOfResponsesMismatch();
ret.responses = new PerChainQueryResponse[](numPerChainQueries);
//walk through the requests and responses in lock step.
for (uint i; i < numPerChainQueries; ++i) {
(ret.responses[i].chainId, reqOff) = response.asUint16MemUnchecked(reqOff);
uint16 respChainId;
(respChainId, respOff) = response.asUint16MemUnchecked(respOff);
if (respChainId != ret.responses[i].chainId)
revert ChainIdMismatch();
(ret.responses[i].queryType, reqOff) = response.asUint8MemUnchecked(reqOff);
QueryType.checkValid(ret.responses[i].queryType);
uint8 respQueryType;
(respQueryType, respOff) = response.asUint8MemUnchecked(respOff);
if (respQueryType != ret.responses[i].queryType)
revert RequestTypeMismatch();
(ret.responses[i].request, reqOff) = response.sliceUint32PrefixedMemUnchecked(reqOff);
(ret.responses[i].response, respOff) = response.sliceUint32PrefixedMemUnchecked(respOff);
}
//end of request body should align with start of response body
if (startOfResponse != reqOff)
revert InvalidPayloadLength(startOfResponse, reqOff);
_checkLength(response.length, respOff);
return ret;
}}
function decodeEthCallQueryResponse(
PerChainQueryResponse memory pcr
) internal pure returns (EthCallQueryResponse memory ret) { unchecked {
if (pcr.queryType != QueryType.ETH_CALL)
revert WrongQueryType(pcr.queryType, QueryType.ETH_CALL);
uint reqOff;
uint respOff;
uint8 numBatchCallData;
(ret.requestBlockId, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(numBatchCallData, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
uint8 respNumResults;
(ret.blockNum, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.blockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.blockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);
if (respNumResults != numBatchCallData)
revert UnexpectedNumberOfResults();
ret.results = new EthCallRecord[](numBatchCallData);
//walk through the call inputs and outputs in lock step.
for (uint i; i < numBatchCallData; ++i) {
EthCallRecord memory ecr = ret.results[i];
(ecr.contractAddress, reqOff) = pcr.request.asAddressMemUnchecked(reqOff);
(ecr.callData, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ecr.result, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
}
_checkLength(pcr.request.length, reqOff);
_checkLength(pcr.response.length, respOff);
return ret;
}}
function decodeEthCallByTimestampQueryResponse(
PerChainQueryResponse memory pcr
) internal pure returns (EthCallByTimestampQueryResponse memory ret) { unchecked {
if (pcr.queryType != QueryType.ETH_CALL_BY_TIMESTAMP)
revert WrongQueryType(pcr.queryType, QueryType.ETH_CALL_BY_TIMESTAMP);
uint reqOff;
uint respOff;
uint8 numBatchCallData;
(ret.requestTargetTimestamp, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
(ret.requestTargetBlockIdHint, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ret.requestFollowingBlockIdHint, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(numBatchCallData, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
uint8 respNumResults;
(ret.targetBlockNum, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.targetBlockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.targetBlockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.followingBlockNum, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.followingBlockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.followingBlockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);
if (respNumResults != numBatchCallData)
revert UnexpectedNumberOfResults();
ret.results = new EthCallRecord[](numBatchCallData);
//walk through the call inputs and outputs in lock step.
for (uint i; i < numBatchCallData; ++i) {
EthCallRecord memory ecr = ret.results[i];
(ecr.contractAddress, reqOff) = pcr.request.asAddressMemUnchecked(reqOff);
(ecr.callData, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ecr.result, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
}
_checkLength(pcr.request.length, reqOff);
_checkLength(pcr.response.length, respOff);
}}
function decodeEthCallWithFinalityQueryResponse(
PerChainQueryResponse memory pcr
) internal pure returns (EthCallWithFinalityQueryResponse memory ret) { unchecked {
if (pcr.queryType != QueryType.ETH_CALL_WITH_FINALITY)
revert WrongQueryType(pcr.queryType, QueryType.ETH_CALL_WITH_FINALITY);
uint reqOff;
uint respOff;
uint8 numBatchCallData;
(ret.requestBlockId, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ret.requestFinality, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(numBatchCallData, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
uint8 respNumResults;
(ret.blockNum, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.blockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.blockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);
if (respNumResults != numBatchCallData)
revert UnexpectedNumberOfResults();
ret.results = new EthCallRecord[](numBatchCallData);
//walk through the call inputs and outputs in lock step.
for (uint i; i < numBatchCallData; ++i) {
EthCallRecord memory ecr = ret.results[i];
(ecr.contractAddress, reqOff) = pcr.request.asAddressMemUnchecked(reqOff);
(ecr.callData, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ecr.result, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
}
_checkLength(pcr.request.length, reqOff);
_checkLength(pcr.response.length, respOff);
}}
function decodeSolanaAccountQueryResponse(
PerChainQueryResponse memory pcr
) internal pure returns (SolanaAccountQueryResponse memory ret) { unchecked {
if (pcr.queryType != QueryType.SOLANA_ACCOUNT)
revert WrongQueryType(pcr.queryType, QueryType.SOLANA_ACCOUNT);
uint reqOff;
uint respOff;
uint8 numAccounts;
(ret.requestCommitment, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ret.requestMinContextSlot, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
(ret.requestDataSliceOffset, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
(ret.requestDataSliceLength, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
(numAccounts, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
uint8 respNumResults;
(ret.slotNumber, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.blockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.blockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);
if (respNumResults != numAccounts)
revert UnexpectedNumberOfResults();
ret.results = new SolanaAccountResult[](numAccounts);
//walk through the call inputs and outputs in lock step.
for (uint i; i < numAccounts; ++i) {
(ret.results[i].account, reqOff) = pcr.request.asBytes32MemUnchecked(reqOff);
(ret.results[i].lamports, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.results[i].rentEpoch, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.results[i].executable, respOff) = pcr.response.asBoolMemUnchecked(respOff);
(ret.results[i].owner, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.results[i].data, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
}
_checkLength(pcr.request.length, reqOff);
_checkLength(pcr.response.length, respOff);
}}
function decodeSolanaPdaQueryResponse(
PerChainQueryResponse memory pcr
) internal pure returns (SolanaPdaQueryResponse memory ret) { unchecked {
if (pcr.queryType != QueryType.SOLANA_PDA)
revert WrongQueryType(pcr.queryType, QueryType.SOLANA_PDA);
uint reqOff;
uint respOff;
(ret.requestCommitment, reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ret.requestMinContextSlot, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
(ret.requestDataSliceOffset, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
(ret.requestDataSliceLength, reqOff) = pcr.request.asUint64MemUnchecked(reqOff);
uint8 numPdas;
(numPdas, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
(ret.slotNumber, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.blockTime, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.blockHash, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
uint8 respNumResults;
(respNumResults, respOff) = pcr.response.asUint8MemUnchecked(respOff);
if (respNumResults != numPdas)
revert UnexpectedNumberOfResults();
ret.results = new SolanaPdaResult[](numPdas);
//walk through the call inputs and outputs in lock step.
for (uint i; i < numPdas; ++i) {
(ret.results[i].programId, reqOff) = pcr.request.asBytes32MemUnchecked(reqOff);
uint8 reqNumSeeds;
(reqNumSeeds, reqOff) = pcr.request.asUint8MemUnchecked(reqOff);
ret.results[i].seeds = new bytes[](reqNumSeeds);
for (uint s; s < reqNumSeeds; ++s)
(ret.results[i].seeds[s], reqOff) = pcr.request.sliceUint32PrefixedMemUnchecked(reqOff);
(ret.results[i].account, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.results[i].bump, respOff) = pcr.response.asUint8MemUnchecked(respOff);
(ret.results[i].lamports, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.results[i].rentEpoch, respOff) = pcr.response.asUint64MemUnchecked(respOff);
(ret.results[i].executable, respOff) = pcr.response.asBoolMemUnchecked(respOff);
(ret.results[i].owner, respOff) = pcr.response.asBytes32MemUnchecked(respOff);
(ret.results[i].data, respOff) = pcr.response.sliceUint32PrefixedMemUnchecked(respOff);
}
_checkLength(pcr.request.length, reqOff);
_checkLength(pcr.response.length, respOff);
}}
function validateBlockTime(
uint64 blockTimeInMicroSeconds,
uint256 minBlockTimeInSeconds
) internal pure {
uint256 blockTimeInSeconds = blockTimeInMicroSeconds / MICROSECONDS_PER_SECOND; // Rounds down
if (blockTimeInSeconds < minBlockTimeInSeconds)
revert StaleBlockTime();
}
function validateBlockNum(uint64 blockNum, uint256 minBlockNum) internal pure {
if (blockNum < minBlockNum)
revert StaleBlockNum();
}
function validateChainId(
uint16 chainId,
uint16[] memory validChainIds
) internal pure { unchecked {
uint len = validChainIds.length;
for (uint i; i < len; ++i)
if (chainId == validChainIds[i])
return;
revert InvalidChainId();
}}
function validateEthCallRecord(
EthCallRecord[] memory ecrs,
address[] memory validContractAddresses,
bytes4[] memory validFunctionSignatures
) internal pure { unchecked {
uint len = ecrs.length;
for (uint i; i < len; ++i)
validateEthCallRecord(ecrs[i], validContractAddresses, validFunctionSignatures);
}}
//validates that EthCallRecord a valid function signature and contract address
//An empty array means we accept all addresses/function signatures
// Example 1: To accept signatures 0xaaaaaaaa and 0xbbbbbbbb from `address(abcd)`
// you'd pass in [0xaaaaaaaa, 0xbbbbbbbb], [address(abcd)]
// Example 2: To accept any function signatures from `address(abcd)` or `address(efab)`
// you'd pass in [], [address(abcd), address(efab)]
// Example 3: To accept function signature 0xaaaaaaaa from any address
// you'd pass in [0xaaaaaaaa], []
//
// WARNING Example 4: If you want to accept signature 0xaaaaaaaa from `address(abcd)`
// and signature 0xbbbbbbbb from `address(efab)` the following input would be incorrect:
// [0xaaaaaaaa, 0xbbbbbbbb], [address(abcd), address(efab)]
// This would accept both 0xaaaaaaaa and 0xbbbbbbbb from `address(abcd)` AND `address(efab)`.
// Instead you should make 2 calls to this method using the pattern in Example 1.
// [0xaaaaaaaa], [address(abcd)] OR [0xbbbbbbbb], [address(efab)]
function validateEthCallRecord(
EthCallRecord memory ecd,
address[] memory validContractAddresses, //empty array means accept all
bytes4[] memory validFunctionSignatures //empty array means accept all
) internal pure {
if (validContractAddresses.length > 0)
_validateContractAddress(ecd.contractAddress, validContractAddresses);
if (validFunctionSignatures.length > 0) {
if (ecd.callData.length < 4)
revert InvalidFunctionSignature();
(bytes4 funcSig, ) = ecd.callData.asBytes4MemUnchecked(0);
_validateFunctionSignature(funcSig, validFunctionSignatures);
}
}
function _validateContractAddress(
address contractAddress,
address[] memory validContractAddresses
) private pure { unchecked {
uint len = validContractAddresses.length;
for (uint i; i < len; ++i)
if (contractAddress == validContractAddresses[i])
return;
revert InvalidContractAddress();
}}
function _validateFunctionSignature(
bytes4 functionSignature,
bytes4[] memory validFunctionSignatures
) private pure { unchecked {
uint len = validFunctionSignatures.length;
for (uint i; i < len; ++i)
if (functionSignature == validFunctionSignatures[i])
return;
revert InvalidFunctionSignature();
}}
//we use this over BytesParsing.checkLength to return our custom errors in all error cases
function _checkLength(uint256 length, uint256 expected) private pure {
if (length != expected)
revert InvalidPayloadLength(length, expected);
}
}// 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 {IMachineEndpoint} from "./IMachineEndpoint.sol";
import {IMakinaGovernable} from "./IMakinaGovernable.sol";
interface ICaliberMailbox is IMachineEndpoint {
event CaliberSet(address indexed caliber);
event CooldownDurationChanged(uint256 oldDuration, uint256 newDuration);
event HubBridgeAdapterSet(uint256 indexed bridgeId, address indexed adapter);
/// @notice Accounting data of the caliber.
/// @param netAum The net AUM expresses in caliber's accounting token.
/// @param positions The list of positions of the caliber, each encoded as abi.encode(positionId, value, isDebt).
/// @param baseTokens The list of base tokens of the caliber, each encoded as abi.encode(token, value).
/// @param bridgesIn The list of incoming bridge amounts, each encoded as abi.encode(token, amount).
/// @param bridgesOut The list of outgoing bridge amounts, each encoded as abi.encode(token, amount).
struct SpokeCaliberAccountingData {
uint256 netAum;
bytes[] positions;
bytes[] baseTokens;
bytes[] bridgesIn;
bytes[] bridgesOut;
}
/// @notice Initializer of the contract.
/// @param mgParams The makina governable initialization parameters.
/// @param initialCooldownDuration The duration of the cooldown period for outgoing bridge transfers.
/// @param hubMachine The foreign address of the hub machine.
function initialize(
IMakinaGovernable.MakinaGovernableInitParams calldata mgParams,
uint256 initialCooldownDuration,
address hubMachine
) external;
/// @notice Address of the associated caliber.
function caliber() external view returns (address);
/// @notice Duration of the cooldown period for outgoing bridge transfers.
function cooldownDuration() external view returns (uint256);
/// @notice Returns the foreign address of the Hub bridge adapter for a given bridge ID.
/// @param bridgeId The ID of the bridge.
function getHubBridgeAdapter(uint16 bridgeId) external view returns (address);
/// @notice Chain ID of the hub.
function hubChainId() external view returns (uint256);
/// @notice Returns the accounting data of the associated caliber.
/// @return data The accounting data.
function getSpokeCaliberAccountingData() external view returns (SpokeCaliberAccountingData memory);
/// @notice Sets the associated caliber address.
/// @param caliber The address of the associated caliber.
function setCaliber(address caliber) external;
/// @notice Sets the duration of the cooldown period for outgoing bridge transfers.
/// @param newCooldownDuration The new duration in seconds.
function setCooldownDuration(uint256 newCooldownDuration) external;
/// @notice Registers a hub bridge adapter.
/// @param bridgeId The ID of the bridge.
/// @param adapter The foreign address of the bridge adapter.
function setHubBridgeAdapter(uint16 bridgeId, address adapter) external;
}// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.28;
library Errors {
error AccountingToken();
error ActiveUpdatePending();
error AlreadyAccountingAgent();
error AlreadyBaseToken();
error AlreadyPositionToken();
error AlreadyRootGuardian();
error AmountOutTooLow();
error BridgeAdapterAlreadyExists();
error BridgeAdapterDoesNotExist();
error BridgeConfigNotSet();
error BridgeStateMismatch();
error CaliberAccountingStale(uint256 caliberChainId);
error CaliberAlreadySet();
error Create3ContractDeploymentFailed();
error DirectManageFlashLoanCall();
error EvmChainIdNotRegistered(uint256 chainId);
error ExceededMaxDeposit();
error ExceededMaxFee(uint256 fee, uint256 max);
error ExceededMaxMint(uint256 shares, uint256 max);
error ExceededMaxWithdraw(uint256 assets, uint256 max);
error ForeignTokenNotRegistered(address token, uint256 foreignEvmChainId);
error HubBridgeAdapterAlreadySet();
error HubBridgeAdapterNotSet();
error GroupIdNotProvided();
error InstructionsMismatch();
error InsufficientBalance();
error InvalidAccounting();
error InvalidAffectedToken();
error InvalidBridgeTransferRoute();
error InvalidChainId();
error InvalidDebtFlag();
error InvalidDecimals();
error InvalidFeedRoute();
error InvalidInputAmount();
error InvalidInputToken();
error InvalidInstructionProof();
error InvalidInstructionType();
error InvalidLzSentAmount();
error InvalidOft();
error InvalidOutputToken();
error InvalidPositionChangeDirection();
error InvalidRecipientChainId();
error InvalidTransferStatus();
error LocalTokenNotRegistered(address token, uint256 foreignEvmChainId);
error LzChainIdNotRegistered(uint32 chainId);
error LzForeignTokenNotRegistered(address token, uint256 foreignEvmChainId);
error OftNotRegistered(address token);
error ManageFlashLoanReentrantCall();
error MaxAuthorizedPriceChangeExceeded();
error MaxValueLossExceeded();
error MessageAlreadyAuthorized();
error Migrated();
error MinOutputAmountExceedsInputAmount();
error MismatchedLength();
error MismatchedLengths();
error MissingInstructionForGroup(uint256 groupId);
error NegativeTokenPrice(address priceFeed);
error NoPendingUpdate();
error NonZeroBalance();
error NotAccountingAgent();
error NotBaseToken();
error NotCaliber();
error NotCaliberMailbox();
error NotController();
error NotFactory();
error NotFlashLoanModule();
error NotMachine();
error NotMachineEndpoint();
error NotMigrated();
error NotPendingMachine();
error NotPreDepositVault();
error NotRootGuardian();
error OngoingCooldown();
error OutTransferDisabled();
error PendingBridgeTransfer();
error PositionAccountingStale(uint256 posId);
error PositionDoesNotExist();
error PositionIsGrouped();
error PositionToken();
error PositionTokenIsBaseToken();
error PriceFeedRouteNotRegistered(address token);
error PriceFeedStale(address priceFeed, uint256 updatedAt);
error ProtectedAccountingAgent();
error ProtectedRootGuardian();
error Create3ProxyDeploymentFailed();
error RecoveryMode();
error SameRoot();
error SlippageProtection();
error SpokeBridgeAdapterAlreadySet();
error SpokeBridgeAdapterNotSet();
error SpokeCaliberAlreadySet();
error StaleData();
error SwapFailed();
error SwapperTargetsNotSet();
error TargetAlreadyExists();
error UnauthorizedCaller();
error UnauthorizedSource();
error UnexpectedMessage();
error UnexpectedResultLength();
error InvalidBridgeId();
error WhChainIdNotRegistered(uint16 chainId);
error ZeroBridgeAdapterAddress();
error ZeroChainId();
error ZeroGroupId();
error ZeroOftAddress();
error ZeroPositionId();
error ZeroSalt();
error ZeroTokenAddress();
}// 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.14;
import {IWormhole} from "wormhole-sdk/interfaces/IWormhole.sol";
import {WORD_SIZE} from "wormhole-sdk/constants/Common.sol";
import {BytesParsing} from "wormhole-sdk/libraries/BytesParsing.sol";
import {UncheckedIndexing} from "wormhole-sdk/libraries/UncheckedIndexing.sol";
import {GuardianSignature, VaaBody, VaaLib} from "wormhole-sdk/libraries/VaaLib.sol";
import {eagerAnd, eagerOr} from "wormhole-sdk/Utils.sol";
// ╭────────────────────────────────────────────────────────────────────────────────────────╮
// │ Library for "client-side" parsing and verification of VAAs / Guardian signed messages. │
// ╰────────────────────────────────────────────────────────────────────────────────────────╯
//
// Offers significant gas savings over calling the CoreBridge due to:
// * its much more efficient implementation
// * by avoiding external call encoding and decoding overheads
// Comes at the expense of larger contract bytecode.
//
// When verifying a single VAA, decodeAndVerifyVaaCd is maximally gas efficient.
// However, when verifying multiple VAAs/signed messages, the most gas efficient choice is to do
// some manual parsing (e.g. by directly using VaaLib) and to explicitly fetch the guardian set
// (which is very likely to be the same for all messages) via `getGuardiansOrEmpty` or
// `getGuardiansOrLatest` and reuse it, rather than to look it up again and again, as a call
// to decodeAndVerifyVaaCd would do.
//
// Function Overview:
// * decodeAndVerifyVaa: Cd and Mem variants for verifying a VAA and decoding/returning its body
// * isVerifiedByQuorum: 2x2=4 variants for verifying a hash (directly passed to ecrecover):
// * Cd <> Mem
// * guardianSetIndex:
// - fetches the guardian set from the CoreBridge with a fallback to the latest guardian set
// if the specified one is expired as an ad-hoc repair attempt
// * guardianAddresses:
// - only tries to verify against the provided guardian addresses, no fallback
// * readUnchecked: Cd and Mem variants for unchecked index access into a GuardianSignature array
// * minSigsForQuorum
library CoreBridgeLib {
using UncheckedIndexing for address[];
using BytesParsing for bytes;
using VaaLib for bytes;
//avoid solc error:
//Only direct number constants and references to such constants are supported by inline assembly.
uint internal constant GUARDIAN_SIGNATURE_STRUCT_SIZE = 128; //4 * WORD_SIZE;
error VerificationFailed();
function minSigsForQuorum(uint numGuardians) internal pure returns (uint) { unchecked {
return numGuardians * 2 / 3 + 1;
}}
//skip out-of-bounds checks by using assembly
function readUncheckedCd(
GuardianSignature[] calldata arr,
uint i
) internal pure returns (GuardianSignature calldata ret) {
assembly ("memory-safe") {
ret := add(arr.offset, mul(i, GUARDIAN_SIGNATURE_STRUCT_SIZE))
}
}
function readUncheckedMem(
GuardianSignature[] memory arr,
uint i
) internal pure returns (GuardianSignature memory ret) {
assembly ("memory-safe") {
ret := mload(add(add(arr, WORD_SIZE), mul(i, WORD_SIZE)))
}
}
//this function is the most efficient choice when verifying multiple messages because it allows
// library users to reuse the same guardian set for multiple messages (thus avoiding redundant
// external calls and the associated allocations and checks)
function isVerifiedByQuorumCd(
bytes32 hash,
GuardianSignature[] calldata guardianSignatures,
address[] memory guardians
) internal pure returns (bool) { unchecked {
uint guardianCount = guardians.length;
uint signatureCount = guardianSignatures.length; //optimization puts var on stack
if (signatureCount < minSigsForQuorum(guardianCount))
return false;
bool isFirstSignature = true; //optimization instead of always checking i == 0
uint prevGuardianIndex;
for (uint i = 0; i < signatureCount; ++i) {
GuardianSignature memory sig = readUncheckedCd(guardianSignatures, i);
uint guardianIndex = sig.guardianIndex;
if (_failsVerification(
hash,
guardianIndex,
sig.r, sig.s, sig.v,
guardians,
guardianCount,
prevGuardianIndex,
isFirstSignature
))
return false;
prevGuardianIndex = guardianIndex;
isFirstSignature = false;
}
return true;
}}
function isVerifiedByQuorumMem(
bytes32 hash,
GuardianSignature[] memory guardianSignatures,
address[] memory guardians
) internal pure returns (bool) { unchecked {
uint guardianCount = guardians.length;
uint signatureCount = guardianSignatures.length; //optimization puts var on stack
if (signatureCount < minSigsForQuorum(guardianCount))
return false;
bool isFirstSignature = true; //optimization instead of always checking i == 0
uint prevGuardianIndex;
for (uint i = 0; i < signatureCount; ++i) {
GuardianSignature memory sig = readUncheckedMem(guardianSignatures, i);
uint guardianIndex = sig.guardianIndex;
if (_failsVerification(
hash,
guardianIndex,
sig.r, sig.s, sig.v,
guardians,
guardianCount,
prevGuardianIndex,
isFirstSignature
))
return false;
prevGuardianIndex = guardianIndex;
isFirstSignature = false;
}
return true;
}}
function decodeAndVerifyVaaCd(
address wormhole,
bytes calldata encodedVaa
) internal view returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes calldata payload
) { unchecked {
uint offset = VaaLib.checkVaaVersionCd(encodedVaa);
uint32 guardianSetIndex;
(guardianSetIndex, offset) = encodedVaa.asUint32CdUnchecked(offset);
address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
uint guardianCount = guardians.length; //optimization puts var on stack thus avoids mload
uint signatureCount;
(signatureCount, offset) = encodedVaa.asUint8CdUnchecked(offset);
//this check will also handle empty guardian sets, because minSigsForQuorum(0) is 1 and so
// subsequent signature verification will fail
if (signatureCount < minSigsForQuorum(guardianCount))
revert VerificationFailed();
uint envelopeOffset = offset + signatureCount * VaaLib.GUARDIAN_SIGNATURE_SIZE;
bytes32 vaaHash = encodedVaa.calcVaaDoubleHashCd(envelopeOffset);
bool isFirstSignature = true; //optimization instead of always checking i == 0
uint prevGuardianIndex;
for (uint i = 0; i < signatureCount; ++i) {
uint guardianIndex; bytes32 r; bytes32 s; uint8 v;
(guardianIndex, r, s, v, offset) = encodedVaa.decodeGuardianSignatureCdUnchecked(offset);
if (_failsVerification(
vaaHash,
guardianIndex,
r, s, v,
guardians,
guardianCount,
prevGuardianIndex,
isFirstSignature
))
revert VerificationFailed();
prevGuardianIndex = guardianIndex;
isFirstSignature = false;
}
return encodedVaa.decodeVaaBodyCd(envelopeOffset);
}}
function decodeAndVerifyVaaMem(
address wormhole,
bytes memory encodedVaa
) internal view returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes memory payload
) {
(timestamp, nonce, emitterChainId, emitterAddress, sequence, consistencyLevel, payload, ) =
decodeAndVerifyVaaMem(wormhole, encodedVaa, 0, encodedVaa.length);
}
function decodeAndVerifyVaaMem(
address wormhole,
bytes memory encodedVaa,
uint offset,
uint vaaLength
) internal view returns (
uint32 timestamp,
uint32 nonce,
uint16 emitterChainId,
bytes32 emitterAddress,
uint64 sequence,
uint8 consistencyLevel,
bytes memory payload,
uint newOffset
) { unchecked {
offset = VaaLib.checkVaaVersionMemUnchecked(encodedVaa, offset);
uint32 guardianSetIndex;
(guardianSetIndex, offset) = encodedVaa.asUint32MemUnchecked(offset);
address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
uint guardianCount = guardians.length;
uint signatureCount;
(signatureCount, offset) = encodedVaa.asUint8MemUnchecked(offset);
//this check will also handle empty guardian sets, because minSigsForQuorum(0) is 1 and so
// subsequent signature verification will fail
if (signatureCount < minSigsForQuorum(guardianCount))
revert VerificationFailed();
uint envelopeOffset = offset + signatureCount * VaaLib.GUARDIAN_SIGNATURE_SIZE;
bytes32 vaaHash = encodedVaa.calcVaaDoubleHashMem(envelopeOffset, vaaLength);
bool isFirstSignature = true; //optimization instead of always checking i == 0
uint prevGuardianIndex;
for (uint i = 0; i < signatureCount; ++i) {
uint guardianIndex; bytes32 r; bytes32 s; uint8 v;
(guardianIndex, r, s, v, offset) = encodedVaa.decodeGuardianSignatureMemUnchecked(offset);
if (_failsVerification(
vaaHash,
guardianIndex,
r, s, v,
guardians,
guardianCount,
prevGuardianIndex,
isFirstSignature
))
revert VerificationFailed();
prevGuardianIndex = guardianIndex;
isFirstSignature = false;
}
( timestamp,
nonce,
emitterChainId,
emitterAddress,
sequence,
consistencyLevel,
payload,
newOffset
) = encodedVaa.decodeVaaBodyMemUnchecked(envelopeOffset, vaaLength);
}}
function isVerifiedByQuorumCd(
address wormhole,
bytes32 hash,
GuardianSignature[] calldata guardianSignatures,
uint32 guardianSetIndex
) internal view returns (bool) {
address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
return isVerifiedByQuorumCd(hash, guardianSignatures, guardians);
}
function isVerifiedByQuorumMem(
address wormhole,
bytes32 hash,
GuardianSignature[] memory guardianSignatures,
uint32 guardianSetIndex
) internal view returns (bool) {
address[] memory guardians = getGuardiansOrLatest(wormhole, guardianSetIndex);
return isVerifiedByQuorumMem(hash, guardianSignatures, guardians);
}
//returns empty array if the guardian set is expired
//has more predictable gas costs (guaranteed to only do one external call)
function getGuardiansOrEmpty(
address wormhole,
uint32 guardianSetIndex
) internal view returns (address[] memory guardians) {
IWormhole.GuardianSet memory guardianSet = IWormhole(wormhole).getGuardianSet(guardianSetIndex);
if (!_isExpired(guardianSet))
guardians = guardianSet.keys;
}
//returns associated guardian set or latest guardian set if the specified one is expired
//has more variable gas costs but has a chance of doing an ad-hoc "repair" of the VAA in case
// the specified signatures are valid for the latest guardian set as well (about a 30 % chance
// for the typical guardian set rotation where one guardian address gets replaced).
function getGuardiansOrLatest(
address wormhole,
uint32 guardianSetIndex
) internal view returns (address[] memory guardians) {
IWormhole.GuardianSet memory guardianSet = IWormhole(wormhole).getGuardianSet(guardianSetIndex);
if (_isExpired(guardianSet))
//if the specified guardian set is expired, we try using the current guardian set as an adhoc
// repair attempt (there's almost certainly never more than 2 valid guardian sets at a time)
guardianSet = IWormhole(wormhole).getGuardianSet(
IWormhole(wormhole).getCurrentGuardianSetIndex()
);
guardians = guardianSet.keys;
}
//negated for optimization because we always want to act on incorrect signatures and so save a NOT
function _failsVerification(
bytes32 hash,
uint guardianIndex,
bytes32 r,
bytes32 s,
uint8 v,
address[] memory guardians,
uint guardianCount,
uint prevGuardianIndex,
bool isFirstSignature
) private pure returns (bool) {
address signatory = ecrecover(hash, v, r, s);
address guardian = guardians.readUnchecked(guardianIndex);
//check that:
// * the guardian indicies are in strictly ascending order (only after the first signature)
// this is itself an optimization to efficiently prevent having the same guardian signature
// included twice
// * that the guardian index is not out of bounds
// * that the signatory is the guardian
//
// the core bridge also includes a separate check that signatory is not the zero address
// but this is already covered by comparing that the signatory matches the guardian which
// [can never be the zero address](https://github.com/wormhole-foundation/wormhole/blob/1dbe8459b96e182932d0dd5ae4b6bbce6f48cb09/ethereum/contracts/Setters.sol#L20)
return eagerOr(
eagerOr(
!eagerOr(isFirstSignature, guardianIndex > prevGuardianIndex),
guardianIndex >= guardianCount
),
signatory != guardian
);
}
function _isExpired(IWormhole.GuardianSet memory guardianSet) private view returns (bool) {
uint expirationTime = guardianSet.expirationTime;
return eagerAnd(expirationTime != 0, expirationTime < block.timestamp);
}
}// 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;
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 IMakinaGovernable {
event AccountingAgentAdded(address indexed newAgent);
event AccountingAgentRemoved(address indexed agent);
event MechanicChanged(address indexed oldMechanic, address indexed newMechanic);
event RecoveryModeChanged(bool recoveryMode);
event RestrictedAccountingModeChanged(bool restrictedAccountingMode);
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.
/// @param initialRestrictedAccountingMode The initial value for the restricted accounting mode.
struct MakinaGovernableInitParams {
address initialMechanic;
address initialSecurityCouncil;
address initialRiskManager;
address initialRiskManagerTimelock;
address initialAuthority;
bool initialRestrictedAccountingMode;
}
/// @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 True if the contract is in restricted accounting mode, false otherwise.
function restrictedAccountingMode() external view returns (bool);
/// @notice User => Whether the user is an accounting agent
function isAccountingAgent(address agent) external view returns (bool);
/// @notice User => Whether the user is the current operator
/// The operator is either the mechanic or the security council depending on the recovery mode.
function isOperator(address user) external view returns (bool);
/// @notice User => Whether the user is authorized to perform accounting operations under current settings
function isAccountingAuthorized(address user) 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;
/// @notice Sets the restricted accounting mode.
/// @param enabled True to enable restricted accounting mode, false to disable it.
function setRestrictedAccountingMode(bool enabled) external;
/// @notice Adds a new accounting agent.
/// @param newAgent The address of the new accounting agent.
function addAccountingAgent(address newAgent) external;
/// @notice Removes an accounting agent.
/// @param agent The address of the accounting agent to remove.
function removeAccountingAgent(address agent) external;
}// 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.14; //for (bugfixed) support of `using ... global;` syntax for libraries
import {WORD_SIZE} from "wormhole-sdk/constants/Common.sol";
// ╭──────────────────────────────────────────────────────────────────────╮
// │ Library for [reading from/writing to] memory without bounds checking │
// ╰──────────────────────────────────────────────────────────────────────╯
library UncheckedIndexing {
function readUnchecked(bytes memory arr, uint index) internal pure returns (uint256 ret) {
/// @solidity memory-safe-assembly
assembly { ret := mload(add(add(arr, WORD_SIZE), index)) }
}
function writeUnchecked(bytes memory arr, uint index, uint256 value) internal pure {
/// @solidity memory-safe-assembly
assembly { mstore(add(add(arr, WORD_SIZE), index), value) }
}
function readUnchecked(address[] memory arr, uint index) internal pure returns (address ret) {
bytes memory arrBytes;
/// @solidity memory-safe-assembly
assembly { arrBytes := arr }
uint256 raw = readUnchecked(arrBytes, _mulWordSize(index));
/// @solidity memory-safe-assembly
assembly { ret := raw }
}
//it is assumed that value is never dirty here (it's hard to create a dirty address)
// see https://docs.soliditylang.org/en/latest/internals/variable_cleanup.html
function writeUnchecked(address[] memory arr, uint index, address value) internal pure {
bytes memory arrBytes;
/// @solidity memory-safe-assembly
assembly { arrBytes := arr }
writeUnchecked(arrBytes, _mulWordSize(index), uint256(uint160(value)));
}
function readUnchecked(uint256[] memory arr, uint index) internal pure returns (uint256 ret) {
bytes memory arrBytes;
/// @solidity memory-safe-assembly
assembly { arrBytes := arr }
return readUnchecked(arrBytes, _mulWordSize(index));
}
function writeUnchecked(uint256[] memory arr, uint index, uint256 value) internal pure {
bytes memory arrBytes;
/// @solidity memory-safe-assembly
assembly { arrBytes := arr }
writeUnchecked(arrBytes, _mulWordSize(index), value);
}
function _mulWordSize(uint index) private pure returns (uint) { unchecked {
return index * WORD_SIZE;
}}
}// 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
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: 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));
}
}{
"remappings": [
"@makina-core/=lib/makina-core/src/",
"@makina-core-test/=lib/makina-core/test/",
"@makina-core-script/=lib/makina-core/script/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/contracts/",
"@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/",
"@balancer-v2-interfaces/=lib/balancer-v2-monorepo/pkg/interfaces/contracts/",
"@balancer-v3-interfaces/=lib/balancer-v3-monorepo/pkg/interfaces/contracts/",
"@morpho/=lib/morpho-blue/src/",
"@aave/=lib/aave-v3-origin/src/contracts/",
"@balancer-labs/=lib/balancer-v2-monorepo/../../node_modules/@balancer-labs/",
"@enso-weiroll/=lib/makina-core/lib/enso-weiroll/contracts/",
"@layerzerolabs/lz-evm-messagelib-v2/=lib/makina-core/lib/LayerZero-v2/packages/layerzero-v2/evm/messagelib/",
"@layerzerolabs/lz-evm-oapp-v2/=lib/makina-core/lib/LayerZero-v2/packages/layerzero-v2/evm/oapp/",
"@layerzerolabs/lz-evm-protocol-v2/=lib/makina-core/lib/LayerZero-v2/packages/layerzero-v2/evm/protocol/",
"@layerzerolabs/oapp-evm/=lib/makina-core/lib/devtools/packages/oapp-evm/",
"@layerzerolabs/oft-evm/=lib/makina-core/lib/devtools/packages/oft-evm/",
"@layerzerolabs/test-evm/=lib/makina-core/lib/devtools/packages/test-devtools-evm-foundry/",
"@wormhole/sdk/=lib/makina-core/lib/wormhole-solidity-sdk/src/",
"IERC20/=lib/makina-core/lib/wormhole-solidity-sdk/src/interfaces/token/",
"LayerZero-v2/=lib/makina-core/lib/",
"SafeERC20/=lib/makina-core/lib/wormhole-solidity-sdk/src/libraries/",
"aave-v3-origin/=lib/aave-v3-origin/",
"balancer-v2-monorepo/=lib/balancer-v2-monorepo/",
"balancer-v3-monorepo/=lib/balancer-v3-monorepo/",
"devtools/=lib/makina-core/lib/devtools/packages/toolbox-foundry/src/",
"ds-test/=lib/aave-v3-origin/lib/forge-std/lib/ds-test/src/",
"enso-weiroll/=lib/makina-core/lib/enso-weiroll/contracts/",
"erc4626-tests/=lib/openzeppelin-contracts-upgradeable/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts-upgradeable/lib/halmos-cheatcodes/src/",
"makina-core/=lib/makina-core/",
"morpho-blue/=lib/morpho-blue/",
"openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/",
"openzeppelin-contracts/=lib/openzeppelin-contracts-upgradeable/lib/openzeppelin-contracts/",
"solidity-utils/=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": 150
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"ChainIdMismatch","type":"error"},{"inputs":[],"name":"InvalidContractAddress","type":"error"},{"inputs":[],"name":"InvalidFunctionSignature","type":"error"},{"inputs":[{"internalType":"uint256","name":"received","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"InvalidPayloadLength","type":"error"},{"inputs":[],"name":"InvalidResponseVersion","type":"error"},{"inputs":[],"name":"NumberOfResponsesMismatch","type":"error"},{"inputs":[],"name":"RequestTypeMismatch","type":"error"},{"inputs":[],"name":"UnexpectedNumberOfResults","type":"error"},{"inputs":[],"name":"UnexpectedResultLength","type":"error"},{"inputs":[{"internalType":"uint8","name":"received","type":"uint8"}],"name":"UnsupportedQueryType","type":"error"},{"inputs":[],"name":"VerificationFailed","type":"error"},{"inputs":[],"name":"VersionMismatch","type":"error"},{"inputs":[{"internalType":"uint8","name":"received","type":"uint8"},{"internalType":"uint8","name":"expected","type":"uint8"}],"name":"WrongQueryType","type":"error"},{"inputs":[],"name":"ZeroQueries","type":"error"},{"inputs":[{"internalType":"address","name":"wormhole","type":"address"},{"internalType":"bytes","name":"response","type":"bytes"},{"components":[{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"uint8","name":"guardianIndex","type":"uint8"}],"internalType":"struct GuardianSignature[]","name":"signatures","type":"tuple[]"}],"name":"decodeAndVerifyQueryResponse","outputs":[{"components":[{"internalType":"uint8","name":"version","type":"uint8"},{"internalType":"uint16","name":"senderChainId","type":"uint16"},{"internalType":"uint32","name":"nonce","type":"uint32"},{"internalType":"bytes","name":"requestId","type":"bytes"},{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"uint8","name":"queryType","type":"uint8"},{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes","name":"response","type":"bytes"}],"internalType":"struct PerChainQueryResponse[]","name":"responses","type":"tuple[]"}],"internalType":"struct QueryResponse","name":"ret","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint16","name":"chainId","type":"uint16"},{"internalType":"uint8","name":"queryType","type":"uint8"},{"internalType":"bytes","name":"request","type":"bytes"},{"internalType":"bytes","name":"response","type":"bytes"}],"internalType":"struct PerChainQueryResponse","name":"pcr","type":"tuple"},{"internalType":"address","name":"caliberMailbox","type":"address"}],"name":"getAccountingData","outputs":[{"components":[{"internalType":"uint256","name":"netAum","type":"uint256"},{"internalType":"bytes[]","name":"positions","type":"bytes[]"},{"internalType":"bytes[]","name":"baseTokens","type":"bytes[]"},{"internalType":"bytes[]","name":"bridgesIn","type":"bytes[]"},{"internalType":"bytes[]","name":"bridgesOut","type":"bytes[]"}],"internalType":"struct ICaliberMailbox.SpokeCaliberAccountingData","name":"","type":"tuple"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"}]Contract Creation Code
6118d0610034600b8282823980515f1a607314602857634e487b7160e01b5f525f60045260245ffd5b305f52607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061003f575f3560e01c8063437b9b3e14610043578063586c2a021461006d575b5f5ffd5b610056610051366004611114565b61008d565b60405161006492919061126c565b60405180910390f35b61008061007b36600461133b565b61022c565b60405161006491906113e9565b6100be6040518060a001604052805f8152602001606081526020016060815260200160608152602001606081525090565b5f5f6100c9856102ab565b90508060800151516001146100f157604051633a279ba160e01b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833701905050905085825f81518110610147576101476114db565b60200260200101906001600160a01b031690816001600160a01b031681525050636775608d60e01b815f81518110610181576101816114db565b60200260200101906001600160e01b03191690816001600160e01b031916815250506101cb83608001515f815181106101bc576101bc6114db565b60200260200101518383610505565b82608001515f815181106101e1576101e16114db565b60200260200101516040015180602001905181019061020091906115d9565b620f4240846040015161021391906116cb565b9095506001600160401b031693505050505b9250929050565b610234610f8c565b6102a186868686868b6001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610278573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029c9190611717565b61055f565b9695505050505050565b6102ec6040518060a00160405280606081526020015f6001600160401b031681526020015f6001600160401b031681526020015f8152602001606081525090565b602082015160ff1660011461032b5760208201516040516396b8e05b60e01b815260ff9091166004820152600160248201526044015b60405180910390fd5b5f5f5f61034583866040015161058a90919063ffffffff16565b90855260408681015182016001908101516060808a0180518801600801516001600160401b0390811660208c01528151890160280151928b0192909252805188016030015190911693890193909352915185016031908101519190930195509190930192915060ff808216908316146103d15760405163179ef5bb60e21b815260040160405180910390fd5b8160ff166001600160401b038111156103ec576103ec610fb8565b60405190808252806020026020018201604052801561044957816020015b61043660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161040a5790505b5060808601525f5b8260ff168110156104dd575f86608001518281518110610473576104736114db565b602002602001015190506104948689604001516105b590919063ffffffff16565b6001600160a01b03909116825260408901519096506104b3908761058a565b602083019190915260608901519096506104cd908661058a565b6040909201529350600101610451565b506104ed866040015151856105ca565b6104fc866060015151846105ca565b50505050919050565b81511561051857825161051890836105f8565b80511561055a57600483602001515110156105465760405163403b6ec560e11b815260040160405180910390fd5b6020838101510151610558818361065e565b505b505050565b610567610f8c565b6105758787878787876106c6565b61057f8686610701565b979650505050505050565b60048183018101516060918301906105a9858363ffffffff8416610b8e565b90969095509350505050565b60148183018101515f918291829185016105a9565b8082146105f45760405163061bc83560e51b81526004810183905260248101829052604401610322565b5050565b80515f5b8181101561064457828181518110610616576106166114db565b60200260200101516001600160a01b0316846001600160a01b03160361063c5750505050565b6001016105fc565b5060405163a710429d60e01b815260040160405180910390fd5b80515f5b818110156106ac5782818151811061067c5761067c6114db565b60200260200101516001600160e01b031916846001600160e01b031916036106a45750505050565b600101610662565b5060405163403b6ec560e11b815260040160405180910390fd5b6106dc866106d48787610bdf565b858585610bf9565b6106f95760405163439cc0cd60e01b815260040160405180910390fd5b505050505050565b610709610f8c565b823560f81c80825260019081146107325760405162ecb0bd60e51b815260040160405180910390fd5b8381013560f01c6020830181905260029091019061076a9082901561075857602061075b565b60415b8187019260ff90911691820190565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060860152845160048083019550888301803560e01c9550600590930193509091013560f81c9060ff1681146107e85760405163714f551360e01b815260040160405180910390fd5b50858101803560e01c60408601526005909101906004013560f81c5f8190036108245760405163bb6b170d60e01b815260040160405180910390fd5b63ffffffff80841685019081905f90610843908b908b908590610c1316565b9350905060ff8082169085161461086d5760405163084ae4a360e41b815260040160405180910390fd5b8360ff166001600160401b0381111561088857610888610fb8565b6040519080825280602002602001820160405280156108db57816020015b604080516080810182525f80825260208201526060918101829052818101919091528152602001906001900390816108a65790505b5060808901525f5b8460ff16811015610b4c57858b013560f01c600287018a60800151838151811061090f5761090f6114db565b602090810291909101015161ffff9290921690915260808a0151805191975060028601958d013560f01c918390811061094a5761094a6114db565b60200260200101515f015161ffff168161ffff161461097c5760405163a179f8c960e01b815260040160405180910390fd5b868c013560f81c600188018b60800151848151811061099d5761099d6114db565b60200260200101516020018199508260ff1660ff1681525050506109e18a6080015183815181106109d0576109d06114db565b602002602001015160200151610c25565b60808a0151805160018701968e013560f81c919084908110610a0557610a056114db565b60200260200101516020015160ff168160ff1614610a3657604051630216496160e01b815260040160405180910390fd5b878d016004818101913560e01c90818b010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610aa757610aa76114db565b6020908102919091010151604001919091529750858d016004818101913560e01c908189010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610b2c57610b2c6114db565b6020026020010151606001819850829052505050508060010190506108e3565b50848214610b775760405163061bc83560e51b81526004810183905260248101869052604401610322565b610b8189846105ca565b5050505050505092915050565b604051828201601f831680610ba1575060205b80830184810186838901015b81831015610bc5578051835260209283019201610bad565b5050848452601f19601f8201166040525050935093915050565b5f610bf2610bed8484610c5c565b610c6e565b9392505050565b5f5f610c058784610cb7565b905061057f86868684610e2a565b9182013560f81c926001909201919050565b610c3660ff82168015906005101790565b15610c59576040516351ee585360e01b815260ff82166004820152602401610322565b50565b5f604051828482379190912092915050565b5f6040518060600160405280602381526020016118786023913982604051602001610c9a929190611730565b604051602081830303815290604052805190602001209050919050565b604051637ca8cbad60e11b815263ffffffff821660048201526060905f906001600160a01b0385169063f951975a906024015f60405180830381865afa158015610d03573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d2a919081019061174a565b9050610d45816020015163ffffffff16801515429091101690565b15610e2257836001600160a01b031663f951975a856001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db99190611717565b6040516001600160e01b031960e084901b16815263ffffffff9190911660048201526024015f60405180830381865afa158015610df8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e1f919081019061174a565b90505b519392505050565b80515f908360016003600284020401811015610e4a575f92505050610ec2565b60015f805b83811015610eb8575f610e6d608083028b0136819003810190611826565b90505f816060015160ff169050610e968c82845f0151856020015186604001518e8d8b8d610eca565b15610eaa575f975050505050505050610ec2565b5f9450925050600101610e4f565b5060019450505050505b949350505050565b604080515f808252602082018084528c905260ff8816928201929092526060810189905260808101889052819060019060a0016020604051602081039080840390855afa158015610f1d573d5f5f3e3d5ffd5b5050604051601f19015191505f9050610f36878c610f70565b9050610f60868c1015868d1186171517826001600160a01b0316846001600160a01b031614151790565b9c9b505050505050505050505050565b5f8281610f838260208602016020015190565b95945050505050565b6040805160a0810182525f80825260208201819052918101919091526060808201819052608082015290565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b0381118282101715610fee57610fee610fb8565b60405290565b60405160a081016001600160401b0381118282101715610fee57610fee610fb8565b604080519081016001600160401b0381118282101715610fee57610fee610fb8565b604051601f8201601f191681016001600160401b038111828210171561106057611060610fb8565b604052919050565b803560ff81168114611078575f5ffd5b919050565b5f6001600160401b0382111561109557611095610fb8565b50601f01601f191660200190565b5f82601f8301126110b2575f5ffd5b81356110c56110c08261107d565b611038565b8181528460208386010111156110d9575f5ffd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114610c59575f5ffd5b8035611078816110f5565b5f5f60408385031215611125575f5ffd5b82356001600160401b0381111561113a575f5ffd5b83016080818603121561114b575f5ffd5b611153610fcc565b813561ffff81168114611164575f5ffd5b815261117260208301611068565b602082015260408201356001600160401b0381111561118f575f5ffd5b61119b878285016110a3565b60408301525060608201356001600160401b038111156111b9575f5ffd5b6111c5878285016110a3565b60608301525092506111db905060208401611109565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561126057601f1985840301885261124a8383516111e4565b602098890198909350919091019060010161122e565b50909695505050505050565b60408152825160408201525f602084015160a0606084015261129160e0840182611212565b90506040850151603f198483030160808501526112ae8282611212565b9150506060850151603f198483030160a08501526112cc8282611212565b9150506080850151603f198483030160c08501526112ea8282611212565b925050508260208301529392505050565b5f5f83601f84011261130b575f5ffd5b5081356001600160401b03811115611321575f5ffd5b6020830191508360208260071b8501011115610225575f5ffd5b5f5f5f5f5f6060868803121561134f575f5ffd5b853561135a816110f5565b945060208601356001600160401b03811115611374575f5ffd5b8601601f81018813611384575f5ffd5b80356001600160401b03811115611399575f5ffd5b8860208284010111156113aa575f5ffd5b6020919091019450925060408601356001600160401b038111156113cc575f5ffd5b6113d8888289016112fb565b969995985093965092949392505050565b6020815260ff825116602082015261ffff602083015116604082015263ffffffff60408301511660608201525f606083015160a0608084015261142f60c08401826111e4565b6080850151848203601f190160a0860152805180835291925060209081019181840191600582901b8501015f5b828110156114cf57601f19868303018452845161ffff815116835260ff602082015116602084015260408101516080604085015261149d60808501826111e4565b90506060820151915083810360608501526114b881836111e4565b60209788019796909601959350505060010161145c565b50979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6001600160401b0382111561150757611507610fb8565b5060051b60200190565b5f82601f830112611520575f5ffd5b815161152e6110c0826114ef565b8082825260208201915060208360051b86010192508583111561154f575f5ffd5b602085015b838110156115cf5780516001600160401b03811115611571575f5ffd5b8601603f81018813611581575f5ffd5b60208101516115926110c08261107d565b8181526040838301018a10156115a6575f5ffd5b8160408401602083015e5f60208383010152808652505050602083019250602081019050611554565b5095945050505050565b5f602082840312156115e9575f5ffd5b81516001600160401b038111156115fe575f5ffd5b820160a0818503121561160f575f5ffd5b611617610ff4565b8151815260208201516001600160401b03811115611633575f5ffd5b61163f86828501611511565b60208301525060408201516001600160401b0381111561165d575f5ffd5b61166986828501611511565b60408301525060608201516001600160401b03811115611687575f5ffd5b61169386828501611511565b60608301525060808201516001600160401b038111156116b1575f5ffd5b6116bd86828501611511565b608083015250949350505050565b5f6001600160401b038316806116ef57634e487b7160e01b5f52601260045260245ffd5b806001600160401b0384160491505092915050565b805163ffffffff81168114611078575f5ffd5b5f60208284031215611727575f5ffd5b610bf282611704565b5f83518060208601845e9190910191825250602001919050565b5f6020828403121561175a575f5ffd5b81516001600160401b0381111561176f575f5ffd5b820160408185031215611780575f5ffd5b611788611016565b81516001600160401b0381111561179d575f5ffd5b8201601f810186136117ad575f5ffd5b80516117bb6110c0826114ef565b8082825260208201915060208360051b8501019250888311156117dc575f5ffd5b6020840193505b828410156118075783516117f6816110f5565b8252602093840193909101906117e3565b84525061181991505060208301611704565b6020820152949350505050565b5f6080828403128015611837575f5ffd5b50611840610fcc565b823581526020808401359082015261185a60408401611068565b604082015261186b60608401611068565b6060820152939250505056fe71756572795f726573706f6e73655f303030303030303030303030303030303030307ca264697066735822122034eda57296f1839d0267b77a23e93b47c1136cec60f2ca51d16b7a95733a509364736f6c634300081c0033
Deployed Bytecode
0x73efc2bfa5dab062d0ee4c9dd955536e44d5ce4db5301460806040526004361061003f575f3560e01c8063437b9b3e14610043578063586c2a021461006d575b5f5ffd5b610056610051366004611114565b61008d565b60405161006492919061126c565b60405180910390f35b61008061007b36600461133b565b61022c565b60405161006491906113e9565b6100be6040518060a001604052805f8152602001606081526020016060815260200160608152602001606081525090565b5f5f6100c9856102ab565b90508060800151516001146100f157604051633a279ba160e01b815260040160405180910390fd5b6040805160018082528183019092525f916020808301908036833750506040805160018082528183019092529293505f9291506020808301908036833701905050905085825f81518110610147576101476114db565b60200260200101906001600160a01b031690816001600160a01b031681525050636775608d60e01b815f81518110610181576101816114db565b60200260200101906001600160e01b03191690816001600160e01b031916815250506101cb83608001515f815181106101bc576101bc6114db565b60200260200101518383610505565b82608001515f815181106101e1576101e16114db565b60200260200101516040015180602001905181019061020091906115d9565b620f4240846040015161021391906116cb565b9095506001600160401b031693505050505b9250929050565b610234610f8c565b6102a186868686868b6001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610278573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061029c9190611717565b61055f565b9695505050505050565b6102ec6040518060a00160405280606081526020015f6001600160401b031681526020015f6001600160401b031681526020015f8152602001606081525090565b602082015160ff1660011461032b5760208201516040516396b8e05b60e01b815260ff9091166004820152600160248201526044015b60405180910390fd5b5f5f5f61034583866040015161058a90919063ffffffff16565b90855260408681015182016001908101516060808a0180518801600801516001600160401b0390811660208c01528151890160280151928b0192909252805188016030015190911693890193909352915185016031908101519190930195509190930192915060ff808216908316146103d15760405163179ef5bb60e21b815260040160405180910390fd5b8160ff166001600160401b038111156103ec576103ec610fb8565b60405190808252806020026020018201604052801561044957816020015b61043660405180606001604052805f6001600160a01b0316815260200160608152602001606081525090565b81526020019060019003908161040a5790505b5060808601525f5b8260ff168110156104dd575f86608001518281518110610473576104736114db565b602002602001015190506104948689604001516105b590919063ffffffff16565b6001600160a01b03909116825260408901519096506104b3908761058a565b602083019190915260608901519096506104cd908661058a565b6040909201529350600101610451565b506104ed866040015151856105ca565b6104fc866060015151846105ca565b50505050919050565b81511561051857825161051890836105f8565b80511561055a57600483602001515110156105465760405163403b6ec560e11b815260040160405180910390fd5b6020838101510151610558818361065e565b505b505050565b610567610f8c565b6105758787878787876106c6565b61057f8686610701565b979650505050505050565b60048183018101516060918301906105a9858363ffffffff8416610b8e565b90969095509350505050565b60148183018101515f918291829185016105a9565b8082146105f45760405163061bc83560e51b81526004810183905260248101829052604401610322565b5050565b80515f5b8181101561064457828181518110610616576106166114db565b60200260200101516001600160a01b0316846001600160a01b03160361063c5750505050565b6001016105fc565b5060405163a710429d60e01b815260040160405180910390fd5b80515f5b818110156106ac5782818151811061067c5761067c6114db565b60200260200101516001600160e01b031916846001600160e01b031916036106a45750505050565b600101610662565b5060405163403b6ec560e11b815260040160405180910390fd5b6106dc866106d48787610bdf565b858585610bf9565b6106f95760405163439cc0cd60e01b815260040160405180910390fd5b505050505050565b610709610f8c565b823560f81c80825260019081146107325760405162ecb0bd60e51b815260040160405180910390fd5b8381013560f01c6020830181905260029091019061076a9082901561075857602061075b565b60415b8187019260ff90911691820190565b82828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f920191909152505050506060860152845160048083019550888301803560e01c9550600590930193509091013560f81c9060ff1681146107e85760405163714f551360e01b815260040160405180910390fd5b50858101803560e01c60408601526005909101906004013560f81c5f8190036108245760405163bb6b170d60e01b815260040160405180910390fd5b63ffffffff80841685019081905f90610843908b908b908590610c1316565b9350905060ff8082169085161461086d5760405163084ae4a360e41b815260040160405180910390fd5b8360ff166001600160401b0381111561088857610888610fb8565b6040519080825280602002602001820160405280156108db57816020015b604080516080810182525f80825260208201526060918101829052818101919091528152602001906001900390816108a65790505b5060808901525f5b8460ff16811015610b4c57858b013560f01c600287018a60800151838151811061090f5761090f6114db565b602090810291909101015161ffff9290921690915260808a0151805191975060028601958d013560f01c918390811061094a5761094a6114db565b60200260200101515f015161ffff168161ffff161461097c5760405163a179f8c960e01b815260040160405180910390fd5b868c013560f81c600188018b60800151848151811061099d5761099d6114db565b60200260200101516020018199508260ff1660ff1681525050506109e18a6080015183815181106109d0576109d06114db565b602002602001015160200151610c25565b60808a0151805160018701968e013560f81c919084908110610a0557610a056114db565b60200260200101516020015160ff168160ff1614610a3657604051630216496160e01b815260040160405180910390fd5b878d016004818101913560e01c90818b010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610aa757610aa76114db565b6020908102919091010151604001919091529750858d016004818101913560e01c908189010182828080601f0160208091040260200160405190810160405280939291908181526020018383808284375f81840152601f19601f8201169050808301925050505050505091509091508c608001518581518110610b2c57610b2c6114db565b6020026020010151606001819850829052505050508060010190506108e3565b50848214610b775760405163061bc83560e51b81526004810183905260248101869052604401610322565b610b8189846105ca565b5050505050505092915050565b604051828201601f831680610ba1575060205b80830184810186838901015b81831015610bc5578051835260209283019201610bad565b5050848452601f19601f8201166040525050935093915050565b5f610bf2610bed8484610c5c565b610c6e565b9392505050565b5f5f610c058784610cb7565b905061057f86868684610e2a565b9182013560f81c926001909201919050565b610c3660ff82168015906005101790565b15610c59576040516351ee585360e01b815260ff82166004820152602401610322565b50565b5f604051828482379190912092915050565b5f6040518060600160405280602381526020016118786023913982604051602001610c9a929190611730565b604051602081830303815290604052805190602001209050919050565b604051637ca8cbad60e11b815263ffffffff821660048201526060905f906001600160a01b0385169063f951975a906024015f60405180830381865afa158015610d03573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610d2a919081019061174a565b9050610d45816020015163ffffffff16801515429091101690565b15610e2257836001600160a01b031663f951975a856001600160a01b0316631cfe79516040518163ffffffff1660e01b8152600401602060405180830381865afa158015610d95573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610db99190611717565b6040516001600160e01b031960e084901b16815263ffffffff9190911660048201526024015f60405180830381865afa158015610df8573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610e1f919081019061174a565b90505b519392505050565b80515f908360016003600284020401811015610e4a575f92505050610ec2565b60015f805b83811015610eb8575f610e6d608083028b0136819003810190611826565b90505f816060015160ff169050610e968c82845f0151856020015186604001518e8d8b8d610eca565b15610eaa575f975050505050505050610ec2565b5f9450925050600101610e4f565b5060019450505050505b949350505050565b604080515f808252602082018084528c905260ff8816928201929092526060810189905260808101889052819060019060a0016020604051602081039080840390855afa158015610f1d573d5f5f3e3d5ffd5b5050604051601f19015191505f9050610f36878c610f70565b9050610f60868c1015868d1186171517826001600160a01b0316846001600160a01b031614151790565b9c9b505050505050505050505050565b5f8281610f838260208602016020015190565b95945050505050565b6040805160a0810182525f80825260208201819052918101919091526060808201819052608082015290565b634e487b7160e01b5f52604160045260245ffd5b604051608081016001600160401b0381118282101715610fee57610fee610fb8565b60405290565b60405160a081016001600160401b0381118282101715610fee57610fee610fb8565b604080519081016001600160401b0381118282101715610fee57610fee610fb8565b604051601f8201601f191681016001600160401b038111828210171561106057611060610fb8565b604052919050565b803560ff81168114611078575f5ffd5b919050565b5f6001600160401b0382111561109557611095610fb8565b50601f01601f191660200190565b5f82601f8301126110b2575f5ffd5b81356110c56110c08261107d565b611038565b8181528460208386010111156110d9575f5ffd5b816020850160208301375f918101602001919091529392505050565b6001600160a01b0381168114610c59575f5ffd5b8035611078816110f5565b5f5f60408385031215611125575f5ffd5b82356001600160401b0381111561113a575f5ffd5b83016080818603121561114b575f5ffd5b611153610fcc565b813561ffff81168114611164575f5ffd5b815261117260208301611068565b602082015260408201356001600160401b0381111561118f575f5ffd5b61119b878285016110a3565b60408301525060608201356001600160401b038111156111b9575f5ffd5b6111c5878285016110a3565b60608301525092506111db905060208401611109565b90509250929050565b5f81518084528060208401602086015e5f602082860101526020601f19601f83011685010191505092915050565b5f82825180855260208501945060208160051b830101602085015f5b8381101561126057601f1985840301885261124a8383516111e4565b602098890198909350919091019060010161122e565b50909695505050505050565b60408152825160408201525f602084015160a0606084015261129160e0840182611212565b90506040850151603f198483030160808501526112ae8282611212565b9150506060850151603f198483030160a08501526112cc8282611212565b9150506080850151603f198483030160c08501526112ea8282611212565b925050508260208301529392505050565b5f5f83601f84011261130b575f5ffd5b5081356001600160401b03811115611321575f5ffd5b6020830191508360208260071b8501011115610225575f5ffd5b5f5f5f5f5f6060868803121561134f575f5ffd5b853561135a816110f5565b945060208601356001600160401b03811115611374575f5ffd5b8601601f81018813611384575f5ffd5b80356001600160401b03811115611399575f5ffd5b8860208284010111156113aa575f5ffd5b6020919091019450925060408601356001600160401b038111156113cc575f5ffd5b6113d8888289016112fb565b969995985093965092949392505050565b6020815260ff825116602082015261ffff602083015116604082015263ffffffff60408301511660608201525f606083015160a0608084015261142f60c08401826111e4565b6080850151848203601f190160a0860152805180835291925060209081019181840191600582901b8501015f5b828110156114cf57601f19868303018452845161ffff815116835260ff602082015116602084015260408101516080604085015261149d60808501826111e4565b90506060820151915083810360608501526114b881836111e4565b60209788019796909601959350505060010161145c565b50979650505050505050565b634e487b7160e01b5f52603260045260245ffd5b5f6001600160401b0382111561150757611507610fb8565b5060051b60200190565b5f82601f830112611520575f5ffd5b815161152e6110c0826114ef565b8082825260208201915060208360051b86010192508583111561154f575f5ffd5b602085015b838110156115cf5780516001600160401b03811115611571575f5ffd5b8601603f81018813611581575f5ffd5b60208101516115926110c08261107d565b8181526040838301018a10156115a6575f5ffd5b8160408401602083015e5f60208383010152808652505050602083019250602081019050611554565b5095945050505050565b5f602082840312156115e9575f5ffd5b81516001600160401b038111156115fe575f5ffd5b820160a0818503121561160f575f5ffd5b611617610ff4565b8151815260208201516001600160401b03811115611633575f5ffd5b61163f86828501611511565b60208301525060408201516001600160401b0381111561165d575f5ffd5b61166986828501611511565b60408301525060608201516001600160401b03811115611687575f5ffd5b61169386828501611511565b60608301525060808201516001600160401b038111156116b1575f5ffd5b6116bd86828501611511565b608083015250949350505050565b5f6001600160401b038316806116ef57634e487b7160e01b5f52601260045260245ffd5b806001600160401b0384160491505092915050565b805163ffffffff81168114611078575f5ffd5b5f60208284031215611727575f5ffd5b610bf282611704565b5f83518060208601845e9190910191825250602001919050565b5f6020828403121561175a575f5ffd5b81516001600160401b0381111561176f575f5ffd5b820160408185031215611780575f5ffd5b611788611016565b81516001600160401b0381111561179d575f5ffd5b8201601f810186136117ad575f5ffd5b80516117bb6110c0826114ef565b8082825260208201915060208360051b8501019250888311156117dc575f5ffd5b6020840193505b828410156118075783516117f6816110f5565b8252602093840193909101906117e3565b84525061181991505060208301611704565b6020820152949350505050565b5f6080828403128015611837575f5ffd5b50611840610fcc565b823581526020808401359082015261185a60408401611068565b604082015261186b60608401611068565b6060820152939250505056fe71756572795f726573706f6e73655f303030303030303030303030303030303030307ca264697066735822122034eda57296f1839d0267b77a23e93b47c1136cec60f2ca51d16b7a95733a509364736f6c634300081c0033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 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.