Created
September 4, 2022 05:42
-
-
Save Elyx0/e6bdf24434fe99169c68ac97f1443504 to your computer and use it in GitHub Desktop.
StateReceiverFlatten.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
forge inspect ./src/StateReceiverFlatten.sol:StateReceiver bytecode | |
0x608060405234801561001057600080fd5b506109ac806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806319494a17146100465780633434735f146100e15780635407ca671461012b575b600080fd5b6100c76004803603604081101561005c57600080fd5b81019080803590602001909291908035906020019064010000000081111561008357600080fd5b82018360208201111561009557600080fd5b803590602001918460018302840111640100000000831117156100b757600080fd5b9091929391929390505050610149565b604051808215151515815260200191505060405180910390f35b6100e961047a565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610133610492565b6040518082815260200191505060405180910390f35b600073fffffffffffffffffffffffffffffffffffffffe73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610200576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260128152602001807f4e6f742053797374656d2041646465737321000000000000000000000000000081525060200191505060405180910390fd5b606061025761025285858080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050610498565b6104c6565b905060006102788260008151811061026b57fe5b60200260200101516105a3565b905080600160005401146102f4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f537461746549647320617265206e6f742073657175656e7469616c000000000081525060200191505060405180910390fd5b600080815480929190600101919050555060006103248360018151811061031757fe5b6020026020010151610614565b905060606103458460028151811061033857fe5b6020026020010151610637565b9050610350826106c3565b1561046f576000624c4b409050606084836040516024018083815260200180602001828103825283818151815260200191508051906020019080838360005b838110156103aa57808201518184015260208101905061038f565b50505050905090810190601f1680156103d75780820380516001836020036101000a031916815260200191505b5093505050506040516020818303038152906040527f26c53bea000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050905060008082516020840160008887f1965050505b505050509392505050565b73fffffffffffffffffffffffffffffffffffffffe81565b60005481565b6104a0610943565b600060208301905060405180604001604052808451815260200182815250915050919050565b60606104d1826106dc565b6104da57600080fd5b60006104e58361072a565b905060608160405190808252806020026020018201604052801561052357816020015b61051061095d565b8152602001906001900390816105085790505b5090506000610535856020015161079b565b8560200151019050600080600090505b848110156105965761055683610824565b915060405180604001604052808381526020018481525084828151811061057957fe5b602002602001018190525081830192508080600101915050610545565b5082945050505050919050565b60008082600001511180156105bd57506021826000015111155b6105c657600080fd5b60006105d5836020015161079b565b9050600081846000015103905060008083866020015101905080519150602083101561060857826020036101000a820491505b81945050505050919050565b6000601582600001511461062757600080fd5b610630826105a3565b9050919050565b6060600082600001511161064a57600080fd5b6000610659836020015161079b565b905060008184600001510390506060816040519080825280601f01601f19166020018201604052801561069b5781602001600182028038833980820191505090505b50905060008160200190506106b78487602001510182856108dc565b81945050505050919050565b600080823b905060008163ffffffff1611915050919050565b600080826000015114156106f35760009050610725565b60008083602001519050805160001a915060c060ff168260ff16101561071e57600092505050610725565b6001925050505b919050565b600080826000015114156107415760009050610796565b60008090506000610755846020015161079b565b84602001510190506000846000015185602001510190505b8082101561078f5761077e82610824565b82019150828060010193505061076d565b8293505050505b919050565b600080825160001a9050608060ff168110156107bb57600091505061081f565b60b860ff168110806107e0575060c060ff1681101580156107df575060f860ff1681105b5b156107ef57600191505061081f565b60c060ff1681101561080f5760018060b80360ff1682030191505061081f565b60018060f80360ff168203019150505b919050565b6000806000835160001a9050608060ff1681101561084557600191506108d2565b60b860ff16811015610862576001608060ff1682030191506108d1565b60c060ff168110156108925760b78103600185019450806020036101000a855104600182018101935050506108d0565b60f860ff168110156108af57600160c060ff1682030191506108cf565b60f78103600185019450806020036101000a855104600182018101935050505b5b5b5b8192505050919050565b60008114156108ea5761093e565b5b602060ff16811061091a5782518252602060ff1683019250602060ff1682019150602060ff16810390506108eb565b6000600182602060ff16036101000a03905080198451168184511681811785525050505b505050565b604051806040016040528060008152602001600081525090565b60405180604001604052806000815260200160008152509056fea265627a7a72315820baa9fb8d83ea311f6aa22cd2ab6a90f17bc1727bfd05a8fc4eee871ad932956264736f6c63430005110032 | |
0x608060405234801561001057600080fd5b506109ac806100206000396000f3fe <- too much. | |
Almost same than : https://polygonscan.com/address/0x0000000000000000000000000000000000001001#code | |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Current bytecode at: https://polygonscan.com/address/0x0000000000000000000000000000000000001001#code | |
// Source: https://github.com/maticnetwork/genesis-contracts/tree/b16a181613862ff475acafb25eb1d3a5c1dde261 | |
pragma solidity ^0.5.11; | |
library RLPReader { | |
uint8 constant STRING_SHORT_START = 0x80; | |
uint8 constant STRING_LONG_START = 0xb8; | |
uint8 constant LIST_SHORT_START = 0xc0; | |
uint8 constant LIST_LONG_START = 0xf8; | |
uint8 constant WORD_SIZE = 32; | |
struct RLPItem { | |
uint len; | |
uint memPtr; | |
} | |
struct Iterator { | |
RLPItem item; // Item that's being iterated over. | |
uint nextPtr; // Position of the next item in the list. | |
} | |
/* | |
* @dev Returns the next element in the iteration. Reverts if it has not next element. | |
* @param self The iterator. | |
* @return The next element in the iteration. | |
*/ | |
function next(Iterator memory self) internal pure returns (RLPItem memory) { | |
require(hasNext(self)); | |
uint ptr = self.nextPtr; | |
uint itemLength = _itemLength(ptr); | |
self.nextPtr = ptr + itemLength; | |
return RLPItem(itemLength, ptr); | |
} | |
/* | |
* @dev Returns true if the iteration has more elements. | |
* @param self The iterator. | |
* @return true if the iteration has more elements. | |
*/ | |
function hasNext(Iterator memory self) internal pure returns (bool) { | |
RLPItem memory item = self.item; | |
return self.nextPtr < item.memPtr + item.len; | |
} | |
/* | |
* @param item RLP encoded bytes | |
*/ | |
function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { | |
uint memPtr; | |
assembly { | |
memPtr := add(item, 0x20) | |
} | |
return RLPItem(item.length, memPtr); | |
} | |
/* | |
* @dev Create an iterator. Reverts if item is not a list. | |
* @param self The RLP item. | |
* @return An 'Iterator' over the item. | |
*/ | |
function iterator(RLPItem memory self) internal pure returns (Iterator memory) { | |
require(isList(self)); | |
uint ptr = self.memPtr + _payloadOffset(self.memPtr); | |
return Iterator(self, ptr); | |
} | |
/* | |
* @param item RLP encoded bytes | |
*/ | |
function rlpLen(RLPItem memory item) internal pure returns (uint) { | |
return item.len; | |
} | |
/* | |
* @param item RLP encoded bytes | |
*/ | |
function payloadLen(RLPItem memory item) internal pure returns (uint) { | |
return item.len - _payloadOffset(item.memPtr); | |
} | |
/* | |
* @param item RLP encoded list in bytes | |
*/ | |
function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { | |
require(isList(item)); | |
uint items = numItems(item); | |
RLPItem[] memory result = new RLPItem[](items); | |
uint memPtr = item.memPtr + _payloadOffset(item.memPtr); | |
uint dataLen; | |
for (uint i = 0; i < items; i++) { | |
dataLen = _itemLength(memPtr); | |
result[i] = RLPItem(dataLen, memPtr); | |
memPtr = memPtr + dataLen; | |
} | |
return result; | |
} | |
// @return indicator whether encoded payload is a list. negate this function call for isData. | |
function isList(RLPItem memory item) internal pure returns (bool) { | |
if (item.len == 0) return false; | |
uint8 byte0; | |
uint memPtr = item.memPtr; | |
assembly { | |
byte0 := byte(0, mload(memPtr)) | |
} | |
if (byte0 < LIST_SHORT_START) | |
return false; | |
return true; | |
} | |
/** RLPItem conversions into data types **/ | |
// @returns raw rlp encoding in bytes | |
function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { | |
bytes memory result = new bytes(item.len); | |
if (result.length == 0) return result; | |
uint ptr; | |
assembly { | |
ptr := add(0x20, result) | |
} | |
copy(item.memPtr, ptr, item.len); | |
return result; | |
} | |
// any non-zero byte is considered true | |
function toBoolean(RLPItem memory item) internal pure returns (bool) { | |
require(item.len == 1); | |
uint result; | |
uint memPtr = item.memPtr; | |
assembly { | |
result := byte(0, mload(memPtr)) | |
} | |
return result == 0 ? false : true; | |
} | |
function toAddress(RLPItem memory item) internal pure returns (address) { | |
// 1 byte for the length prefix | |
require(item.len == 21); | |
return address(toUint(item)); | |
} | |
function toUint(RLPItem memory item) internal pure returns (uint) { | |
require(item.len > 0 && item.len <= 33); | |
uint offset = _payloadOffset(item.memPtr); | |
uint len = item.len - offset; | |
uint result; | |
uint memPtr = item.memPtr + offset; | |
assembly { | |
result := mload(memPtr) | |
// shfit to the correct location if neccesary | |
if lt(len, 32) { | |
result := div(result, exp(256, sub(32, len))) | |
} | |
} | |
return result; | |
} | |
// enforces 32 byte length | |
function toUintStrict(RLPItem memory item) internal pure returns (uint) { | |
// one byte prefix | |
require(item.len == 33); | |
uint result; | |
uint memPtr = item.memPtr + 1; | |
assembly { | |
result := mload(memPtr) | |
} | |
return result; | |
} | |
function toBytes(RLPItem memory item) internal pure returns (bytes memory) { | |
require(item.len > 0); | |
uint offset = _payloadOffset(item.memPtr); | |
uint len = item.len - offset; // data length | |
bytes memory result = new bytes(len); | |
uint destPtr; | |
assembly { | |
destPtr := add(0x20, result) | |
} | |
copy(item.memPtr + offset, destPtr, len); | |
return result; | |
} | |
/* | |
* Private Helpers | |
*/ | |
// @return number of payload items inside an encoded list. | |
function numItems(RLPItem memory item) private pure returns (uint) { | |
if (item.len == 0) return 0; | |
uint count = 0; | |
uint currPtr = item.memPtr + _payloadOffset(item.memPtr); | |
uint endPtr = item.memPtr + item.len; | |
while (currPtr < endPtr) { | |
currPtr = currPtr + _itemLength(currPtr); // skip over an item | |
count++; | |
} | |
return count; | |
} | |
// @return entire rlp item byte length | |
function _itemLength(uint memPtr) private pure returns (uint) { | |
uint itemLen; | |
uint byte0; | |
assembly { | |
byte0 := byte(0, mload(memPtr)) | |
} | |
if (byte0 < STRING_SHORT_START) | |
itemLen = 1; | |
else if (byte0 < STRING_LONG_START) | |
itemLen = byte0 - STRING_SHORT_START + 1; | |
else if (byte0 < LIST_SHORT_START) { | |
assembly { | |
let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is | |
memPtr := add(memPtr, 1) // skip over the first byte | |
/* 32 byte word size */ | |
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len | |
itemLen := add(dataLen, add(byteLen, 1)) | |
} | |
} | |
else if (byte0 < LIST_LONG_START) { | |
itemLen = byte0 - LIST_SHORT_START + 1; | |
} | |
else { | |
assembly { | |
let byteLen := sub(byte0, 0xf7) | |
memPtr := add(memPtr, 1) | |
let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length | |
itemLen := add(dataLen, add(byteLen, 1)) | |
} | |
} | |
return itemLen; | |
} | |
// @return number of bytes until the data | |
function _payloadOffset(uint memPtr) private pure returns (uint) { | |
uint byte0; | |
assembly { | |
byte0 := byte(0, mload(memPtr)) | |
} | |
if (byte0 < STRING_SHORT_START) | |
return 0; | |
else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) | |
return 1; | |
else if (byte0 < LIST_SHORT_START) // being explicit | |
return byte0 - (STRING_LONG_START - 1) + 1; | |
else | |
return byte0 - (LIST_LONG_START - 1) + 1; | |
} | |
/* | |
* @param src Pointer to source | |
* @param dest Pointer to destination | |
* @param len Amount of memory to copy from the source | |
*/ | |
function copy(uint src, uint dest, uint len) private pure { | |
if (len == 0) return; | |
// copy as many word sizes as possible | |
for (; len >= WORD_SIZE; len -= WORD_SIZE) { | |
assembly { | |
mstore(dest, mload(src)) | |
} | |
src += WORD_SIZE; | |
dest += WORD_SIZE; | |
} | |
// left over bytes. Mask is used to remove unwanted bytes from the word | |
uint mask = 256 ** (WORD_SIZE - len) - 1; | |
assembly { | |
let srcpart := and(mload(src), not(mask)) // zero out src | |
let destpart := and(mload(dest), mask) // retrieve the bytes | |
mstore(dest, or(destpart, srcpart)) | |
} | |
} | |
} | |
contract System { | |
address public constant SYSTEM_ADDRESS = 0xffffFFFfFFffffffffffffffFfFFFfffFFFfFFfE; | |
modifier onlySystem() { | |
require(msg.sender == SYSTEM_ADDRESS, "Not System Addess!"); | |
_; | |
} | |
} | |
// IStateReceiver represents interface to receive state | |
interface IStateReceiver { | |
function onStateReceive(uint256 stateId, bytes calldata data) external; | |
} | |
contract StateReceiver is System { | |
using RLPReader for bytes; | |
using RLPReader for RLPReader.RLPItem; | |
uint256 public lastStateId; | |
function commitState(uint256 syncTime, bytes calldata recordBytes) onlySystem external returns(bool success) { | |
// parse state data | |
RLPReader.RLPItem[] memory dataList = recordBytes.toRlpItem().toList(); | |
uint256 stateId = dataList[0].toUint(); | |
require( | |
lastStateId + 1 == stateId, | |
"StateIds are not sequential" | |
); | |
lastStateId++; | |
address receiver = dataList[1].toAddress(); | |
bytes memory stateData = dataList[2].toBytes(); | |
// notify state receiver contract, in a non-revert manner | |
if (isContract(receiver)) { | |
uint256 txGas = 5000000; | |
bytes memory data = abi.encodeWithSignature("onStateReceive(uint256,bytes)", stateId, stateData); | |
// solium-disable-next-line security/no-inline-assembly | |
assembly { | |
success := call(txGas, receiver, 0, add(data, 0x20), mload(data), 0, 0) | |
} | |
} | |
} | |
// check if address is contract | |
function isContract(address _addr) private view returns (bool){ | |
uint32 size; | |
assembly { | |
size := extcodesize(_addr) | |
} | |
return (size > 0); | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment