Source Code
Overview
HYPE Balance
HYPE Value
$0.00Latest 6 from a total of 6 transactions
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Block | From | To | |||
|---|---|---|---|---|---|---|
| 175421 | 337 days ago | Contract Creation | 0 HYPE |
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Storage
Compiler Version
v0.8.20+commit.a1b79de6
Optimization Enabled:
Yes with 20 runs
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.17 .0;
import {Net} from "../../net/Net.sol";
/// @title Storage
/// @author Aspyn Palatnick (aspyn.eth, stuckinaboot.eth)
/// @notice Data storage with persistent history using Net
contract Storage {
event Stored(bytes32 indexed key, address indexed operator);
struct BulkPutParams {
bytes32 key;
string text;
bytes value;
}
struct BulkGetParams {
bytes32 key;
address operator;
}
struct BulkGetValueAtIndexParams {
bytes32 key;
address operator;
uint256 idx;
}
struct BulkGetResult {
string text;
bytes value;
}
Net internal net = Net(0x00000000B24D62781dB359b07880a105cD0b64e6);
/// @notice Store value for a given key
/// @param key key
/// @param text text
/// @param value value
function put(
bytes32 key,
string calldata text,
bytes calldata value
) public {
// Convert key to string
string memory topic = string(abi.encodePacked(key));
// Send message on Net
net.sendMessageViaApp(msg.sender, text, topic, value);
// Emit event
emit Stored(key, msg.sender);
}
/// @notice Store values for given params
/// @param params params
function bulkPut(BulkPutParams[] calldata params) external {
for (uint256 i; i < params.length; ) {
put(params[i].key, params[i].text, params[i].value);
unchecked {
++i;
}
}
}
/// @notice Get value for a particular key and operator
/// @param key key
/// @param operator user that stored key
/// @return (text, data) stored value for the particular key-operator pair
function get(
bytes32 key,
address operator
) public view returns (string memory, bytes memory) {
string memory topic = string(abi.encodePacked(key));
// Get most recent message for particular key-operator pair
Net.Message memory message = net.getMessageForAppUserTopic(
net.getTotalMessagesForAppUserTopicCount(
address(this),
operator,
topic
) - 1,
address(this),
operator,
topic
);
return (message.text, message.data);
}
/// @notice Bulk get values for particular parameters
/// @param params parameters
/// @return results for stored values for the particular parameters
function bulkGet(
BulkGetParams[] calldata params
) public view returns (BulkGetResult[] memory results) {
results = new BulkGetResult[](params.length);
for (uint256 i; i < results.length; ) {
(string memory text, bytes memory data) = get(
params[i].key,
params[i].operator
);
results[i] = BulkGetResult(text, data);
unchecked {
++i;
}
}
}
/// @notice Get value at index for a particular key and operator
/// @param key key
/// @param operator user that stored key
/// @param idx index
/// @return (text, data) stored value at index for the particular key-operator pair
function getValueAtIndex(
bytes32 key,
address operator,
uint256 idx
) public view returns (string memory, bytes memory) {
Net.Message memory message = net.getMessageForAppUserTopic(
idx,
address(this),
operator,
string(abi.encodePacked(key))
);
return (message.text, message.data);
}
/// @notice Bulk get value at index for particular parameters
/// @param params parameters
/// @return results for stored values for the particular parameters
function bulkGetValueAtIndex(
BulkGetValueAtIndexParams[] calldata params
) public view returns (BulkGetResult[] memory results) {
results = new BulkGetResult[](params.length);
for (uint256 i; i < results.length; ) {
(string memory text, bytes memory data) = getValueAtIndex(
params[i].key,
params[i].operator,
params[i].idx
);
results[i] = BulkGetResult(text, data);
unchecked {
++i;
}
}
}
/// @notice Get total number of writes to a particular key for a given operator
/// @param key key
/// @param operator user that stored key
/// @return total total writes count
function getTotalWrites(
bytes32 key,
address operator
) public view returns (uint256) {
return
net.getTotalMessagesForAppUserTopicCount(
address(this),
operator,
string(abi.encodePacked(key))
);
}
/// @notice Bulk get total writes for particular parameters
/// @param params parameters
/// @return results for total writes for the particular parameters
function bulkGetTotalWrites(
BulkGetParams[] calldata params
) public view returns (uint256[] memory results) {
results = new uint256[](params.length);
for (uint256 i; i < results.length; ) {
results[i] = getTotalWrites(params[i].key, params[i].operator);
unchecked {
++i;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Read and write to persistent storage at a fraction of the cost.
/// @author Solady (https://github.com/vectorized/solmady/blob/main/src/utils/SSTORE2.sol)
/// @author Saw-mon-and-Natalie (https://github.com/Saw-mon-and-Natalie)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SSTORE2.sol)
/// @author Modified from 0xSequence (https://github.com/0xSequence/sstore2/blob/master/contracts/SSTORE2.sol)
library SSTORE2 {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev We skip the first byte as it's a STOP opcode,
/// which ensures the contract can't be called.
uint256 internal constant DATA_OFFSET = 1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Unable to deploy the storage contract.
error DeploymentFailed();
/// @dev The storage contract address is invalid.
error InvalidPointer();
/// @dev Attempt to read outside of the storage contract's bytecode bounds.
error ReadOutOfBounds();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* WRITE LOGIC */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Writes `data` into the bytecode of a storage contract and returns its address.
function write(bytes memory data) internal returns (address pointer) {
/// @solidity memory-safe-assembly
assembly {
let originalDataLength := mload(data)
// Add 1 to data size since we are prefixing it with a STOP opcode.
let dataSize := add(originalDataLength, DATA_OFFSET)
/**
* ------------------------------------------------------------------------------+
* Opcode | Mnemonic | Stack | Memory |
* ------------------------------------------------------------------------------|
* 61 dataSize | PUSH2 dataSize | dataSize | |
* 80 | DUP1 | dataSize dataSize | |
* 60 0xa | PUSH1 0xa | 0xa dataSize dataSize | |
* 3D | RETURNDATASIZE | 0 0xa dataSize dataSize | |
* 39 | CODECOPY | dataSize | [0..dataSize): code |
* 3D | RETURNDATASIZE | 0 dataSize | [0..dataSize): code |
* F3 | RETURN | | [0..dataSize): code |
* 00 | STOP | | |
* ------------------------------------------------------------------------------+
* @dev Prefix the bytecode with a STOP opcode to ensure it cannot be called.
* Also PUSH2 is used since max contract size cap is 24,576 bytes which is less than 2 ** 16.
*/
mstore(
// Do a out-of-gas revert if `dataSize` is more than 2 bytes.
// The actual EVM limit may be smaller and may change over time.
add(data, gt(dataSize, 0xffff)),
// Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2.
or(0xfd61000080600a3d393df300, shl(0x40, dataSize))
)
// Deploy a new contract with the generated creation code.
pointer := create(0, add(data, 0x15), add(dataSize, 0xa))
// If `pointer` is zero, revert.
if iszero(pointer) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// Restore original length of the variable size `data`.
mstore(data, originalDataLength)
}
}
/// @dev Writes `data` into the bytecode of a storage contract with `salt`
/// and returns its deterministic address.
function writeDeterministic(bytes memory data, bytes32 salt)
internal
returns (address pointer)
{
/// @solidity memory-safe-assembly
assembly {
let originalDataLength := mload(data)
let dataSize := add(originalDataLength, DATA_OFFSET)
mstore(
// Do a out-of-gas revert if `dataSize` is more than 2 bytes.
// The actual EVM limit may be smaller and may change over time.
add(data, gt(dataSize, 0xffff)),
// Left shift `dataSize` by 64 so that it lines up with the 0000 after PUSH2.
or(0xfd61000080600a3d393df300, shl(0x40, dataSize))
)
// Deploy a new contract with the generated creation code.
pointer := create2(0, add(data, 0x15), add(dataSize, 0xa), salt)
// If `pointer` is zero, revert.
if iszero(pointer) {
// Store the function selector of `DeploymentFailed()`.
mstore(0x00, 0x30116425)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// Restore original length of the variable size `data`.
mstore(data, originalDataLength)
}
}
/// @dev Returns the initialization code hash of the storage contract for `data`.
/// Used for mining vanity addresses with create2crunch.
function initCodeHash(bytes memory data) internal pure returns (bytes32 hash) {
/// @solidity memory-safe-assembly
assembly {
let originalDataLength := mload(data)
let dataSize := add(originalDataLength, DATA_OFFSET)
// Do a out-of-gas revert if `dataSize` is more than 2 bytes.
// The actual EVM limit may be smaller and may change over time.
returndatacopy(returndatasize(), returndatasize(), shr(16, dataSize))
mstore(data, or(0x61000080600a3d393df300, shl(0x40, dataSize)))
hash := keccak256(add(data, 0x15), add(dataSize, 0xa))
// Restore original length of the variable size `data`.
mstore(data, originalDataLength)
}
}
/// @dev Returns the address of the storage contract for `data`
/// deployed with `salt` by `deployer`.
/// Note: The returned result has dirty upper 96 bits. Please clean if used in assembly.
function predictDeterministicAddress(bytes memory data, bytes32 salt, address deployer)
internal
pure
returns (address predicted)
{
bytes32 hash = initCodeHash(data);
/// @solidity memory-safe-assembly
assembly {
// Compute and store the bytecode hash.
mstore8(0x00, 0xff) // Write the prefix.
mstore(0x35, hash)
mstore(0x01, shl(96, deployer))
mstore(0x15, salt)
predicted := keccak256(0x00, 0x55)
// Restore the part of the free memory pointer that has been overwritten.
mstore(0x35, 0)
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* READ LOGIC */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns all the `data` from the bytecode of the storage contract at `pointer`.
function read(address pointer) internal view returns (bytes memory data) {
/// @solidity memory-safe-assembly
assembly {
let pointerCodesize := extcodesize(pointer)
if iszero(pointerCodesize) {
// Store the function selector of `InvalidPointer()`.
mstore(0x00, 0x11052bb4)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// Offset all indices by 1 to skip the STOP opcode.
let size := sub(pointerCodesize, DATA_OFFSET)
// Get the pointer to the free memory and allocate
// enough 32-byte words for the data and the length of the data,
// then copy the code to the allocated memory.
// Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
data := mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot.
extcodecopy(pointer, add(data, 0x20), DATA_OFFSET, size)
}
}
/// @dev Returns the `data` from the bytecode of the storage contract at `pointer`,
/// from the byte at `start`, to the end of the data stored.
function read(address pointer, uint256 start) internal view returns (bytes memory data) {
/// @solidity memory-safe-assembly
assembly {
let pointerCodesize := extcodesize(pointer)
if iszero(pointerCodesize) {
// Store the function selector of `InvalidPointer()`.
mstore(0x00, 0x11052bb4)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// If `!(pointer.code.size > start)`, reverts.
// This also handles the case where `start + DATA_OFFSET` overflows.
if iszero(gt(pointerCodesize, start)) {
// Store the function selector of `ReadOutOfBounds()`.
mstore(0x00, 0x84eb0dd1)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
let size := sub(pointerCodesize, add(start, DATA_OFFSET))
// Get the pointer to the free memory and allocate
// enough 32-byte words for the data and the length of the data,
// then copy the code to the allocated memory.
// Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
data := mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot.
extcodecopy(pointer, add(data, 0x20), add(start, DATA_OFFSET), size)
}
}
/// @dev Returns the `data` from the bytecode of the storage contract at `pointer`,
/// from the byte at `start`, to the byte at `end` (exclusive) of the data stored.
function read(address pointer, uint256 start, uint256 end)
internal
view
returns (bytes memory data)
{
/// @solidity memory-safe-assembly
assembly {
let pointerCodesize := extcodesize(pointer)
if iszero(pointerCodesize) {
// Store the function selector of `InvalidPointer()`.
mstore(0x00, 0x11052bb4)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
// If `!(pointer.code.size > end) || (start > end)`, revert.
// This also handles the cases where
// `end + DATA_OFFSET` or `start + DATA_OFFSET` overflows.
if iszero(
and(
gt(pointerCodesize, end), // Within bounds.
iszero(gt(start, end)) // Valid range.
)
) {
// Store the function selector of `ReadOutOfBounds()`.
mstore(0x00, 0x84eb0dd1)
// Revert with (offset, size).
revert(0x1c, 0x04)
}
let size := sub(end, start)
// Get the pointer to the free memory and allocate
// enough 32-byte words for the data and the length of the data,
// then copy the code to the allocated memory.
// Masking with 0xffe0 will suffice, since contract size is less than 16 bits.
data := mload(0x40)
mstore(0x40, add(data, and(add(size, 0x3f), 0xffe0)))
mstore(data, size)
mstore(add(add(data, 0x20), size), 0) // Zeroize the last slot.
extcodecopy(pointer, add(data, 0x20), add(start, DATA_OFFSET), size)
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.17 .0;
interface EventsAndErrors {
error MsgEmpty();
error InvalidRange();
error InvalidStartIndex();
error InvalidEndIndex();
event MessageSent(
address indexed sender,
string indexed topic,
uint256 messageIndex
);
event MessageSentViaApp(
address indexed app,
address indexed sender,
string indexed topic,
uint256 messageIndex
);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.17 .0;
interface INet {
struct Message {
address app;
address sender;
uint256 timestamp;
bytes data;
string text;
string topic;
}
function sendMessageViaApp(
address sender,
string calldata text,
string calldata topic,
bytes calldata extraData
) external;
function sendMessage(
string calldata text,
string calldata topic,
bytes calldata extraData
) external;
// **************
// Fetch Messages
// **************
// Fetch message indexes
function getMessageIdxForApp(
uint256 idx,
address app
) external view returns (uint256);
function getMessageIdxForAppUser(
uint256 idx,
address app,
address user
) external view returns (uint256);
function getMessageIdxForAppTopic(
uint256 idx,
address app,
string calldata topic
) external view returns (uint256);
function getMessageIdxForAppUserTopic(
uint256 idx,
address app,
address user,
string calldata topic
) external view returns (uint256);
// Fetch single message
function getMessage(uint256 idx) external view returns (Message memory);
function getMessageForApp(
uint256 idx,
address app
) external view returns (Message memory);
function getMessageForAppUser(
uint256 idx,
address app,
address user
) external view returns (Message memory);
function getMessageForAppTopic(
uint256 idx,
address app,
string calldata topic
) external view returns (Message memory);
function getMessageForAppUserTopic(
uint256 idx,
address app,
address user,
string calldata topic
) external view returns (Message memory);
// Fetch multiple messages
function getMessagesInRange(
uint256 startIdx,
uint256 endIdx
) external view returns (Message[] memory);
function getMessagesInRangeForApp(
uint256 startIdx,
uint256 endIdx,
address app
) external view returns (Message[] memory);
function getMessagesInRangeForAppUser(
uint256 startIdx,
uint256 endIdx,
address app,
address user
) external view returns (Message[] memory);
function getMessagesInRangeForAppTopic(
uint256 startIdx,
uint256 endIdx,
address app,
string calldata topic
) external view returns (Message[] memory);
function getMessagesInRangeForAppUserTopic(
uint256 startIdx,
uint256 endIdx,
address app,
address user,
string calldata topic
) external view returns (Message[] memory);
// **************
// Message counts
// **************
function getTotalMessagesCount() external view returns (uint256);
function getTotalMessagesForAppCount(
address app
) external view returns (uint256);
function getTotalMessagesForAppUserCount(
address app,
address user
) external view returns (uint256);
function getTotalMessagesForAppTopicCount(
address app,
string calldata topic
) external view returns (uint256);
function getTotalMessagesForAppUserTopicCount(
address app,
address user,
string calldata topic
) external view returns (uint256);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.8.17 .0;
import {EventsAndErrors} from "./EventsAndErrors.sol";
import {INet} from "./INet.sol";
import {SSTORE2} from "@solady/utils/SSTORE2.sol";
/// @title Net
/// @author Aspyn Palatnick (aspyn.eth, stuckinaboot.eth)
/// @notice Fully decentralized onchain messaging protocol
contract Net is INet, EventsAndErrors {
// Use a single global mapping to map hashes to message indexes
mapping(bytes32 hashVal => uint256[] messageIndexes)
public hashToMessageIndexes;
address[] public messagePointers;
bytes32 constant ZERO_HASH = keccak256(abi.encodePacked(address(0)));
// Empty topic "" will not impact a hash, which could result in collisions
// between hash values that use topic and don't use topic. For that reason,
// we prefix the relevant hash topic keys with these values to ensure collisions don't occur
// Example if this prefix didn't exist:
// keccak256(abi.encodePacked(address(0))) == keccak256(abi.encodePacked(address(0), "" /* where "" represents topic */)) evaluates to true
uint256 constant APP_TOPIC_HASH_PREFIX = 1;
uint256 constant APP_USER_TOPIC_HASH_PREFIX = 2;
// ************
// Send message
// ************
/// @notice Send message via app
/// @param sender message sender
/// @param text message text
/// @param topic message topic
/// @param data message data
function sendMessageViaApp(
address sender,
string calldata text,
string calldata topic,
bytes calldata data
) external {
// Revert if message length is none to prevent empty messages
if (bytes(text).length == 0 && bytes(data).length == 0) {
revert MsgEmpty();
}
// Track message index in topic and user mappings
uint256 messagesLength = messagePointers.length;
// App messages
hashToMessageIndexes[keccak256(abi.encodePacked(msg.sender))].push(
messagesLength
);
// App-user messages
hashToMessageIndexes[keccak256(abi.encodePacked(msg.sender, sender))]
.push(messagesLength);
// App-topic messages
hashToMessageIndexes[
// msg.sender is the app id
keccak256(
abi.encodePacked(APP_TOPIC_HASH_PREFIX, msg.sender, topic)
)
].push(messagesLength);
// App-user-topic messages
hashToMessageIndexes[
keccak256(
abi.encodePacked(
APP_USER_TOPIC_HASH_PREFIX,
msg.sender,
sender,
topic
)
)
].push(messagesLength);
// Emit message sent using current messages length as the index
emit MessageSentViaApp(msg.sender, sender, topic, messagesLength);
// Store message
messagePointers.push(
SSTORE2.write(
abi.encode(
// App
msg.sender,
// Sender
sender,
// Timestamp
block.timestamp,
// Data
data,
// Text
text,
// Topic
topic
)
)
);
}
/// @notice Send message
/// @param text message text
/// @param topic message topic
/// @param data message data
function sendMessage(
string calldata text,
string calldata topic,
bytes calldata data
) external {
// Revert if message length is none to prevent empty messages
if (bytes(text).length == 0 && bytes(data).length == 0) {
revert MsgEmpty();
}
// Track message index in topic and user mappings
uint256 messagesLength = messagePointers.length;
// address(0) is used to represent messages sent from "no app"
hashToMessageIndexes[ZERO_HASH].push(messagesLength);
hashToMessageIndexes[
keccak256(
abi.encodePacked(APP_TOPIC_HASH_PREFIX, address(0), topic)
)
].push(messagesLength);
hashToMessageIndexes[
keccak256(abi.encodePacked(address(0), msg.sender))
].push(messagesLength);
hashToMessageIndexes[
keccak256(
abi.encodePacked(
APP_USER_TOPIC_HASH_PREFIX,
address(0),
msg.sender,
topic
)
)
].push(messagesLength);
// Emit message sent using current messages length as the index
emit MessageSent(msg.sender, topic, messagesLength);
// Store message
messagePointers.push(
SSTORE2.write(
abi.encode(
// App
address(0),
// Sender
msg.sender,
// Timestamp
block.timestamp,
// Data
data,
// Text
text,
// Topic
topic
)
)
);
}
// **************
// Fetch Messages
// **************
// Fetch message indexes
/// @notice Get message pointer index for app
/// @param idx message index
/// @param app app
/// @return index index
function getMessageIdxForApp(
uint256 idx,
address app
) external view returns (uint256) {
return hashToMessageIndexes[keccak256(abi.encodePacked(app))][idx];
}
/// @notice Get message pointer index for app user
/// @param idx message index
/// @param app app
/// @param user user
/// @return index index
function getMessageIdxForAppUser(
uint256 idx,
address app,
address user
) external view returns (uint256) {
return
hashToMessageIndexes[keccak256(abi.encodePacked(app, user))][idx];
}
/// @notice Get message pointer index for app topic
/// @param idx message index
/// @param app app
/// @param topic topic
/// @return index index
function getMessageIdxForAppTopic(
uint256 idx,
address app,
string calldata topic
) external view returns (uint256) {
return
hashToMessageIndexes[
keccak256(abi.encodePacked(APP_TOPIC_HASH_PREFIX, app, topic))
][idx];
}
/// @notice Get message pointer index for app user topic
/// @param idx message index
/// @param app app
/// @param user user
/// @param topic topic
/// @return index index
function getMessageIdxForAppUserTopic(
uint256 idx,
address app,
address user,
string calldata topic
) external view returns (uint256) {
return
hashToMessageIndexes[
keccak256(
abi.encodePacked(
APP_USER_TOPIC_HASH_PREFIX,
app,
user,
topic
)
)
][idx];
}
// Fetch single message
/// @notice Decode encoded message
/// @param encodedMessage encoded message
/// @return decodedMessage decoded message
function decodeMessage(
bytes memory encodedMessage
) public pure returns (Message memory) {
Message memory message;
(
message.app,
message.sender,
message.timestamp,
message.data,
message.text,
message.topic
) = abi.decode(
encodedMessage,
(
// App
address,
// Sender
address,
// Timestamp
uint256,
// Data
bytes,
// Text
string,
// Topic
string
)
);
return message;
}
/// @notice Decode message at index in message pointers
/// @param idx index
/// @return decodedMessage decoded message
function decodeMessageAtIndex(
uint256 idx
) public view returns (Message memory) {
return decodeMessage(SSTORE2.read(messagePointers[idx]));
}
/// @notice Get message
/// @param idx index
/// @return message message
function getMessage(uint256 idx) external view returns (Message memory) {
return decodeMessageAtIndex(idx);
}
/// @notice Get message for app
/// @param idx index
/// @param app app
/// @return message message
function getMessageForApp(
uint256 idx,
address app
) external view returns (Message memory) {
return
decodeMessageAtIndex(
hashToMessageIndexes[keccak256(abi.encodePacked(app))][idx]
);
}
/// @notice Get message for app user
/// @param idx index
/// @param app app
/// @param user user
/// @return message message
function getMessageForAppUser(
uint256 idx,
address app,
address user
) external view returns (Message memory) {
return
decodeMessageAtIndex(
hashToMessageIndexes[keccak256(abi.encodePacked(app, user))][
idx
]
);
}
/// @notice Get message for app topic
/// @param idx index
/// @param app app
/// @param topic topic
/// @return message message
function getMessageForAppTopic(
uint256 idx,
address app,
string calldata topic
) external view returns (Message memory) {
return
decodeMessageAtIndex(
hashToMessageIndexes[
keccak256(
abi.encodePacked(APP_TOPIC_HASH_PREFIX, app, topic)
)
][idx]
);
}
/// @notice Get message for app user topic
/// @param idx index
/// @param app app
/// @param user user
/// @param topic topic
/// @return message message
function getMessageForAppUserTopic(
uint256 idx,
address app,
address user,
string calldata topic
) external view returns (Message memory) {
return
decodeMessageAtIndex(
hashToMessageIndexes[
keccak256(
abi.encodePacked(
APP_USER_TOPIC_HASH_PREFIX,
app,
user,
topic
)
)
][idx]
);
}
// Fetch multiple messages
/// @notice Get messages in range
/// @param startIdx start index
/// @param endIdx end index
/// @return messages list of messages
function getMessagesInRange(
uint256 startIdx,
uint256 endIdx
) external view returns (Message[] memory) {
if (startIdx >= endIdx) {
revert InvalidRange();
}
uint256 querySetLength = messagePointers.length;
if (startIdx + 1 > querySetLength) {
revert InvalidStartIndex();
}
if (endIdx > querySetLength) {
revert InvalidEndIndex();
}
Message[] memory messagesSlice = new Message[](endIdx - startIdx);
uint256 idxInMessages = startIdx;
unchecked {
for (; idxInMessages < endIdx; ) {
messagesSlice[idxInMessages - startIdx] = decodeMessageAtIndex(
idxInMessages
);
++idxInMessages;
}
}
return messagesSlice;
}
/// @notice Get messages in range for hash
/// @param startIdx start index
/// @param endIdx end index
/// @param hashVal hash
/// @return messages list of messages
function getMessagesInRangeForHash(
uint256 startIdx,
uint256 endIdx,
bytes32 hashVal
) public view returns (Message[] memory) {
if (startIdx >= endIdx) {
revert InvalidRange();
}
uint256 querySetLength = hashToMessageIndexes[hashVal].length;
if (startIdx + 1 > querySetLength) {
revert InvalidStartIndex();
}
if (endIdx > querySetLength) {
revert InvalidEndIndex();
}
Message[] memory messagesSlice = new Message[](endIdx - startIdx);
uint256 idxInMessages = startIdx;
unchecked {
for (; idxInMessages < endIdx; ) {
messagesSlice[idxInMessages - startIdx] = decodeMessageAtIndex(
hashToMessageIndexes[hashVal][idxInMessages]
);
++idxInMessages;
}
}
return messagesSlice;
}
/// @notice Get messages in range for app
/// @param startIdx start index
/// @param endIdx end index
/// @param app app
/// @return messages list of messages
function getMessagesInRangeForApp(
uint256 startIdx,
uint256 endIdx,
address app
) external view returns (Message[] memory) {
return
getMessagesInRangeForHash(
startIdx,
endIdx,
keccak256(abi.encodePacked(app))
);
}
/// @notice Get messages in range for app user
/// @param startIdx start index
/// @param endIdx end index
/// @param app app
/// @param user user
/// @return messages list of messages
function getMessagesInRangeForAppUser(
uint256 startIdx,
uint256 endIdx,
address app,
address user
) external view returns (Message[] memory) {
return
getMessagesInRangeForHash(
startIdx,
endIdx,
keccak256(abi.encodePacked(app, user))
);
}
/// @notice Get messages in range for app topic
/// @param startIdx start index
/// @param endIdx end index
/// @param app app
/// @param topic topic
/// @return messages list of messages
function getMessagesInRangeForAppTopic(
uint256 startIdx,
uint256 endIdx,
address app,
string calldata topic
) external view returns (Message[] memory) {
return
getMessagesInRangeForHash(
startIdx,
endIdx,
keccak256(abi.encodePacked(APP_TOPIC_HASH_PREFIX, app, topic))
);
}
/// @notice Get messages in range for app user topic
/// @param startIdx start index
/// @param endIdx end index
/// @param app app
/// @param user user
/// @param topic topic
/// @return messages list of messages
function getMessagesInRangeForAppUserTopic(
uint256 startIdx,
uint256 endIdx,
address app,
address user,
string calldata topic
) external view returns (Message[] memory) {
return
getMessagesInRangeForHash(
startIdx,
endIdx,
keccak256(
abi.encodePacked(
APP_USER_TOPIC_HASH_PREFIX,
app,
user,
topic
)
)
);
}
// **************
// Message counts
// **************
/// @notice Get total messages count
/// @return count count
function getTotalMessagesCount() external view returns (uint256) {
return messagePointers.length;
}
/// @notice Get total messages for hash count
/// @param hashVal hash
/// @return count count
function getTotalMessagesForHashCount(
bytes32 hashVal
) public view returns (uint256) {
return hashToMessageIndexes[hashVal].length;
}
/// @notice Get total messages for app count
/// @param app app
/// @return count count
function getTotalMessagesForAppCount(
address app
) external view returns (uint256) {
return getTotalMessagesForHashCount(keccak256(abi.encodePacked(app)));
}
/// @notice Get total messages for app user count
/// @param app app
/// @param user user
/// @return count count
function getTotalMessagesForAppUserCount(
address app,
address user
) external view returns (uint256) {
return
getTotalMessagesForHashCount(
keccak256(abi.encodePacked(app, user))
);
}
/// @notice Get total messages for app topic count
/// @param app app
/// @param topic topic
/// @return count count
function getTotalMessagesForAppTopicCount(
address app,
string calldata topic
) external view returns (uint256) {
return
getTotalMessagesForHashCount(
keccak256(abi.encodePacked(APP_TOPIC_HASH_PREFIX, app, topic))
);
}
/// @notice Get total messages for app user topic count
/// @param app app
/// @param user user
/// @param topic topic
/// @return count count
function getTotalMessagesForAppUserTopicCount(
address app,
address user,
string calldata topic
) external view returns (uint256) {
return
getTotalMessagesForHashCount(
keccak256(
abi.encodePacked(
APP_USER_TOPIC_HASH_PREFIX,
app,
user,
topic
)
)
);
}
}{
"evmVersion": "paris",
"libraries": {},
"metadata": {
"appendCBOR": false,
"bytecodeHash": "none",
"useLiteralContent": false
},
"optimizer": {
"enabled": true,
"runs": 20
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"remappings": [
"@prb/test/=lib/prb-test/src/",
"forge-std/=lib/forge-std/src/",
"src/=src/",
"@erc721a/=lib/ERC721A/contracts/",
"@openzeppelin/=lib/openzeppelin-contracts/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
"@solady/=lib/solady/src/",
"solmate/=lib/solady/lib/solmate/src/",
"utility-contracts/=lib/utility-contracts/src/",
"@seaport-types/=lib/seaport-types/src/",
"@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
"ERC721A/=lib/ERC721A/contracts/",
"ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"prb-math/=lib/prb-math/src/",
"prb-test/=lib/prb-test/src/",
"seaport-types/=lib/seaport-types/src/",
"solady/=lib/solady/src/"
],
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"key","type":"bytes32"},{"indexed":true,"internalType":"address","name":"operator","type":"address"}],"name":"Stored","type":"event"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"}],"internalType":"struct Storage.BulkGetParams[]","name":"params","type":"tuple[]"}],"name":"bulkGet","outputs":[{"components":[{"internalType":"string","name":"text","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct Storage.BulkGetResult[]","name":"results","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"}],"internalType":"struct Storage.BulkGetParams[]","name":"params","type":"tuple[]"}],"name":"bulkGetTotalWrites","outputs":[{"internalType":"uint256[]","name":"results","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"idx","type":"uint256"}],"internalType":"struct Storage.BulkGetValueAtIndexParams[]","name":"params","type":"tuple[]"}],"name":"bulkGetValueAtIndex","outputs":[{"components":[{"internalType":"string","name":"text","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct Storage.BulkGetResult[]","name":"results","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"string","name":"text","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"internalType":"struct Storage.BulkPutParams[]","name":"params","type":"tuple[]"}],"name":"bulkPut","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"}],"name":"get","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"}],"name":"getTotalWrites","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"address","name":"operator","type":"address"},{"internalType":"uint256","name":"idx","type":"uint256"}],"name":"getValueAtIndex","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"key","type":"bytes32"},{"internalType":"string","name":"text","type":"string"},{"internalType":"bytes","name":"value","type":"bytes"}],"name":"put","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
6080604052600080546001600160a01b0319166fb24d62781db359b07880a105cd0b64e617905534801561003257600080fd5b50610f5c806100426000396000f3fe608060405234801561001057600080fd5b50600436106100785760003560e01c80630b768bbf1461007d57806320c027b8146100a657806347a21327146100c75780639456185a146100e8578063a71d51c814610108578063b13dcd481461011b578063f372437714610130578063f9ed11d914610143575b600080fd5b61009061008b366004610834565b610156565b60405161009d91906108f8565b60405180910390f35b6100b96100b4366004610995565b61024b565b60405161009d9291906109c5565b6100da6100d5366004610995565b610381565b60405190815260200161009d565b6100fb6100f6366004610834565b610419565b60405161009d91906109f3565b610090610116366004610a37565b6104d9565b61012e610129366004610a99565b6105e8565b005b6100b961013e366004610afb565b61068c565b61012e610151366004610b74565b610755565b6060816001600160401b0381111561017057610170610bed565b6040519080825280602002602001820160405280156101a957816020015b61019661081a565b81526020019060019003908161018e5790505b50905060005b8151811015610244576000806102048686858181106101d0576101d0610c03565b905060400201600001358787868181106101ec576101ec610c03565b90506040020160200160208101906100b49190610c19565b9150915060405180604001604052808381526020018281525084848151811061022f5761022f610c03565b602090810291909101015250506001016101af565b5092915050565b60608060008460405160200161026391815260200190565b60408051601f19818403018152908290526000805463e976718d60e01b8452919350916001600160a01b039091169063176b710c90600190839063e976718d906102b59030908c908a90600401610c3d565b602060405180830381865afa1580156102d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f69190610c69565b6103009190610c82565b3088866040518563ffffffff1660e01b81526004016103229493929190610ca3565b600060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103679190810190610d94565b9050806080015181606001519350935050505b9250929050565b60008054604080516020808201879052825180830390910181528183019283905263e976718d60e01b9092526001600160a01b039092169163e976718d916103cf9130918791604401610c3d565b602060405180830381865afa1580156103ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104109190610c69565b90505b92915050565b6060816001600160401b0381111561043357610433610bed565b60405190808252806020026020018201604052801561045c578160200160208202803683370190505b50905060005b8151811015610244576104b484848381811061048057610480610c03565b9050604002016000013585858481811061049c5761049c610c03565b90506040020160200160208101906100d59190610c19565b8282815181106104c6576104c6610c03565b6020908102919091010152600101610462565b6060816001600160401b038111156104f3576104f3610bed565b60405190808252806020026020018201604052801561052c57816020015b61051961081a565b8152602001906001900390816105115790505b50905060005b8151811015610244576000806105a886868581811061055357610553610c03565b9050606002016000013587878681811061056f5761056f610c03565b90506060020160200160208101906105879190610c19565b88888781811061059957610599610c03565b9050606002016040013561068c565b915091506040518060400160405280838152602001828152508484815181106105d3576105d3610c03565b60209081029190910101525050600101610532565b60005b818110156106875761067f83838381811061060857610608610c03565b905060200281019061061a9190610e74565b3584848481811061062d5761062d610c03565b905060200281019061063f9190610e74565b61064d906020810190610e94565b86868681811061065f5761065f610c03565b90506020028101906106719190610e74565b610151906040810190610e94565b6001016105eb565b505050565b60608060008060009054906101000a90046001600160a01b03166001600160a01b031663176b710c8530888a6040516020016106ca91815260200190565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016106f89493929190610ca3565b600060405180830381865afa158015610715573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261073d9190810190610d94565b60808101516060909101519097909650945050505050565b60008560405160200161076a91815260200190565b60408051601f19818403018152908290526000546308521f2760e21b83529092506001600160a01b0316906321487c9c906107b39033908990899087908a908a90600401610f03565b600060405180830381600087803b1580156107cd57600080fd5b505af11580156107e1573d6000803e3d6000fd5b50506040513392508891507f5c07bbc009a8b5cd591fb836e410b19010c5600d44b836b4d44ab5be178bba3d90600090a3505050505050565b604051806040016040528060608152602001606081525090565b6000806020838503121561084757600080fd5b82356001600160401b038082111561085e57600080fd5b818501915085601f83011261087257600080fd5b81358181111561088157600080fd5b8660208260061b850101111561089657600080fd5b60209290920196919550909350505050565b60005b838110156108c35781810151838201526020016108ab565b50506000910152565b600081518084526108e48160208601602086016108a8565b601f01601f19169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561096f57888303603f1901855281518051878552610943888601826108cc565b91890151858303868b015291905061095b81836108cc565b96890196945050509086019060010161091f565b509098975050505050505050565b6001600160a01b038116811461099257600080fd5b50565b600080604083850312156109a857600080fd5b8235915060208301356109ba8161097d565b809150509250929050565b6040815260006109d860408301856108cc565b82810360208401526109ea81856108cc565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015610a2b57835183529284019291840191600101610a0f565b50909695505050505050565b60008060208385031215610a4a57600080fd5b82356001600160401b0380821115610a6157600080fd5b818501915085601f830112610a7557600080fd5b813581811115610a8457600080fd5b86602060608302850101111561089657600080fd5b60008060208385031215610aac57600080fd5b82356001600160401b0380821115610ac357600080fd5b818501915085601f830112610ad757600080fd5b813581811115610ae657600080fd5b8660208260051b850101111561089657600080fd5b600080600060608486031215610b1057600080fd5b833592506020840135610b228161097d565b929592945050506040919091013590565b60008083601f840112610b4557600080fd5b5081356001600160401b03811115610b5c57600080fd5b60208301915083602082850101111561037a57600080fd5b600080600080600060608688031215610b8c57600080fd5b8535945060208601356001600160401b0380821115610baa57600080fd5b610bb689838a01610b33565b90965094506040880135915080821115610bcf57600080fd5b50610bdc88828901610b33565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610c2b57600080fd5b8135610c368161097d565b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906109ea908301846108cc565b600060208284031215610c7b57600080fd5b5051919050565b8181038181111561041357634e487b7160e01b600052601160045260246000fd5b8481526001600160a01b03848116602083015283166040820152608060608201819052600090610cd5908301846108cc565b9695505050505050565b60405160c081016001600160401b0381118282101715610d0157610d01610bed565b60405290565b8051610d128161097d565b919050565b600082601f830112610d2857600080fd5b81516001600160401b0380821115610d4257610d42610bed565b604051601f8301601f19908116603f01168101908282118183101715610d6a57610d6a610bed565b81604052838152866020858801011115610d8357600080fd5b610cd58460208301602089016108a8565b600060208284031215610da657600080fd5b81516001600160401b0380821115610dbd57600080fd5b9083019060c08286031215610dd157600080fd5b610dd9610cdf565b610de283610d07565b8152610df060208401610d07565b602082015260408301516040820152606083015182811115610e1157600080fd5b610e1d87828601610d17565b606083015250608083015182811115610e3557600080fd5b610e4187828601610d17565b60808301525060a083015182811115610e5957600080fd5b610e6587828601610d17565b60a08301525095945050505050565b60008235605e19833603018112610e8a57600080fd5b9190910192915050565b6000808335601e19843603018112610eab57600080fd5b8301803591506001600160401b03821115610ec557600080fd5b60200191503681900382131561037a57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0387168152608060208201819052600090610f289083018789610eda565b8281036040840152610f3a81876108cc565b90508281036060840152610f4f818587610eda565b999850505050505050505056
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100785760003560e01c80630b768bbf1461007d57806320c027b8146100a657806347a21327146100c75780639456185a146100e8578063a71d51c814610108578063b13dcd481461011b578063f372437714610130578063f9ed11d914610143575b600080fd5b61009061008b366004610834565b610156565b60405161009d91906108f8565b60405180910390f35b6100b96100b4366004610995565b61024b565b60405161009d9291906109c5565b6100da6100d5366004610995565b610381565b60405190815260200161009d565b6100fb6100f6366004610834565b610419565b60405161009d91906109f3565b610090610116366004610a37565b6104d9565b61012e610129366004610a99565b6105e8565b005b6100b961013e366004610afb565b61068c565b61012e610151366004610b74565b610755565b6060816001600160401b0381111561017057610170610bed565b6040519080825280602002602001820160405280156101a957816020015b61019661081a565b81526020019060019003908161018e5790505b50905060005b8151811015610244576000806102048686858181106101d0576101d0610c03565b905060400201600001358787868181106101ec576101ec610c03565b90506040020160200160208101906100b49190610c19565b9150915060405180604001604052808381526020018281525084848151811061022f5761022f610c03565b602090810291909101015250506001016101af565b5092915050565b60608060008460405160200161026391815260200190565b60408051601f19818403018152908290526000805463e976718d60e01b8452919350916001600160a01b039091169063176b710c90600190839063e976718d906102b59030908c908a90600401610c3d565b602060405180830381865afa1580156102d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f69190610c69565b6103009190610c82565b3088866040518563ffffffff1660e01b81526004016103229493929190610ca3565b600060405180830381865afa15801561033f573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526103679190810190610d94565b9050806080015181606001519350935050505b9250929050565b60008054604080516020808201879052825180830390910181528183019283905263e976718d60e01b9092526001600160a01b039092169163e976718d916103cf9130918791604401610c3d565b602060405180830381865afa1580156103ec573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104109190610c69565b90505b92915050565b6060816001600160401b0381111561043357610433610bed565b60405190808252806020026020018201604052801561045c578160200160208202803683370190505b50905060005b8151811015610244576104b484848381811061048057610480610c03565b9050604002016000013585858481811061049c5761049c610c03565b90506040020160200160208101906100d59190610c19565b8282815181106104c6576104c6610c03565b6020908102919091010152600101610462565b6060816001600160401b038111156104f3576104f3610bed565b60405190808252806020026020018201604052801561052c57816020015b61051961081a565b8152602001906001900390816105115790505b50905060005b8151811015610244576000806105a886868581811061055357610553610c03565b9050606002016000013587878681811061056f5761056f610c03565b90506060020160200160208101906105879190610c19565b88888781811061059957610599610c03565b9050606002016040013561068c565b915091506040518060400160405280838152602001828152508484815181106105d3576105d3610c03565b60209081029190910101525050600101610532565b60005b818110156106875761067f83838381811061060857610608610c03565b905060200281019061061a9190610e74565b3584848481811061062d5761062d610c03565b905060200281019061063f9190610e74565b61064d906020810190610e94565b86868681811061065f5761065f610c03565b90506020028101906106719190610e74565b610151906040810190610e94565b6001016105eb565b505050565b60608060008060009054906101000a90046001600160a01b03166001600160a01b031663176b710c8530888a6040516020016106ca91815260200190565b6040516020818303038152906040526040518563ffffffff1660e01b81526004016106f89493929190610ca3565b600060405180830381865afa158015610715573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405261073d9190810190610d94565b60808101516060909101519097909650945050505050565b60008560405160200161076a91815260200190565b60408051601f19818403018152908290526000546308521f2760e21b83529092506001600160a01b0316906321487c9c906107b39033908990899087908a908a90600401610f03565b600060405180830381600087803b1580156107cd57600080fd5b505af11580156107e1573d6000803e3d6000fd5b50506040513392508891507f5c07bbc009a8b5cd591fb836e410b19010c5600d44b836b4d44ab5be178bba3d90600090a3505050505050565b604051806040016040528060608152602001606081525090565b6000806020838503121561084757600080fd5b82356001600160401b038082111561085e57600080fd5b818501915085601f83011261087257600080fd5b81358181111561088157600080fd5b8660208260061b850101111561089657600080fd5b60209290920196919550909350505050565b60005b838110156108c35781810151838201526020016108ab565b50506000910152565b600081518084526108e48160208601602086016108a8565b601f01601f19169290920160200192915050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b8381101561096f57888303603f1901855281518051878552610943888601826108cc565b91890151858303868b015291905061095b81836108cc565b96890196945050509086019060010161091f565b509098975050505050505050565b6001600160a01b038116811461099257600080fd5b50565b600080604083850312156109a857600080fd5b8235915060208301356109ba8161097d565b809150509250929050565b6040815260006109d860408301856108cc565b82810360208401526109ea81856108cc565b95945050505050565b6020808252825182820181905260009190848201906040850190845b81811015610a2b57835183529284019291840191600101610a0f565b50909695505050505050565b60008060208385031215610a4a57600080fd5b82356001600160401b0380821115610a6157600080fd5b818501915085601f830112610a7557600080fd5b813581811115610a8457600080fd5b86602060608302850101111561089657600080fd5b60008060208385031215610aac57600080fd5b82356001600160401b0380821115610ac357600080fd5b818501915085601f830112610ad757600080fd5b813581811115610ae657600080fd5b8660208260051b850101111561089657600080fd5b600080600060608486031215610b1057600080fd5b833592506020840135610b228161097d565b929592945050506040919091013590565b60008083601f840112610b4557600080fd5b5081356001600160401b03811115610b5c57600080fd5b60208301915083602082850101111561037a57600080fd5b600080600080600060608688031215610b8c57600080fd5b8535945060208601356001600160401b0380821115610baa57600080fd5b610bb689838a01610b33565b90965094506040880135915080821115610bcf57600080fd5b50610bdc88828901610b33565b969995985093965092949392505050565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b600060208284031215610c2b57600080fd5b8135610c368161097d565b9392505050565b6001600160a01b038481168252831660208201526060604082018190526000906109ea908301846108cc565b600060208284031215610c7b57600080fd5b5051919050565b8181038181111561041357634e487b7160e01b600052601160045260246000fd5b8481526001600160a01b03848116602083015283166040820152608060608201819052600090610cd5908301846108cc565b9695505050505050565b60405160c081016001600160401b0381118282101715610d0157610d01610bed565b60405290565b8051610d128161097d565b919050565b600082601f830112610d2857600080fd5b81516001600160401b0380821115610d4257610d42610bed565b604051601f8301601f19908116603f01168101908282118183101715610d6a57610d6a610bed565b81604052838152866020858801011115610d8357600080fd5b610cd58460208301602089016108a8565b600060208284031215610da657600080fd5b81516001600160401b0380821115610dbd57600080fd5b9083019060c08286031215610dd157600080fd5b610dd9610cdf565b610de283610d07565b8152610df060208401610d07565b602082015260408301516040820152606083015182811115610e1157600080fd5b610e1d87828601610d17565b606083015250608083015182811115610e3557600080fd5b610e4187828601610d17565b60808301525060a083015182811115610e5957600080fd5b610e6587828601610d17565b60a08301525095945050505050565b60008235605e19833603018112610e8a57600080fd5b9190910192915050565b6000808335601e19843603018112610eab57600080fd5b8301803591506001600160401b03821115610ec557600080fd5b60200191503681900382131561037a57600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b0387168152608060208201819052600090610f289083018789610eda565b8281036040840152610f3a81876108cc565b90508281036060840152610f4f818587610eda565b999850505050505050505056
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in HYPE
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ 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.