Overview
ETH Balance
0 ETH
Eth Value
$0.00More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
Value | ||||
---|---|---|---|---|---|---|---|---|---|
0x60f26100 | 16436743 | 530 days ago | IN | Create: Message | 0 ETH | 0.00298092 |
Loading...
Loading
Contract Name:
Message
Compiler Version
v0.7.6+commit.7338295f
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2023-02-17 */ /* * Copyright (c) 2022, Circle Internet Financial Limited. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ pragma solidity 0.7.6; /* The MIT License (MIT) Copyright (c) 2016 Smart Contract Solutions, Inc. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) { // Gas optimization: this is cheaper than asserting 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (_a == 0) { return 0; } c = _a * _b; require(c / _a == _b, "Overflow during multiplication."); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ function div(uint256 _a, uint256 _b) internal pure returns (uint256) { // assert(_b > 0); // Solidity automatically throws when dividing by 0 // uint256 c = _a / _b; // assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold return _a / _b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 _a, uint256 _b) internal pure returns (uint256) { require(_b <= _a, "Underflow during subtraction."); return _a - _b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) { c = _a + _b; require(c >= _a, "Overflow during addition."); return c; } } library TypedMemView { using SafeMath for uint256; // Why does this exist? // the solidity `bytes memory` type has a few weaknesses. // 1. You can't index ranges effectively // 2. You can't slice without copying // 3. The underlying data may represent any type // 4. Solidity never deallocates memory, and memory costs grow // superlinearly // By using a memory view instead of a `bytes memory` we get the following // advantages: // 1. Slices are done on the stack, by manipulating the pointer // 2. We can index arbitrary ranges and quickly convert them to stack types // 3. We can insert type info into the pointer, and typecheck at runtime // This makes `TypedMemView` a useful tool for efficient zero-copy // algorithms. // Why bytes29? // We want to avoid confusion between views, digests, and other common // types so we chose a large and uncommonly used odd number of bytes // // Note that while bytes are left-aligned in a word, integers and addresses // are right-aligned. This means when working in assembly we have to // account for the 3 unused bytes on the righthand side // // First 5 bytes are a type flag. // - ff_ffff_fffe is reserved for unknown type. // - ff_ffff_ffff is reserved for invalid types/errors. // next 12 are memory address // next 12 are len // bottom 3 bytes are empty // Assumptions: // - non-modification of memory. // - No Solidity updates // - - wrt free mem point // - - wrt bytes representation in memory // - - wrt memory addressing in general // Usage: // - create type constants // - use `assertType` for runtime type assertions // - - unfortunately we can't do this at compile time yet :( // - recommended: implement modifiers that perform type checking // - - e.g. // - - `uint40 constant MY_TYPE = 3;` // - - ` modifer onlyMyType(bytes29 myView) { myView.assertType(MY_TYPE); }` // - instantiate a typed view from a bytearray using `ref` // - use `index` to inspect the contents of the view // - use `slice` to create smaller views into the same memory // - - `slice` can increase the offset // - - `slice can decrease the length` // - - must specify the output type of `slice` // - - `slice` will return a null view if you try to overrun // - - make sure to explicitly check for this with `notNull` or `assertType` // - use `equal` for typed comparisons. // The null view bytes29 public constant NULL = hex"ffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"; uint256 constant LOW_12_MASK = 0xffffffffffffffffffffffff; uint8 constant TWELVE_BYTES = 96; /** * @notice Returns the encoded hex character that represents the lower 4 bits of the argument. * @param _b The byte * @return char - The encoded hex character */ function nibbleHex(uint8 _b) internal pure returns (uint8 char) { // This can probably be done more efficiently, but it's only in error // paths, so we don't really care :) uint8 _nibble = _b | 0xf0; // set top 4, keep bottom 4 if (_nibble == 0xf0) {return 0x30;} // 0 if (_nibble == 0xf1) {return 0x31;} // 1 if (_nibble == 0xf2) {return 0x32;} // 2 if (_nibble == 0xf3) {return 0x33;} // 3 if (_nibble == 0xf4) {return 0x34;} // 4 if (_nibble == 0xf5) {return 0x35;} // 5 if (_nibble == 0xf6) {return 0x36;} // 6 if (_nibble == 0xf7) {return 0x37;} // 7 if (_nibble == 0xf8) {return 0x38;} // 8 if (_nibble == 0xf9) {return 0x39;} // 9 if (_nibble == 0xfa) {return 0x61;} // a if (_nibble == 0xfb) {return 0x62;} // b if (_nibble == 0xfc) {return 0x63;} // c if (_nibble == 0xfd) {return 0x64;} // d if (_nibble == 0xfe) {return 0x65;} // e if (_nibble == 0xff) {return 0x66;} // f } /** * @notice Returns a uint16 containing the hex-encoded byte. * @param _b The byte * @return encoded - The hex-encoded byte */ function byteHex(uint8 _b) internal pure returns (uint16 encoded) { encoded |= nibbleHex(_b >> 4); // top 4 bits encoded <<= 8; encoded |= nibbleHex(_b); // lower 4 bits } /** * @notice Encodes the uint256 to hex. `first` contains the encoded top 16 bytes. * `second` contains the encoded lower 16 bytes. * * @param _b The 32 bytes as uint256 * @return first - The top 16 bytes * @return second - The bottom 16 bytes */ function encodeHex(uint256 _b) internal pure returns (uint256 first, uint256 second) { for (uint8 i = 31; i > 15; i -= 1) { uint8 _byte = uint8(_b >> (i * 8)); first |= byteHex(_byte); if (i != 16) { first <<= 16; } } // abusing underflow here =_= for (uint8 i = 15; i < 255 ; i -= 1) { uint8 _byte = uint8(_b >> (i * 8)); second |= byteHex(_byte); if (i != 0) { second <<= 16; } } } /** * @notice Changes the endianness of a uint256. * @dev https://graphics.stanford.edu/~seander/bithacks.html#ReverseParallel * @param _b The unsigned integer to reverse * @return v - The reversed value */ function reverseUint256(uint256 _b) internal pure returns (uint256 v) { v = _b; // swap bytes v = ((v >> 8) & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) | ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8); // swap 2-byte long pairs v = ((v >> 16) & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) | ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16); // swap 4-byte long pairs v = ((v >> 32) & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) | ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32); // swap 8-byte long pairs v = ((v >> 64) & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) | ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64); // swap 16-byte long pairs v = (v >> 128) | (v << 128); } /** * @notice Create a mask with the highest `_len` bits set. * @param _len The length * @return mask - The mask */ function leftMask(uint8 _len) private pure returns (uint256 mask) { // ugly. redo without assembly? assembly { // solium-disable-previous-line security/no-inline-assembly mask := sar( sub(_len, 1), 0x8000000000000000000000000000000000000000000000000000000000000000 ) } } /** * @notice Return the null view. * @return bytes29 - The null view */ function nullView() internal pure returns (bytes29) { return NULL; } /** * @notice Check if the view is null. * @return bool - True if the view is null */ function isNull(bytes29 memView) internal pure returns (bool) { return memView == NULL; } /** * @notice Check if the view is not null. * @return bool - True if the view is not null */ function notNull(bytes29 memView) internal pure returns (bool) { return !isNull(memView); } /** * @notice Check if the view is of a valid type and points to a valid location * in memory. * @dev We perform this check by examining solidity's unallocated memory * pointer and ensuring that the view's upper bound is less than that. * @param memView The view * @return ret - True if the view is valid */ function isValid(bytes29 memView) internal pure returns (bool ret) { if (typeOf(memView) == 0xffffffffff) {return false;} uint256 _end = end(memView); assembly { // solium-disable-previous-line security/no-inline-assembly ret := not(gt(_end, mload(0x40))) } } /** * @notice Require that a typed memory view be valid. * @dev Returns the view for easy chaining. * @param memView The view * @return bytes29 - The validated view */ function assertValid(bytes29 memView) internal pure returns (bytes29) { require(isValid(memView), "Validity assertion failed"); return memView; } /** * @notice Return true if the memview is of the expected type. Otherwise false. * @param memView The view * @param _expected The expected type * @return bool - True if the memview is of the expected type */ function isType(bytes29 memView, uint40 _expected) internal pure returns (bool) { return typeOf(memView) == _expected; } /** * @notice Require that a typed memory view has a specific type. * @dev Returns the view for easy chaining. * @param memView The view * @param _expected The expected type * @return bytes29 - The view with validated type */ function assertType(bytes29 memView, uint40 _expected) internal pure returns (bytes29) { if (!isType(memView, _expected)) { (, uint256 g) = encodeHex(uint256(typeOf(memView))); (, uint256 e) = encodeHex(uint256(_expected)); string memory err = string( abi.encodePacked( "Type assertion failed. Got 0x", uint80(g), ". Expected 0x", uint80(e) ) ); revert(err); } return memView; } /** * @notice Return an identical view with a different type. * @param memView The view * @param _newType The new type * @return newView - The new view with the specified type */ function castTo(bytes29 memView, uint40 _newType) internal pure returns (bytes29 newView) { // then | in the new type assembly { // solium-disable-previous-line security/no-inline-assembly // shift off the top 5 bytes newView := or(newView, shr(40, shl(40, memView))) newView := or(newView, shl(216, _newType)) } } /** * @notice Unsafe raw pointer construction. This should generally not be called * directly. Prefer `ref` wherever possible. * @dev Unsafe raw pointer construction. This should generally not be called * directly. Prefer `ref` wherever possible. * @param _type The type * @param _loc The memory address * @param _len The length * @return newView - The new view with the specified type, location and length */ function unsafeBuildUnchecked(uint256 _type, uint256 _loc, uint256 _len) private pure returns (bytes29 newView) { assembly { // solium-disable-previous-line security/no-inline-assembly newView := shl(96, or(newView, _type)) // insert type newView := shl(96, or(newView, _loc)) // insert loc newView := shl(24, or(newView, _len)) // empty bottom 3 bytes } } /** * @notice Instantiate a new memory view. This should generally not be called * directly. Prefer `ref` wherever possible. * @dev Instantiate a new memory view. This should generally not be called * directly. Prefer `ref` wherever possible. * @param _type The type * @param _loc The memory address * @param _len The length * @return newView - The new view with the specified type, location and length */ function build(uint256 _type, uint256 _loc, uint256 _len) internal pure returns (bytes29 newView) { uint256 _end = _loc.add(_len); assembly { // solium-disable-previous-line security/no-inline-assembly if gt(_end, mload(0x40)) { _end := 0 } } if (_end == 0) { return NULL; } newView = unsafeBuildUnchecked(_type, _loc, _len); } /** * @notice Instantiate a memory view from a byte array. * @dev Note that due to Solidity memory representation, it is not possible to * implement a deref, as the `bytes` type stores its len in memory. * @param arr The byte array * @param newType The type * @return bytes29 - The memory view */ function ref(bytes memory arr, uint40 newType) internal pure returns (bytes29) { uint256 _len = arr.length; uint256 _loc; assembly { // solium-disable-previous-line security/no-inline-assembly _loc := add(arr, 0x20) // our view is of the data, not the struct } return build(newType, _loc, _len); } /** * @notice Return the associated type information. * @param memView The memory view * @return _type - The type associated with the view */ function typeOf(bytes29 memView) internal pure returns (uint40 _type) { assembly { // solium-disable-previous-line security/no-inline-assembly // 216 == 256 - 40 _type := shr(216, memView) // shift out lower 24 bytes } } /** * @notice Optimized type comparison. Checks that the 5-byte type flag is equal. * @param left The first view * @param right The second view * @return bool - True if the 5-byte type flag is equal */ function sameType(bytes29 left, bytes29 right) internal pure returns (bool) { return (left ^ right) >> (2 * TWELVE_BYTES) == 0; } /** * @notice Return the memory address of the underlying bytes. * @param memView The view * @return _loc - The memory address */ function loc(bytes29 memView) internal pure returns (uint96 _loc) { uint256 _mask = LOW_12_MASK; // assembly can't use globals assembly { // solium-disable-previous-line security/no-inline-assembly // 120 bits = 12 bytes (the encoded loc) + 3 bytes (empty low space) _loc := and(shr(120, memView), _mask) } } /** * @notice The number of memory words this memory view occupies, rounded up. * @param memView The view * @return uint256 - The number of memory words */ function words(bytes29 memView) internal pure returns (uint256) { return uint256(len(memView)).add(32) / 32; } /** * @notice The in-memory footprint of a fresh copy of the view. * @param memView The view * @return uint256 - The in-memory footprint of a fresh copy of the view. */ function footprint(bytes29 memView) internal pure returns (uint256) { return words(memView) * 32; } /** * @notice The number of bytes of the view. * @param memView The view * @return _len - The length of the view */ function len(bytes29 memView) internal pure returns (uint96 _len) { uint256 _mask = LOW_12_MASK; // assembly can't use globals assembly { // solium-disable-previous-line security/no-inline-assembly _len := and(shr(24, memView), _mask) } } /** * @notice Returns the endpoint of `memView`. * @param memView The view * @return uint256 - The endpoint of `memView` */ function end(bytes29 memView) internal pure returns (uint256) { return loc(memView) + len(memView); } /** * @notice Safe slicing without memory modification. * @param memView The view * @param _index The start index * @param _len The length * @param newType The new type * @return bytes29 - The new view */ function slice(bytes29 memView, uint256 _index, uint256 _len, uint40 newType) internal pure returns (bytes29) { uint256 _loc = loc(memView); // Ensure it doesn't overrun the view if (_loc.add(_index).add(_len) > end(memView)) { return NULL; } _loc = _loc.add(_index); return build(newType, _loc, _len); } /** * @notice Shortcut to `slice`. Gets a view representing the first `_len` bytes. * @param memView The view * @param _len The length * @param newType The new type * @return bytes29 - The new view */ function prefix(bytes29 memView, uint256 _len, uint40 newType) internal pure returns (bytes29) { return slice(memView, 0, _len, newType); } /** * @notice Shortcut to `slice`. Gets a view representing the last `_len` byte. * @param memView The view * @param _len The length * @param newType The new type * @return bytes29 - The new view */ function postfix(bytes29 memView, uint256 _len, uint40 newType) internal pure returns (bytes29) { return slice(memView, uint256(len(memView)).sub(_len), _len, newType); } /** * @notice Construct an error message for an indexing overrun. * @param _loc The memory address * @param _len The length * @param _index The index * @param _slice The slice where the overrun occurred * @return err - The err */ function indexErrOverrun( uint256 _loc, uint256 _len, uint256 _index, uint256 _slice ) internal pure returns (string memory err) { (, uint256 a) = encodeHex(_loc); (, uint256 b) = encodeHex(_len); (, uint256 c) = encodeHex(_index); (, uint256 d) = encodeHex(_slice); err = string( abi.encodePacked( "TypedMemView/index - Overran the view. Slice is at 0x", uint48(a), " with length 0x", uint48(b), ". Attempted to index at offset 0x", uint48(c), " with length 0x", uint48(d), "." ) ); } /** * @notice Load up to 32 bytes from the view onto the stack. * @dev Returns a bytes32 with only the `_bytes` highest bytes set. * This can be immediately cast to a smaller fixed-length byte array. * To automatically cast to an integer, use `indexUint`. * @param memView The view * @param _index The index * @param _bytes The bytes * @return result - The 32 byte result */ function index(bytes29 memView, uint256 _index, uint8 _bytes) internal pure returns (bytes32 result) { if (_bytes == 0) {return bytes32(0);} if (_index.add(_bytes) > len(memView)) { revert(indexErrOverrun(loc(memView), len(memView), _index, uint256(_bytes))); } require(_bytes <= 32, "TypedMemView/index - Attempted to index more than 32 bytes"); uint8 bitLength = _bytes * 8; uint256 _loc = loc(memView); uint256 _mask = leftMask(bitLength); assembly { // solium-disable-previous-line security/no-inline-assembly result := and(mload(add(_loc, _index)), _mask) } } /** * @notice Parse an unsigned integer from the view at `_index`. * @dev Requires that the view have >= `_bytes` bytes following that index. * @param memView The view * @param _index The index * @param _bytes The bytes * @return result - The unsigned integer */ function indexUint(bytes29 memView, uint256 _index, uint8 _bytes) internal pure returns (uint256 result) { return uint256(index(memView, _index, _bytes)) >> ((32 - _bytes) * 8); } /** * @notice Parse an unsigned integer from LE bytes. * @param memView The view * @param _index The index * @param _bytes The bytes * @return result - The unsigned integer */ function indexLEUint(bytes29 memView, uint256 _index, uint8 _bytes) internal pure returns (uint256 result) { return reverseUint256(uint256(index(memView, _index, _bytes))); } /** * @notice Parse an address from the view at `_index`. Requires that the view have >= 20 bytes * following that index. * @param memView The view * @param _index The index * @return address - The address */ function indexAddress(bytes29 memView, uint256 _index) internal pure returns (address) { return address(uint160(indexUint(memView, _index, 20))); } /** * @notice Return the keccak256 hash of the underlying memory * @param memView The view * @return digest - The keccak256 hash of the underlying memory */ function keccak(bytes29 memView) internal pure returns (bytes32 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly digest := keccak256(_loc, _len) } } /** * @notice Return the sha2 digest of the underlying memory. * @dev We explicitly deallocate memory afterwards. * @param memView The view * @return digest - The sha2 hash of the underlying memory */ function sha2(bytes29 memView) internal view returns (bytes32 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1 digest := mload(ptr) } } /** * @notice Implements bitcoin's hash160 (rmd160(sha2())) * @param memView The pre-image * @return digest - the Digest */ function hash160(bytes29 memView) internal view returns (bytes20 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 pop(staticcall(gas(), 3, ptr, 0x20, ptr, 0x20)) // rmd160 digest := mload(add(ptr, 0xc)) // return value is 0-prefixed. } } /** * @notice Implements bitcoin's hash256 (double sha2) * @param memView A view of the preimage * @return digest - the Digest */ function hash256(bytes29 memView) internal view returns (bytes32 digest) { uint256 _loc = loc(memView); uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) pop(staticcall(gas(), 2, _loc, _len, ptr, 0x20)) // sha2 #1 pop(staticcall(gas(), 2, ptr, 0x20, ptr, 0x20)) // sha2 #2 digest := mload(ptr) } } /** * @notice Return true if the underlying memory is equal. Else false. * @param left The first view * @param right The second view * @return bool - True if the underlying memory is equal */ function untypedEqual(bytes29 left, bytes29 right) internal pure returns (bool) { return (loc(left) == loc(right) && len(left) == len(right)) || keccak(left) == keccak(right); } /** * @notice Return false if the underlying memory is equal. Else true. * @param left The first view * @param right The second view * @return bool - False if the underlying memory is equal */ function untypedNotEqual(bytes29 left, bytes29 right) internal pure returns (bool) { return !untypedEqual(left, right); } /** * @notice Compares type equality. * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. * @param left The first view * @param right The second view * @return bool - True if the types are the same */ function equal(bytes29 left, bytes29 right) internal pure returns (bool) { return left == right || (typeOf(left) == typeOf(right) && keccak(left) == keccak(right)); } /** * @notice Compares type inequality. * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. * @param left The first view * @param right The second view * @return bool - True if the types are not the same */ function notEqual(bytes29 left, bytes29 right) internal pure returns (bool) { return !equal(left, right); } /** * @notice Copy the view to a location, return an unsafe memory reference * @dev Super Dangerous direct memory access. * * This reference can be overwritten if anything else modifies memory (!!!). * As such it MUST be consumed IMMEDIATELY. * This function is private to prevent unsafe usage by callers. * @param memView The view * @param _newLoc The new location * @return written - the unsafe memory reference */ function unsafeCopyTo(bytes29 memView, uint256 _newLoc) private view returns (bytes29 written) { require(notNull(memView), "TypedMemView/copyTo - Null pointer deref"); require(isValid(memView), "TypedMemView/copyTo - Invalid pointer deref"); uint256 _len = len(memView); uint256 _oldLoc = loc(memView); uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // revert if we're writing in occupied memory if gt(ptr, _newLoc) { revert(0x60, 0x20) // empty revert message } // use the identity precompile to copy // guaranteed not to fail, so pop the success pop(staticcall(gas(), 4, _oldLoc, _len, _newLoc, _len)) } written = unsafeBuildUnchecked(typeOf(memView), _newLoc, _len); } /** * @notice Copies the referenced memory to a new loc in memory, returning a `bytes` pointing to * the new memory * @dev Shortcuts if the pointers are identical, otherwise compares type and digest. * @param memView The view * @return ret - The view pointing to the new memory */ function clone(bytes29 memView) internal view returns (bytes memory ret) { uint256 ptr; uint256 _len = len(memView); assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer ret := ptr } unsafeCopyTo(memView, ptr + 0x20); assembly { // solium-disable-previous-line security/no-inline-assembly mstore(0x40, add(add(ptr, _len), 0x20)) // write new unused pointer mstore(ptr, _len) // write len of new array (in bytes) } } /** * @notice Join the views in memory, return an unsafe reference to the memory. * @dev Super Dangerous direct memory access. * * This reference can be overwritten if anything else modifies memory (!!!). * As such it MUST be consumed IMMEDIATELY. * This function is private to prevent unsafe usage by callers. * @param memViews The views * @return unsafeView - The conjoined view pointing to the new memory */ function unsafeJoin(bytes29[] memory memViews, uint256 _location) private view returns (bytes29 unsafeView) { assembly { // solium-disable-previous-line security/no-inline-assembly let ptr := mload(0x40) // revert if we're writing in occupied memory if gt(ptr, _location) { revert(0x60, 0x20) // empty revert message } } uint256 _offset = 0; for (uint256 i = 0; i < memViews.length; i ++) { bytes29 memView = memViews[i]; unsafeCopyTo(memView, _location + _offset); _offset += len(memView); } unsafeView = unsafeBuildUnchecked(0, _location, _offset); } /** * @notice Produce the keccak256 digest of the concatenated contents of multiple views. * @param memViews The views * @return bytes32 - The keccak256 digest */ function joinKeccak(bytes29[] memory memViews) internal view returns (bytes32) { uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer } return keccak(unsafeJoin(memViews, ptr)); } /** * @notice Produce the sha256 digest of the concatenated contents of multiple views. * @param memViews The views * @return bytes32 - The sha256 digest */ function joinSha2(bytes29[] memory memViews) internal view returns (bytes32) { uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer } return sha2(unsafeJoin(memViews, ptr)); } /** * @notice copies all views, joins them into a new bytearray. * @param memViews The views * @return ret - The new byte array */ function join(bytes29[] memory memViews) internal view returns (bytes memory ret) { uint256 ptr; assembly { // solium-disable-previous-line security/no-inline-assembly ptr := mload(0x40) // load unused memory pointer } bytes29 _newView = unsafeJoin(memViews, ptr + 0x20); uint256 _written = len(_newView); uint256 _footprint = footprint(_newView); assembly { // solium-disable-previous-line security/no-inline-assembly // store the legnth mstore(ptr, _written) // new pointer is old + 0x20 + the footprint of the body mstore(0x40, add(add(ptr, _footprint), 0x20)) ret := ptr } } } /** * @title Message Library * @notice Library for formatted messages used by Relayer and Receiver. * * @dev The message body is dynamically-sized to support custom message body * formats. Other fields must be fixed-size to avoid hash collisions. * Each other input value has an explicit type to guarantee fixed-size. * Padding: uintNN fields are left-padded, and bytesNN fields are right-padded. * * Field Bytes Type Index * version 4 uint32 0 * sourceDomain 4 uint32 4 * destinationDomain 4 uint32 8 * nonce 8 uint64 12 * sender 32 bytes32 20 * recipient 32 bytes32 52 * destinationCaller 32 bytes32 84 * messageBody dynamic bytes 116 * **/ library Message { using TypedMemView for bytes; using TypedMemView for bytes29; // Indices of each field in message uint8 private constant VERSION_INDEX = 0; uint8 private constant SOURCE_DOMAIN_INDEX = 4; uint8 private constant DESTINATION_DOMAIN_INDEX = 8; uint8 private constant NONCE_INDEX = 12; uint8 private constant SENDER_INDEX = 20; uint8 private constant RECIPIENT_INDEX = 52; uint8 private constant DESTINATION_CALLER_INDEX = 84; uint8 private constant MESSAGE_BODY_INDEX = 116; /** * @notice Returns formatted (packed) message with provided fields * @param _msgVersion the version of the message format * @param _msgSourceDomain Domain of home chain * @param _msgDestinationDomain Domain of destination chain * @param _msgNonce Destination-specific nonce * @param _msgSender Address of sender on source chain as bytes32 * @param _msgRecipient Address of recipient on destination chain as bytes32 * @param _msgDestinationCaller Address of caller on destination chain as bytes32 * @param _msgRawBody Raw bytes of message body * @return Formatted message **/ function _formatMessage( uint32 _msgVersion, uint32 _msgSourceDomain, uint32 _msgDestinationDomain, uint64 _msgNonce, bytes32 _msgSender, bytes32 _msgRecipient, bytes32 _msgDestinationCaller, bytes memory _msgRawBody ) internal pure returns (bytes memory) { return abi.encodePacked( _msgVersion, _msgSourceDomain, _msgDestinationDomain, _msgNonce, _msgSender, _msgRecipient, _msgDestinationCaller, _msgRawBody ); } // @notice Returns _message's version field function _version(bytes29 _message) internal pure returns (uint32) { return uint32(_message.indexUint(VERSION_INDEX, 4)); } // @notice Returns _message's sourceDomain field function _sourceDomain(bytes29 _message) internal pure returns (uint32) { return uint32(_message.indexUint(SOURCE_DOMAIN_INDEX, 4)); } // @notice Returns _message's destinationDomain field function _destinationDomain(bytes29 _message) internal pure returns (uint32) { return uint32(_message.indexUint(DESTINATION_DOMAIN_INDEX, 4)); } // @notice Returns _message's nonce field function _nonce(bytes29 _message) internal pure returns (uint64) { return uint64(_message.indexUint(NONCE_INDEX, 8)); } // @notice Returns _message's sender field function _sender(bytes29 _message) internal pure returns (bytes32) { return _message.index(SENDER_INDEX, 32); } // @notice Returns _message's recipient field function _recipient(bytes29 _message) internal pure returns (bytes32) { return _message.index(RECIPIENT_INDEX, 32); } // @notice Returns _message's destinationCaller field function _destinationCaller(bytes29 _message) internal pure returns (bytes32) { return _message.index(DESTINATION_CALLER_INDEX, 32); } // @notice Returns _message's messageBody field function _messageBody(bytes29 _message) internal pure returns (bytes29) { return _message.slice( MESSAGE_BODY_INDEX, _message.len() - MESSAGE_BODY_INDEX, 0 ); } /** * @notice converts address to bytes32 (alignment preserving cast.) * @param addr the address to convert to bytes32 */ function addressToBytes32(address addr) external pure returns (bytes32) { return bytes32(uint256(uint160(addr))); } /** * @notice converts bytes32 to address (alignment preserving cast.) * @dev Warning: it is possible to have different input values _buf map to the same address. * For use cases where this is not acceptable, validate that the first 12 bytes of _buf are zero-padding. * @param _buf the bytes32 to convert to address */ function bytes32ToAddress(bytes32 _buf) public pure returns (address) { return address(uint160(uint256(_buf))); } /** * @notice Reverts if message is malformed or incorrect length * @param _message The message as bytes29 */ function _validateMessageFormat(bytes29 _message) internal pure { require(_message.isValid(), "Malformed message"); require( _message.len() >= MESSAGE_BODY_INDEX, "Invalid message: too short" ); } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"address","name":"addr","type":"address"}],"name":"addressToBytes32","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_buf","type":"bytes32"}],"name":"bytes32ToAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"pure","type":"function"}]
Contract Creation Code
60f2610025600b82828239805160001a60731461001857fe5b30600052607381538281f3fe7300000000000000000000000000000000000000003014608060405260043610603d5760003560e01c80635ced058e14604257806382c947b7146078575b600080fd5b605c60048036036020811015605657600080fd5b503560ad565b604080516001600160a01b039092168252519081900360200190f35b609b60048036036020811015608c57600080fd5b50356001600160a01b031660b0565b60408051918252519081900360200190f35b90565b6001600160a01b03169056fea26469706673582212208404296badaef08d58c3bff31538c0b3255dac6b929ac372cc285c74383ad77c64736f6c63430007060033
Deployed Bytecode
0x7333486c492a1e918204a150b6a962bcb4a69a38d83014608060405260043610603d5760003560e01c80635ced058e14604257806382c947b7146078575b600080fd5b605c60048036036020811015605657600080fd5b503560ad565b604080516001600160a01b039092168252519081900360200190f35b609b60048036036020811015608c57600080fd5b50356001600160a01b031660b0565b60408051918252519081900360200190f35b90565b6001600160a01b03169056fea26469706673582212208404296badaef08d58c3bff31538c0b3255dac6b929ac372cc285c74383ad77c64736f6c63430007060033
Deployed Bytecode Sourcemap
36502:4818:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;40795:127;;;;;;;;;;;;;;;;-1:-1:-1;40795:127:0;;:::i;:::-;;;;-1:-1:-1;;;;;40795:127:0;;;;;;;;;;;;;;40304:129;;;;;;;;;;;;;;;;-1:-1:-1;40304:129:0;-1:-1:-1;;;;;40304:129:0;;:::i;:::-;;;;;;;;;;;;;;;;40795:127;40907:4;40795:127::o;40304:129::-;-1:-1:-1;;;;;40402:22:0;;40304:129::o
Swarm Source
ipfs://8404296badaef08d58c3bff31538c0b3255dac6b929ac372cc285c74383ad77c
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 26 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
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.