More Info
Private Name Tags
ContractCreator
Latest 1 from a total of 1 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Renounce Ownersh... | 18122892 | 519 days ago | IN | 0 ETH | 0.00026344 |
Latest 1 internal transaction
Advanced mode:
Parent Transaction Hash | Block |
From
|
To
|
|||
---|---|---|---|---|---|---|
18122866 | 519 days ago | Contract Creation | 0 ETH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Contract Source Code Verified (Exact Match)
Contract Name:
CartesiDApp
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) pragma solidity ^0.8.8; import {ICartesiDApp, Proof} from "./ICartesiDApp.sol"; import {IConsensus} from "../consensus/IConsensus.sol"; import {LibOutputValidation, OutputValidityProof} from "../library/LibOutputValidation.sol"; import {Bitmask} from "@cartesi/util/contracts/Bitmask.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC721Holder} from "@openzeppelin/contracts/token/ERC721/utils/ERC721Holder.sol"; import {ERC1155Holder} from "@openzeppelin/contracts/token/ERC1155/utils/ERC1155Holder.sol"; import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; /// @title Cartesi DApp /// /// @notice This contract acts as the base layer incarnation of a DApp running on the execution layer. /// The DApp is hereby able to interact with other smart contracts through the execution of vouchers /// and the validation of notices. These outputs are generated by the DApp backend on the execution /// layer and can be proven in the base layer thanks to claims submitted by a consensus contract. /// /// A voucher is a one-time message call to another contract. It can encode asset transfers, approvals, /// or any other message call that doesn't require Ether to be sent along. A voucher will only be consumed /// if the underlying message call succeeds (that is, it doesn't revert). Furthermore, the return data of /// the message call is discarded entirely. As a protective measure against reentrancy attacks, nested /// voucher executions are prohibited. /// /// A notice, on the other hand, constitutes an arbitrary piece of data that can be proven any number of times. /// On their own, they do not trigger any type of contract-to-contract interaction. /// Rather, they merely serve to attest off-chain results, e.g. which player won a particular chess match. /// /// Every DApp is subscribed to a consensus contract, and governed by a single address, the owner. /// The consensus has the power of submitting claims, which, in turn, are used to validate vouchers and notices. /// Meanwhile, the owner has complete power over the DApp, as it can replace the consensus at any time. /// Therefore, the users of a DApp must trust both the consensus and the DApp owner. /// /// The DApp developer can choose whichever ownership and consensus models it wants. /// /// Examples of DApp ownership models include: /// /// * no owner (address zero) /// * individual signer (externally-owned account) /// * multiple signers (multi-sig) /// * DAO (decentralized autonomous organization) /// * self-owned DApp (off-chain governance logic) /// /// See `IConsensus` for examples of consensus models. /// /// This contract inherits the following OpenZeppelin contracts. /// For more information, please consult OpenZeppelin's official documentation. /// /// * `Ownable` /// * `ERC721Holder` /// * `ERC1155Holder` /// * `ReentrancyGuard` /// contract CartesiDApp is ICartesiDApp, Ownable, ERC721Holder, ERC1155Holder, ReentrancyGuard { using Bitmask for mapping(uint256 => uint256); using LibOutputValidation for OutputValidityProof; /// @notice Raised when executing an already executed voucher. error VoucherReexecutionNotAllowed(); /// @notice Raised when the transfer fails. error EtherTransferFailed(); /// @notice Raised when a mehtod is not called by DApp itself. error OnlyDApp(); /// @notice The initial machine state hash. /// @dev See the `getTemplateHash` function. bytes32 internal immutable templateHash; /// @notice The executed voucher bitmask, which keeps track of which vouchers /// were executed already in order to avoid re-execution. /// @dev See the `wasVoucherExecuted` function. mapping(uint256 => uint256) internal voucherBitmask; /// @notice The current consensus contract. /// @dev See the `getConsensus` and `migrateToConsensus` functions. IConsensus internal consensus; /// @notice Creates a `CartesiDApp` contract. /// @param _consensus The initial consensus contract /// @param _owner The initial DApp owner /// @param _templateHash The initial machine state hash /// @dev Calls the `join` function on `_consensus`. constructor(IConsensus _consensus, address _owner, bytes32 _templateHash) { transferOwnership(_owner); templateHash = _templateHash; consensus = _consensus; _consensus.join(); } function executeVoucher( address _destination, bytes calldata _payload, Proof calldata _proof ) external override nonReentrant returns (bool) { bytes32 epochHash; uint256 firstInputIndex; uint256 lastInputIndex; uint256 inputIndex; // query the current consensus for the desired claim (epochHash, firstInputIndex, lastInputIndex) = getClaim(_proof.context); // validate input index range and calculate the input index // based on the input index range provided by the consensus inputIndex = _proof.validity.validateInputIndexRange( firstInputIndex, lastInputIndex ); // reverts if proof isn't valid _proof.validity.validateVoucher(_destination, _payload, epochHash); uint256 voucherPosition = LibOutputValidation.getBitMaskPosition( _proof.validity.outputIndexWithinInput, inputIndex ); // check if voucher has been executed if (_wasVoucherExecuted(voucherPosition)) { revert VoucherReexecutionNotAllowed(); } // execute voucher (bool succ, ) = _destination.call(_payload); // if properly executed, mark it as executed and emit event if (succ) { voucherBitmask.setBit(voucherPosition, true); emit VoucherExecuted(voucherPosition); } return succ; } function wasVoucherExecuted( uint256 _inputIndex, uint256 _outputIndexWithinInput ) external view override returns (bool) { uint256 voucherPosition = LibOutputValidation.getBitMaskPosition( _outputIndexWithinInput, _inputIndex ); return _wasVoucherExecuted(voucherPosition); } function _wasVoucherExecuted( uint256 _voucherPosition ) internal view returns (bool) { return voucherBitmask.getBit(_voucherPosition); } function validateNotice( bytes calldata _notice, Proof calldata _proof ) external view override returns (bool) { bytes32 epochHash; uint256 firstInputIndex; uint256 lastInputIndex; // query the current consensus for the desired claim (epochHash, firstInputIndex, lastInputIndex) = getClaim(_proof.context); // validate the epoch input index based on the input index range // provided by the consensus _proof.validity.validateInputIndexRange( firstInputIndex, lastInputIndex ); // reverts if proof isn't valid _proof.validity.validateNotice(_notice, epochHash); return true; } /// @notice Retrieve a claim about the DApp from the current consensus. /// The encoding of `_proofContext` might vary depending on the implementation. /// @param _proofContext Data for retrieving the desired claim /// @return The claimed epoch hash /// @return The index of the first input of the epoch in the input box /// @return The index of the last input of the epoch in the input box function getClaim( bytes calldata _proofContext ) internal view returns (bytes32, uint256, uint256) { return consensus.getClaim(address(this), _proofContext); } function migrateToConsensus( IConsensus _newConsensus ) external override onlyOwner { consensus = _newConsensus; _newConsensus.join(); emit NewConsensus(_newConsensus); } function getTemplateHash() external view override returns (bytes32) { return templateHash; } function getConsensus() external view override returns (IConsensus) { return consensus; } /// @notice Accept Ether transfers. /// @dev If you wish to transfer Ether to a DApp while informing /// the DApp backend of it, then please do so through the Ether portal contract. receive() external payable {} /// @notice Transfer some amount of Ether to some recipient. /// @param _receiver The address which will receive the amount of Ether /// @param _value The amount of Ether to be transferred in Wei /// @dev This function can only be called by the DApp itself through vouchers. /// If this method is not called by DApp itself, `OnlyDApp` error is raised. /// If the transfer fails, `EtherTransferFailed` error is raised. function withdrawEther(address _receiver, uint256 _value) external { if (msg.sender != address(this)) { revert OnlyDApp(); } (bool sent, ) = _receiver.call{value: _value}(""); if (!sent) { revert EtherTransferFailed(); } } }
// SPDX-License-Identifier: Apache-2.0 // 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.8.0; /// @title Bit Mask Library /// @author Stephen Chen /// @notice Implements bit mask with dynamic array library Bitmask { /// @notice Set a bit in the bit mask function setBit(mapping(uint256 => uint256) storage bitmask, uint256 _bit, bool _value) public { // calculate the number of bits has been store in bitmask now uint256 positionOfMask = uint256(_bit / 256); uint256 positionOfBit = _bit % 256; if (_value) { bitmask[positionOfMask] = bitmask[positionOfMask] | (1 << positionOfBit); } else { bitmask[positionOfMask] = bitmask[positionOfMask] & ~(1 << positionOfBit); } } /// @notice Get a bit in the bit mask function getBit(mapping(uint256 => uint256) storage bitmask, uint256 _bit) public view returns (bool) { // calculate the number of bits has been store in bitmask now uint256 positionOfMask = uint256(_bit / 256); uint256 positionOfBit = _bit % 256; return ((bitmask[positionOfMask] & (1 << positionOfBit)) != 0); } }
// SPDX-License-Identifier: Apache-2.0 // 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. /// @title CartesiMath /// @author Felipe Argento pragma solidity ^0.8.0; library CartesiMathV2 { // mapping values are packed as bytes3 each // see test/TestCartesiMath.ts for decimal values bytes constant log2tableTimes1M = hex"0000000F4240182F421E8480236E082771822AD63A2DC6C0305E8532B04834C96736B3C23876D73A187A3B9D4A3D09003E5EA63FA0C540D17741F28843057D440BA745062945F60246DC1047B917488DC7495ABA4A207C4ADF8A4B98544C4B404CF8AA4DA0E64E44434EE3054F7D6D5013B750A61A5134C851BFF05247BD52CC58534DE753CC8D54486954C19C55384255AC75561E50568DE956FB575766B057D00758376F589CFA5900BA5962BC59C3135A21CA5A7EF15ADA945B34BF5B8D805BE4DF5C3AEA5C8FA95CE3265D356C5D86835DD6735E25455E73005EBFAD5F0B525F55F75F9FA25FE85A60302460770860BD0A61023061467F6189FD61CCAE620E98624FBF62902762CFD5630ECD634D12638AA963C7966403DC643F7F647A8264B4E864EEB56527EC6560906598A365D029660724663D9766738566A8F066DDDA6712476746386779AF67ACAF67DF3A6811526842FA68743268A4FC68D55C6905536934E169640A6992CF69C13169EF326A1CD46A4A186A76FF6AA38C6ACFC0"; /// @notice Approximates log2 * 1M /// @param _num number to take log2 * 1M of /// @return approximate log2 times 1M function log2ApproxTimes1M(uint256 _num) public pure returns (uint256) { require(_num > 0, "Number cannot be zero"); uint256 leading = 0; if (_num == 1) return 0; while (_num > 128) { _num = _num >> 1; leading += 1; } return (leading * uint256(1000000)) + (getLog2TableTimes1M(_num)); } /// @notice navigates log2tableTimes1M /// @param _num number to take log2 of /// @return result after table look-up function getLog2TableTimes1M(uint256 _num) public pure returns (uint256) { bytes3 result = 0; for (uint8 i = 0; i < 3; i++) { bytes3 tempResult = log2tableTimes1M[(_num - 1) * 3 + i]; result = result | (tempResult >> (i * 8)); } return uint256(uint24(result)); } /// @notice get floor of log2 of number /// @param _num number to take floor(log2) of /// @return floor(log2) of _num function getLog2Floor(uint256 _num) public pure returns (uint8) { require(_num != 0, "log of zero is undefined"); return uint8(255 - clz(_num)); } /// @notice checks if a number is Power of 2 /// @param _num number to check /// @return true if number is power of 2, false if not function isPowerOf2(uint256 _num) public pure returns (bool) { if (_num == 0) return false; return _num & (_num - 1) == 0; } /// @notice count trailing zeros /// @param _num number you want the ctz of /// @dev this a binary search implementation function ctz(uint256 _num) public pure returns (uint256) { if (_num == 0) return 256; uint256 n = 0; if (_num & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { n = n + 128; _num = _num >> 128; } if (_num & 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF == 0) { n = n + 64; _num = _num >> 64; } if (_num & 0x00000000000000000000000000000000000000000000000000000000FFFFFFFF == 0) { n = n + 32; _num = _num >> 32; } if (_num & 0x000000000000000000000000000000000000000000000000000000000000FFFF == 0) { n = n + 16; _num = _num >> 16; } if (_num & 0x00000000000000000000000000000000000000000000000000000000000000FF == 0) { n = n + 8; _num = _num >> 8; } if (_num & 0x000000000000000000000000000000000000000000000000000000000000000F == 0) { n = n + 4; _num = _num >> 4; } if (_num & 0x0000000000000000000000000000000000000000000000000000000000000003 == 0) { n = n + 2; _num = _num >> 2; } if (_num & 0x0000000000000000000000000000000000000000000000000000000000000001 == 0) { n = n + 1; } return n; } /// @notice count leading zeros /// @param _num number you want the clz of /// @dev this a binary search implementation function clz(uint256 _num) public pure returns (uint256) { if (_num == 0) return 256; uint256 n = 0; if (_num & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 == 0) { n = n + 128; _num = _num << 128; } if (_num & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 == 0) { n = n + 64; _num = _num << 64; } if (_num & 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 == 0) { n = n + 32; _num = _num << 32; } if (_num & 0xFFFF000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 16; _num = _num << 16; } if (_num & 0xFF00000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 8; _num = _num << 8; } if (_num & 0xF000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 4; _num = _num << 4; } if (_num & 0xC000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 2; _num = _num << 2; } if (_num & 0x8000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 1; } return n; } }
// SPDX-License-Identifier: Apache-2.0 // 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. /// @title Library for Merkle proofs pragma solidity ^0.8.0; import "./CartesiMathV2.sol"; library MerkleV2 { using CartesiMathV2 for uint256; uint128 constant L_WORD_SIZE = 3; // word = 8 bytes, log = 3 // number of hashes in EMPTY_TREE_HASHES uint128 constant EMPTY_TREE_SIZE = 1952; // 61*32=1952. 32 bytes per 61 indexes (64 words) // merkle root hashes of trees of zero concatenated // 32 bytes for each root, first one is keccak(0), second one is // keccak(keccack(0), keccak(0)) and so on bytes constant EMPTY_TREE_HASHES = hex"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce4d9470a821fbe90117ec357e30bad9305732fb19ddf54a07dd3e29f440619254ae39ce8537aca75e2eff3e38c98011dfe934e700a0967732fc07b430dd656a233fc9a15f5b4869c872f81087bb6104b7d63e6f9ab47f2c43f3535eae7172aa7f17d2dd614cddaa4d879276b11e0672c9560033d3e8453a1d045339d34ba601b9c37b8b13ca95166fb7af16988a70fcc90f38bf9126fd833da710a47fb37a55e68e7a427fa943d9966b389f4f257173676090c6e95f43e2cb6d65f8758111e30930b0b9deb73e155c59740bacf14a6ff04b64bb8e201a506409c3fe381ca4ea90cd5deac729d0fdaccc441d09d7325f41586ba13c801b7eccae0f95d8f3933efed8b96e5b7f6f459e9cb6a2f41bf276c7b85c10cd4662c04cbbb365434726c0a0c9695393027fb106a8153109ac516288a88b28a93817899460d6310b71cf1e6163e8806fa0d4b197a259e8c3ac28864268159d0ac85f8581ca28fa7d2c0c03eb91e3eee5ca7a3da2b3053c9770db73599fb149f620e3facef95e947c0ee860b72122e31e4bbd2b7c783d79cc30f60c6238651da7f0726f767d22747264fdb046f7549f26cc70ed5e18baeb6c81bb0625cb95bb4019aeecd40774ee87ae29ec517a71f6ee264c5d761379b3d7d617ca83677374b49d10aec50505ac087408ca892b573c267a712a52e1d06421fe276a03efb1889f337201110fdc32a81f8e152499af665835aabfdc6740c7e2c3791a31c3cdc9f5ab962f681b12fc092816a62f27d86025599a41233848702f0cfc0437b445682df51147a632a0a083d2d38b5e13e466a8935afff58bb533b3ef5d27fba63ee6b0fd9e67ff20af9d50deee3f8bf065ec220c1fd4ba57e341261d55997f85d66d32152526736872693d2b437a233e2337b715f6ac9a6a272622fdc2d67fcfe1da3459f8dab4ed7e40a657a54c36766c5e8ac9a88b35b05c34747e6507f6b044ab66180dc76ac1a696de03189593fedc0d0dbbd855c8ead673544899b0960e4a5a7ca43b4ef90afe607de7698caefdc242788f654b57a4fb32a71b335ef6ff9a4cc118b282b53bdd6d6192b7a82c3c5126b9c7e33c8e5a5ac9738b8bd31247fb7402054f97b573e8abb9faad219f4fd085aceaa7f542d787ee4196d365f3cc566e7bbcfbfd451230c48d804c017d21e2d8fa914e2559bb72bf0ab78c8ab92f00ef0d0d576eccdd486b64138a4172674857e543d1d5b639058dd908186597e366ad5f3d9c7ceaff44d04d1550b8d33abc751df07437834ba5acb32328a396994aebb3c40f759c2d6d7a3cb5377e55d5d218ef5a296dda8ddc355f3f50c3d0b660a51dfa4d98a6a5a33564556cf83c1373a814641d6a1dcef97b883fee61bb84fe60a3409340217e629cc7e4dcc93b85d8820921ff5826148b60e6939acd7838e1d7f20562bff8ee4b5ec4a05ad997a57b9796fdcb2eda87883c2640b072b140b946bfdf6575cacc066fdae04f6951e63624cbd316a677cad529bbe4e97b9144e4bc06c4afd1de55dd3e1175f90423847a230d34dfb71ed56f2965a7f6c72e6aa33c24c303fd67745d632656c5ef90bec80f4f5d1daa251988826cef375c81c36bf457e09687056f924677cb0bccf98dff81e014ce25f2d132497923e267363963cdf4302c5049d63131dc03fd95f65d8b6aa5934f817252c028c90f56d413b9d5d10d89790707dae2fabb249f649929927c21dd71e3f656826de5451c5da375aadecbd59d5ebf3a31fae65ac1b316a1611f1b276b26530f58d7247df459ce1f86db1d734f6f811932f042cee45d0e455306d01081bc3384f82c5fb2aacaa19d89cdfa46cc916eac61121475ba2e6191b4feecbe1789717021a158ace5d06744b40f551076b67cd63af60007f8c99876e1424883a45ec49d497ddaf808a5521ca74a999ab0b3c7aa9c80f85e93977ec61ce68b20307a1a81f71ca645b568fcd319ccbb5f651e87b707d37c39e15f945ea69e2f7c7d2ccc85b7e654c07e96f0636ae4044fe0e38590b431795ad0f8647bdd613713ada493cc17efd313206380e6a685b8198475bbd021c6e9d94daab2214947127506073e44d5408ba166c512a0b86805d07f5a44d3c41706be2bc15e712e55805248b92e8677d90f6d284d1d6ffaff2c430657042a0e82624fa3717b06cc0a6fd12230ea586dae83019fb9e06034ed2803c98d554b93c9a52348cafff75c40174a91f9ae6b8647854a156029f0b88b83316663ce574a4978277bb6bb27a31085634b6ec78864b6d8201c7e93903d75815067e378289a3d072ae172dafa6a452470f8d645bebfad9779594fc0784bb764a22e3a8181d93db7bf97893c414217a618ccb14caa9e92e8c61673afc9583662e812adba1f87a9c68202d60e909efab43c42c0cb00695fc7f1ffe67c75ca894c3c51e1e5e731360199e600f6ced9a87b2a6a87e70bf251bb5075ab222138288164b2eda727515ea7de12e2496d4fe42ea8d1a120c03cf9c50622c2afe4acb0dad98fd62d07ab4e828a94495f6d1ab973982c7ccbe6c1fae02788e4422ae22282fa49cbdb04ba54a7a238c6fc41187451383460762c06d1c8a72b9cd718866ad4b689e10c9a8c38fe5ef045bd785b01e980fc82c7e3532ce81876b778dd9f1ceeba4478e86411fb6fdd790683916ca832592485093644e8760cd7b4c01dba1ccc82b661bf13f0e3f34acd6b88"; /// @notice Gets merkle root hash of drive with a replacement /// @param _position position of _drive /// @param _logSizeOfReplacement log2 of size the replacement /// @param _logSizeOfFullDrive log2 of size the full drive, which can be the entire machine /// @param _replacement hash of the replacement /// @param siblings of replacement that merkle root can be calculated function getRootAfterReplacementInDrive( uint256 _position, uint256 _logSizeOfReplacement, uint256 _logSizeOfFullDrive, bytes32 _replacement, bytes32[] calldata siblings ) public pure returns (bytes32) { require( _logSizeOfFullDrive >= _logSizeOfReplacement && _logSizeOfReplacement >= 3 && _logSizeOfFullDrive <= 64, "3 <= logSizeOfReplacement <= logSizeOfFullDrive <= 64" ); uint256 size = 1 << _logSizeOfReplacement; require(((size - 1) & _position) == 0, "Position is not aligned"); require(siblings.length == _logSizeOfFullDrive - _logSizeOfReplacement, "Proof length does not match"); for (uint256 i; i < siblings.length; i++) { if ((_position & (size << i)) == 0) { _replacement = keccak256(abi.encodePacked(_replacement, siblings[i])); } else { _replacement = keccak256(abi.encodePacked(siblings[i], _replacement)); } } return _replacement; } /// @notice Gets precomputed hash of zero in empty tree hashes /// @param _index of hash wanted /// @dev first index is keccak(0), second index is keccak(keccak(0), keccak(0)) function getEmptyTreeHashAtIndex(uint256 _index) public pure returns (bytes32) { uint256 start = _index * 32; require(EMPTY_TREE_SIZE >= start + 32, "index out of bounds"); bytes32 hashedZeros; bytes memory zeroTree = EMPTY_TREE_HASHES; // first word is length, then skip index words assembly { hashedZeros := mload(add(add(zeroTree, 0x20), start)) } return hashedZeros; } /// @notice get merkle root of generic array of bytes /// @param _data array of bytes to be merklelized /// @param _log2Size log2 of total size of the drive /// @dev _data is padded with zeroes until is multiple of 8 /// @dev root is completed with zero tree until log2size is complete /// @dev hashes are taken word by word (8 bytes by 8 bytes) function getMerkleRootFromBytes(bytes calldata _data, uint256 _log2Size) public pure returns (bytes32) { require(_log2Size >= 3 && _log2Size <= 64, "range of log2Size: [3,64]"); // if _data is empty return pristine drive of size log2size if (_data.length == 0) return getEmptyTreeHashAtIndex(_log2Size - 3); // total size of the drive in words uint256 size = 1 << (_log2Size - 3); require(size << L_WORD_SIZE >= _data.length, "data is bigger than drive"); // the stack depth is log2(_data.length / 8) + 2 uint256 stack_depth = 2 + ((_data.length) >> L_WORD_SIZE).getLog2Floor(); bytes32[] memory stack = new bytes32[](stack_depth); uint256 numOfHashes; // total number of hashes on stack (counting levels) uint256 stackLength; // total length of stack uint256 numOfJoins; // number of hashes of the same level on stack uint256 topStackLevel; // hash level of the top of the stack while (numOfHashes < size) { if ((numOfHashes << L_WORD_SIZE) < _data.length) { // we still have words to hash stack[stackLength] = getHashOfWordAtIndex(_data, numOfHashes); numOfHashes++; numOfJoins = numOfHashes; } else { // since padding happens in hashOfWordAtIndex function // we only need to complete the stack with pre-computed // hash(0), hash(hash(0),hash(0)) and so on topStackLevel = numOfHashes.ctz(); stack[stackLength] = getEmptyTreeHashAtIndex(topStackLevel); //Empty Tree Hash summarizes many hashes numOfHashes = numOfHashes + (1 << topStackLevel); numOfJoins = numOfHashes >> topStackLevel; } stackLength++; // while there are joins, hash top of stack together while (numOfJoins & 1 == 0) { bytes32 h2 = stack[stackLength - 1]; bytes32 h1 = stack[stackLength - 2]; stack[stackLength - 2] = keccak256(abi.encodePacked(h1, h2)); stackLength = stackLength - 1; // remove hashes from stack numOfJoins = numOfJoins >> 1; } } require(stackLength == 1, "stack error"); return stack[0]; } /// @notice Get the hash of a word in an array of bytes /// @param _data array of bytes /// @param _wordIndex index of word inside the bytes to get the hash of /// @dev if word is incomplete (< 8 bytes) it gets padded with zeroes function getHashOfWordAtIndex(bytes calldata _data, uint256 _wordIndex) public pure returns (bytes32) { uint256 start = _wordIndex << L_WORD_SIZE; uint256 end = start + (1 << L_WORD_SIZE); // TODO: in .lua this just returns zero, but this might be more consistent require(start <= _data.length, "word out of bounds"); if (end <= _data.length) { return keccak256(abi.encodePacked(_data[start:end])); } // word is incomplete // fill paddedSlice with incomplete words - the rest is going to be bytes(0) bytes memory paddedSlice = new bytes(8); uint256 remaining = _data.length - start; for (uint256 i; i < remaining; i++) { paddedSlice[i] = _data[start + i]; } return keccak256(paddedSlice); } /// @notice Calculate the root of Merkle tree from an array of power of 2 elements /// @param hashes The array containing power of 2 elements /// @return byte32 the root hash being calculated function calculateRootFromPowerOfTwo(bytes32[] memory hashes) public pure returns (bytes32) { // revert when the input is not of power of 2 require((hashes.length).isPowerOf2(), "array len not power of 2"); if (hashes.length == 1) { return hashes[0]; } else { bytes32[] memory newHashes = new bytes32[](hashes.length >> 1); for (uint256 i; i < hashes.length; i += 2) { newHashes[i >> 1] = keccak256(abi.encodePacked(hashes[i], hashes[i + 1])); } return calculateRootFromPowerOfTwo(newHashes); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol) pragma solidity ^0.8.0; import "../utils/Context.sol"; /** * @dev Contract module which provides a basic access control mechanism, where * there is an account (an owner) that can be granted exclusive access to * specific functions. * * By default, the owner account will be the one that deploys the contract. This * can later be changed with {transferOwnership}. * * This module is used through inheritance. It will make available the modifier * `onlyOwner`, which can be applied to your functions to restrict their use to * the owner. */ abstract contract Ownable is Context { address private _owner; event OwnershipTransferred(address indexed previousOwner, address indexed newOwner); /** * @dev Initializes the contract setting the deployer as the initial owner. */ constructor() { _transferOwnership(_msgSender()); } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { require(owner() == _msgSender(), "Ownable: caller is not the owner"); } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby disabling any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { require(newOwner != address(0), "Ownable: new owner is the zero address"); _transferOwnership(newOwner); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Internal function without access restriction. */ function _transferOwnership(address newOwner) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol) pragma solidity ^0.8.0; /** * @dev Contract module that helps prevent reentrant calls to a function. * * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier * available, which can be applied to functions to make sure there are no nested * (reentrant) calls to them. * * Note that because there is a single `nonReentrant` guard, functions marked as * `nonReentrant` may not call one another. This can be worked around by making * those functions `private`, and then adding `external` `nonReentrant` entry * points to them. * * TIP: If you would like to learn more about reentrancy and alternative ways * to protect against it, check out our blog post * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul]. */ abstract contract ReentrancyGuard { // Booleans are more expensive than uint256 or any type that takes up a full // word because each write operation emits an extra SLOAD to first read the // slot's contents, replace the bits taken up by the boolean, and then write // back. This is the compiler's defense against contract upgrades and // pointer aliasing, and it cannot be disabled. // The values being non-zero value makes deployment a bit more expensive, // but in exchange the refund on every call to nonReentrant will be lower in // amount. Since refunds are capped to a percentage of the total // transaction's gas, it is best to keep them low in cases like this one, to // increase the likelihood of the full refund coming into effect. uint256 private constant _NOT_ENTERED = 1; uint256 private constant _ENTERED = 2; uint256 private _status; constructor() { _status = _NOT_ENTERED; } /** * @dev Prevents a contract from calling itself, directly or indirectly. * Calling a `nonReentrant` function from another `nonReentrant` * function is not supported. It is possible to prevent this from happening * by making the `nonReentrant` function external, and making it call a * `private` function that does the actual work. */ modifier nonReentrant() { _nonReentrantBefore(); _; _nonReentrantAfter(); } function _nonReentrantBefore() private { // On the first call to nonReentrant, _status will be _NOT_ENTERED require(_status != _ENTERED, "ReentrancyGuard: reentrant call"); // Any calls to nonReentrant after this point will fail _status = _ENTERED; } function _nonReentrantAfter() private { // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = _NOT_ENTERED; } /** * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a * `nonReentrant` function in the call stack. */ function _reentrancyGuardEntered() internal view returns (bool) { return _status == _ENTERED; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/IERC1155Receiver.sol) pragma solidity ^0.8.0; import "../../utils/introspection/IERC165.sol"; /** * @dev _Available since v3.1._ */ interface IERC1155Receiver is IERC165 { /** * @dev Handles the receipt of a single ERC1155 token type. This function is * called at the end of a `safeTransferFrom` after the balance has been updated. * * NOTE: To accept the transfer, this must return * `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` * (i.e. 0xf23a6e61, or its own function selector). * * @param operator The address which initiated the transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param id The ID of the token being transferred * @param value The amount of tokens being transferred * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed */ function onERC1155Received( address operator, address from, uint256 id, uint256 value, bytes calldata data ) external returns (bytes4); /** * @dev Handles the receipt of a multiple ERC1155 token types. This function * is called at the end of a `safeBatchTransferFrom` after the balances have * been updated. * * NOTE: To accept the transfer(s), this must return * `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` * (i.e. 0xbc197c81, or its own function selector). * * @param operator The address which initiated the batch transfer (i.e. msg.sender) * @param from The address which previously owned the token * @param ids An array containing ids of each token being transferred (order and length must match values array) * @param values An array containing amounts of each token being transferred (order and length must match ids array) * @param data Additional data with no specified format * @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed */ function onERC1155BatchReceived( address operator, address from, uint256[] calldata ids, uint256[] calldata values, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.5.0) (token/ERC1155/utils/ERC1155Holder.sol) pragma solidity ^0.8.0; import "./ERC1155Receiver.sol"; /** * Simple implementation of `ERC1155Receiver` that will allow a contract to hold ERC1155 tokens. * * IMPORTANT: When inheriting this contract, you must include a way to use the received tokens, otherwise they will be * stuck. * * @dev _Available since v3.1._ */ contract ERC1155Holder is ERC1155Receiver { function onERC1155Received( address, address, uint256, uint256, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155Received.selector; } function onERC1155BatchReceived( address, address, uint256[] memory, uint256[] memory, bytes memory ) public virtual override returns (bytes4) { return this.onERC1155BatchReceived.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (token/ERC1155/utils/ERC1155Receiver.sol) pragma solidity ^0.8.0; import "../IERC1155Receiver.sol"; import "../../../utils/introspection/ERC165.sol"; /** * @dev _Available since v3.1._ */ abstract contract ERC1155Receiver is ERC165, IERC1155Receiver { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { return interfaceId == type(IERC1155Receiver).interfaceId || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol) pragma solidity ^0.8.0; /** * @title ERC721 token receiver interface * @dev Interface for any contract that wants to support safeTransfers * from ERC721 asset contracts. */ interface IERC721Receiver { /** * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom} * by `operator` from `from`, this function is called. * * It must return its Solidity selector to confirm the token transfer. * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted. * * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received( address operator, address from, uint256 tokenId, bytes calldata data ) external returns (bytes4); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/utils/ERC721Holder.sol) pragma solidity ^0.8.0; import "../IERC721Receiver.sol"; /** * @dev Implementation of the {IERC721Receiver} interface. * * Accepts all token transfers. * Make sure the contract is able to use its token with {IERC721-safeTransferFrom}, {IERC721-approve} or {IERC721-setApprovalForAll}. */ contract ERC721Holder is IERC721Receiver { /** * @dev See {IERC721Receiver-onERC721Received}. * * Always returns `IERC721Receiver.onERC721Received.selector`. */ function onERC721Received(address, address, uint256, bytes memory) public virtual override returns (bytes4) { return this.onERC721Received.selector; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/Context.sol) pragma solidity ^0.8.0; /** * @dev Provides information about the current execution context, including the * sender of the transaction and its data. While these are generally available * via msg.sender and msg.data, they should not be accessed in such a direct * manner, since when dealing with meta-transactions the account sending and * paying for execution may not be the actual sender (as far as an application * is concerned). * * This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) pragma solidity ^0.8.8; /// @title Canonical Machine Constants Library /// /// @notice Defines several constants related to the reference implementation /// of the RISC-V machine that runs Linux, also known as the "Cartesi Machine". library CanonicalMachine { /// @notice Base-2 logarithm of number of bytes. type Log2Size is uint64; /// @notice Machine word size (8 bytes). Log2Size constant WORD_LOG2_SIZE = Log2Size.wrap(3); /// @notice Machine address space size (2^64 bytes). Log2Size constant MACHINE_LOG2_SIZE = Log2Size.wrap(64); /// @notice Keccak-256 output size (32 bytes). Log2Size constant KECCAK_LOG2_SIZE = Log2Size.wrap(5); /// @notice Maximum input size (~2 megabytes). /// @dev The offset and size fields use up the extra 64 bytes. uint256 constant INPUT_MAX_SIZE = (1 << 21) - 64; /// @notice Maximum voucher metadata memory range (2 megabytes). Log2Size constant VOUCHER_METADATA_LOG2_SIZE = Log2Size.wrap(21); /// @notice Maximum notice metadata memory range (2 megabytes). Log2Size constant NOTICE_METADATA_LOG2_SIZE = Log2Size.wrap(21); /// @notice Maximum epoch voucher memory range (128 megabytes). Log2Size constant EPOCH_VOUCHER_LOG2_SIZE = Log2Size.wrap(37); /// @notice Maximum epoch notice memory range (128 megabytes). Log2Size constant EPOCH_NOTICE_LOG2_SIZE = Log2Size.wrap(37); /// @notice Unwrap `s` into its underlying uint64 value. /// @param s Base-2 logarithm of some number of bytes function uint64OfSize(Log2Size s) internal pure returns (uint64) { return Log2Size.unwrap(s); } /// @notice Return the position of an intra memory range on a memory range /// with contents with the same size. /// @param index Index of intra memory range /// @param log2Size Base-2 logarithm of intra memory range size function getIntraMemoryRangePosition( uint64 index, Log2Size log2Size ) internal pure returns (uint64) { return index << Log2Size.unwrap(log2Size); } }
// (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) pragma solidity ^0.8.8; /// @title Output Encoding Library /// /// @notice Defines the encoding of outputs generated by the off-chain machine. library OutputEncoding { /// @notice Encode a notice. /// @param notice The notice /// @return The encoded output function encodeNotice( bytes calldata notice ) internal pure returns (bytes memory) { return abi.encode(notice); } /// @notice Encode a voucher. /// @param destination The address that will receive the payload through a message call /// @param payload The payload, which—in the case of Solidity contracts—encodes a function call /// @return The encoded output function encodeVoucher( address destination, bytes calldata payload ) internal pure returns (bytes memory) { return abi.encode(destination, payload); } }
// (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) pragma solidity ^0.8.8; /// @title Consensus interface /// /// @notice This contract defines a generic interface for consensuses. /// We use the word "consensus" to designate a contract that provides claims /// in the base layer regarding the state of off-chain machines running in /// the execution layer. How this contract is able to reach consensus, who is /// able to submit claims, and how are claims stored in the base layer are /// some of the implementation details left unspecified by this interface. /// /// From the point of view of a DApp, these claims are necessary to validate /// on-chain action allowed by the off-chain machine in the form of vouchers /// and notices. Each claim is composed of three parts: an epoch hash, a first /// index, and a last index. We'll explain each of these parts below. /// /// First, let us define the word "epoch". For finality reasons, we need to /// divide the stream of inputs being fed into the off-chain machine into /// batches of inputs, which we call "epoches". At the end of every epoch, /// we summarize the state of the off-chain machine in a single hash, called /// "epoch hash". Please note that this interface does not define how this /// stream of inputs is being chopped up into epoches. /// /// The other two parts are simply the indices of the first and last inputs /// accepted during the epoch. Logically, the first index MUST BE less than /// or equal to the last index. As a result, every epoch MUST accept at least /// one input. This assumption stems from the fact that the state of a machine /// can only change after an input is fed into it. /// /// Examples of possible implementations of this interface include: /// /// * An authority consensus, controlled by a single address who has full /// control over epoch boundaries, claim submission, asset management, etc. /// /// * A quorum consensus, controlled by a limited set of validators, that /// vote on the state of the machine at the end of every epoch. Also, epoch /// boundaries are determined by the timestamp in the base layer, and assets /// are split equally amongst the validators. /// /// * An NxN consensus, which allows anyone to submit and dispute claims /// in the base layer. Epoch boundaries are determined in the same fashion /// as in the quorum example. /// interface IConsensus { /// @notice An application has joined the consensus' validation set. /// @param application The application /// @dev MUST be triggered on a successful call to `join`. event ApplicationJoined(address application); /// @notice Get a specific claim regarding a specific DApp. /// The encoding of `_proofContext` might vary /// depending on the implementation. /// @param _dapp The DApp address /// @param _proofContext Data for retrieving the desired claim /// @return epochHash_ The claimed epoch hash /// @return firstInputIndex_ The index of the first input of the epoch in the input box /// @return lastInputIndex_ The index of the last input of the epoch in the input box function getClaim( address _dapp, bytes calldata _proofContext ) external view returns ( bytes32 epochHash_, uint256 firstInputIndex_, uint256 lastInputIndex_ ); /// @notice Signal the consensus that the message sender wants to join its validation set. /// @dev MUST fire an `ApplicationJoined` event with the message sender as argument. function join() external; }
// (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) pragma solidity ^0.8.8; import {IConsensus} from "../consensus/IConsensus.sol"; import {OutputValidityProof} from "../library/LibOutputValidation.sol"; /// @notice Data for validating outputs. /// @param validity A validity proof for the output /// @param context Data for querying the right claim from the current consensus contract /// @dev The encoding of `context` might vary depending on the implementation of the consensus contract. struct Proof { OutputValidityProof validity; bytes context; } /// @title Cartesi DApp interface interface ICartesiDApp { // Events /// @notice The DApp has migrated to another consensus contract. /// @param newConsensus The new consensus contract /// @dev MUST be triggered on a successful call to `migrateToConsensus`. event NewConsensus(IConsensus newConsensus); /// @notice A voucher was executed from the DApp. /// @param voucherId A number that uniquely identifies the voucher /// amongst all vouchers emitted by this DApp event VoucherExecuted(uint256 voucherId); // Permissioned functions /// @notice Migrate the DApp to a new consensus. /// @param _newConsensus The new consensus /// @dev Can only be called by the DApp owner. function migrateToConsensus(IConsensus _newConsensus) external; // Permissionless functions /// @notice Try to execute a voucher. /// /// Reverts if voucher was already successfully executed. /// /// @param _destination The address that will receive the payload through a message call /// @param _payload The payload, which—in the case of Solidity contracts—encodes a function call /// @param _proof The proof used to validate the voucher against /// a claim submitted by the current consensus contract /// @return Whether the execution was successful or not /// @dev On a successful execution, emits a `VoucherExecuted` event. /// Execution of already executed voucher will raise a `VoucherReexecutionNotAllowed` error. function executeVoucher( address _destination, bytes calldata _payload, Proof calldata _proof ) external returns (bool); /// @notice Check whether a voucher has been executed. /// @param _inputIndex The index of the input in the input box /// @param _outputIndexWithinInput The index of output emitted by the input /// @return Whether the voucher has been executed before function wasVoucherExecuted( uint256 _inputIndex, uint256 _outputIndexWithinInput ) external view returns (bool); /// @notice Validate a notice. /// @param _notice The notice /// @param _proof Data for validating outputs /// @return Whether the notice is valid or not function validateNotice( bytes calldata _notice, Proof calldata _proof ) external view returns (bool); /// @notice Get the DApp's template hash. /// @return The DApp's template hash function getTemplateHash() external view returns (bytes32); /// @notice Get the current consensus. /// @return The current consensus function getConsensus() external view returns (IConsensus); }
// (c) Cartesi and individual authors (see AUTHORS) // SPDX-License-Identifier: Apache-2.0 (see LICENSE) pragma solidity ^0.8.8; import {CanonicalMachine} from "../common/CanonicalMachine.sol"; import {MerkleV2} from "@cartesi/util/contracts/MerkleV2.sol"; import {OutputEncoding} from "../common/OutputEncoding.sol"; /// @param inputIndexWithinEpoch Which input, inside the epoch, the output belongs to /// @param outputIndexWithinInput Index of output emitted by the input /// @param outputHashesRootHash Merkle root of hashes of outputs emitted by the input /// @param vouchersEpochRootHash Merkle root of all epoch's voucher metadata hashes /// @param noticesEpochRootHash Merkle root of all epoch's notice metadata hashes /// @param machineStateHash Hash of the machine state claimed this epoch /// @param outputHashInOutputHashesSiblings Proof that this output metadata is in metadata memory range /// @param outputHashesInEpochSiblings Proof that this output metadata is in epoch's output memory range struct OutputValidityProof { uint64 inputIndexWithinEpoch; uint64 outputIndexWithinInput; bytes32 outputHashesRootHash; bytes32 vouchersEpochRootHash; bytes32 noticesEpochRootHash; bytes32 machineStateHash; bytes32[] outputHashInOutputHashesSiblings; bytes32[] outputHashesInEpochSiblings; } /// @title Output Validation Library library LibOutputValidation { using CanonicalMachine for CanonicalMachine.Log2Size; /// @notice Raised when some `OutputValidityProof` variables does not match /// the presented finalized epoch. error IncorrectEpochHash(); /// @notice Raised when `OutputValidityProof` metadata memory range is NOT /// contained in epoch's output memory range. error IncorrectOutputsEpochRootHash(); /// @notice Raised when Merkle root of output hash is NOT contained /// in the output metadata array memory range. error IncorrectOutputHashesRootHash(); /// @notice Raised when epoch input index is NOT compatible with the /// provided input index range. error InputIndexOutOfClaimBounds(); /// @notice Make sure the output proof is valid, otherwise revert. /// @param v The output validity proof /// @param encodedOutput The encoded output /// @param epochHash The hash of the epoch in which the output was generated /// @param outputsEpochRootHash Either `v.vouchersEpochRootHash` (for vouchers) /// or `v.noticesEpochRootHash` (for notices) /// @param outputEpochLog2Size Either `EPOCH_VOUCHER_LOG2_SIZE` (for vouchers) /// or `EPOCH_NOTICE_LOG2_SIZE` (for notices) /// @param outputHashesLog2Size Either `VOUCHER_METADATA_LOG2_SIZE` (for vouchers) /// or `NOTICE_METADATA_LOG2_SIZE` (for notices) function validateEncodedOutput( OutputValidityProof calldata v, bytes memory encodedOutput, bytes32 epochHash, bytes32 outputsEpochRootHash, uint256 outputEpochLog2Size, uint256 outputHashesLog2Size ) internal pure { // prove that outputs hash is represented in a finalized epoch if ( keccak256( abi.encodePacked( v.vouchersEpochRootHash, v.noticesEpochRootHash, v.machineStateHash ) ) != epochHash ) { revert IncorrectEpochHash(); } // prove that output metadata memory range is contained in epoch's output memory range if ( MerkleV2.getRootAfterReplacementInDrive( CanonicalMachine.getIntraMemoryRangePosition( v.inputIndexWithinEpoch, CanonicalMachine.KECCAK_LOG2_SIZE ), CanonicalMachine.KECCAK_LOG2_SIZE.uint64OfSize(), outputEpochLog2Size, v.outputHashesRootHash, v.outputHashesInEpochSiblings ) != outputsEpochRootHash ) { revert IncorrectOutputsEpochRootHash(); } // The hash of the output is converted to bytes (abi.encode) and // treated as data. The metadata output memory range stores that data while // being indifferent to its contents. To prove that the received // output is contained in the metadata output memory range we need to // prove that x, where: // x = keccak( // keccak( // keccak(hashOfOutput[0:7]), // keccak(hashOfOutput[8:15]) // ), // keccak( // keccak(hashOfOutput[16:23]), // keccak(hashOfOutput[24:31]) // ) // ) // is contained in it. We can't simply use hashOfOutput because the // log2size of the leaf is three (8 bytes) not five (32 bytes) bytes32 merkleRootOfHashOfOutput = MerkleV2.getMerkleRootFromBytes( abi.encodePacked(keccak256(encodedOutput)), CanonicalMachine.KECCAK_LOG2_SIZE.uint64OfSize() ); // prove that Merkle root of bytes(hashOfOutput) is contained // in the output metadata array memory range if ( MerkleV2.getRootAfterReplacementInDrive( CanonicalMachine.getIntraMemoryRangePosition( v.outputIndexWithinInput, CanonicalMachine.KECCAK_LOG2_SIZE ), CanonicalMachine.KECCAK_LOG2_SIZE.uint64OfSize(), outputHashesLog2Size, merkleRootOfHashOfOutput, v.outputHashInOutputHashesSiblings ) != v.outputHashesRootHash ) { revert IncorrectOutputHashesRootHash(); } } /// @notice Make sure the output proof is valid, otherwise revert. /// @param v The output validity proof /// @param destination The address that will receive the payload through a message call /// @param payload The payload, which—in the case of Solidity contracts—encodes a function call /// @param epochHash The hash of the epoch in which the output was generated function validateVoucher( OutputValidityProof calldata v, address destination, bytes calldata payload, bytes32 epochHash ) internal pure { bytes memory encodedVoucher = OutputEncoding.encodeVoucher( destination, payload ); validateEncodedOutput( v, encodedVoucher, epochHash, v.vouchersEpochRootHash, CanonicalMachine.EPOCH_VOUCHER_LOG2_SIZE.uint64OfSize(), CanonicalMachine.VOUCHER_METADATA_LOG2_SIZE.uint64OfSize() ); } /// @notice Make sure the output proof is valid, otherwise revert. /// @param v The output validity proof /// @param notice The notice /// @param epochHash The hash of the epoch in which the output was generated function validateNotice( OutputValidityProof calldata v, bytes calldata notice, bytes32 epochHash ) internal pure { bytes memory encodedNotice = OutputEncoding.encodeNotice(notice); validateEncodedOutput( v, encodedNotice, epochHash, v.noticesEpochRootHash, CanonicalMachine.EPOCH_NOTICE_LOG2_SIZE.uint64OfSize(), CanonicalMachine.NOTICE_METADATA_LOG2_SIZE.uint64OfSize() ); } /// @notice Get the position of a voucher on the bit mask. /// @param voucher The index of voucher from those generated by such input /// @param input The index of the input in the DApp's input box /// @return Position of the voucher on the bit mask function getBitMaskPosition( uint256 voucher, uint256 input ) internal pure returns (uint256) { // voucher * 2 ** 128 + input // this shouldn't overflow because it is impossible to have > 2**128 vouchers // and because we are assuming there will be < 2 ** 128 inputs on the input box return (((voucher << 128) | input)); } /// @notice Validate input index range and get the input index. /// @param v The output validity proof /// @param firstInputIndex The index of the first input of the epoch in the input box /// @param lastInputIndex The index of the last input of the epoch in the input box /// @return The index of the input in the DApp's input box /// @dev Reverts if epoch input index is not compatible with the provided input index range. function validateInputIndexRange( OutputValidityProof calldata v, uint256 firstInputIndex, uint256 lastInputIndex ) internal pure returns (uint256) { uint256 inputIndex = firstInputIndex + v.inputIndexWithinEpoch; if (inputIndex > lastInputIndex) { revert InputIndexOutOfClaimBounds(); } return inputIndex; } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "metadata": { "useLiteralContent": true }, "libraries": { "@cartesi/util/contracts/Bitmask.sol": { "Bitmask": "0xf5b2d8c81cde4d6238bbf20d3d77db37df13f735" }, "@cartesi/util/contracts/MerkleV2.sol": { "MerkleV2": "0x33436035441927df1a73fe3aac5906854632e53d" } } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"inputs":[{"internalType":"contract IConsensus","name":"_consensus","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"bytes32","name":"_templateHash","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EtherTransferFailed","type":"error"},{"inputs":[],"name":"IncorrectEpochHash","type":"error"},{"inputs":[],"name":"IncorrectOutputHashesRootHash","type":"error"},{"inputs":[],"name":"IncorrectOutputsEpochRootHash","type":"error"},{"inputs":[],"name":"InputIndexOutOfClaimBounds","type":"error"},{"inputs":[],"name":"OnlyDApp","type":"error"},{"inputs":[],"name":"VoucherReexecutionNotAllowed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract IConsensus","name":"newConsensus","type":"address"}],"name":"NewConsensus","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"voucherId","type":"uint256"}],"name":"VoucherExecuted","type":"event"},{"inputs":[{"internalType":"address","name":"_destination","type":"address"},{"internalType":"bytes","name":"_payload","type":"bytes"},{"components":[{"components":[{"internalType":"uint64","name":"inputIndexWithinEpoch","type":"uint64"},{"internalType":"uint64","name":"outputIndexWithinInput","type":"uint64"},{"internalType":"bytes32","name":"outputHashesRootHash","type":"bytes32"},{"internalType":"bytes32","name":"vouchersEpochRootHash","type":"bytes32"},{"internalType":"bytes32","name":"noticesEpochRootHash","type":"bytes32"},{"internalType":"bytes32","name":"machineStateHash","type":"bytes32"},{"internalType":"bytes32[]","name":"outputHashInOutputHashesSiblings","type":"bytes32[]"},{"internalType":"bytes32[]","name":"outputHashesInEpochSiblings","type":"bytes32[]"}],"internalType":"struct OutputValidityProof","name":"validity","type":"tuple"},{"internalType":"bytes","name":"context","type":"bytes"}],"internalType":"struct Proof","name":"_proof","type":"tuple"}],"name":"executeVoucher","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getConsensus","outputs":[{"internalType":"contract IConsensus","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getTemplateHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract IConsensus","name":"_newConsensus","type":"address"}],"name":"migrateToConsensus","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC721Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"_notice","type":"bytes"},{"components":[{"components":[{"internalType":"uint64","name":"inputIndexWithinEpoch","type":"uint64"},{"internalType":"uint64","name":"outputIndexWithinInput","type":"uint64"},{"internalType":"bytes32","name":"outputHashesRootHash","type":"bytes32"},{"internalType":"bytes32","name":"vouchersEpochRootHash","type":"bytes32"},{"internalType":"bytes32","name":"noticesEpochRootHash","type":"bytes32"},{"internalType":"bytes32","name":"machineStateHash","type":"bytes32"},{"internalType":"bytes32[]","name":"outputHashInOutputHashesSiblings","type":"bytes32[]"},{"internalType":"bytes32[]","name":"outputHashesInEpochSiblings","type":"bytes32[]"}],"internalType":"struct OutputValidityProof","name":"validity","type":"tuple"},{"internalType":"bytes","name":"context","type":"bytes"}],"internalType":"struct Proof","name":"_proof","type":"tuple"}],"name":"validateNotice","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_inputIndex","type":"uint256"},{"internalType":"uint256","name":"_outputIndexWithinInput","type":"uint256"}],"name":"wasVoucherExecuted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_receiver","type":"address"},{"internalType":"uint256","name":"_value","type":"uint256"}],"name":"withdrawEther","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]
Contract Creation Code
60a06040523480156200001157600080fd5b506040516200171038038062001710833981016040819052620000349162000212565b6200003f33620000cb565b600180556200004e826200011b565b6080819052600380546001600160a01b0319166001600160a01b0385169081179091556040805163b688a36360e01b8152905163b688a3639160048082019260009290919082900301818387803b158015620000a957600080fd5b505af1158015620000be573d6000803e3d6000fd5b505050505050506200025a565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b620001256200019e565b6001600160a01b038116620001905760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6200019b81620000cb565b50565b6000546001600160a01b03163314620001fa5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640162000187565b565b6001600160a01b03811681146200019b57600080fd5b6000806000606084860312156200022857600080fd5b83516200023581620001fc565b60208501519093506200024881620001fc565b80925050604084015190509250925092565b60805161149a6200027660003960006101ec015261149a6000f3fe6080604052600436106100e15760003560e01c80638da5cb5b1161007f578063bc197c8111610059578063bc197c8114610288578063f23a6e61146102b4578063f2fde38b146102e0578063fc4116831461030057600080fd5b80638da5cb5b1461022a57806396487d46146102485780639d9b11451461026857600080fd5b8063179e740b116100bb578063179e740b14610186578063522f6815146101b857806361b12c66146101da578063715018a61461021557600080fd5b806301ffc9a7146100ed5780631250482f14610122578063150b7a021461014257600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004610d2a565b610320565b60405190151581526020015b60405180910390f35b34801561012e57600080fd5b5061010d61013d366004610dd0565b610357565b34801561014e57600080fd5b5061016d61015d366004610f00565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610119565b34801561019257600080fd5b506003546001600160a01b03165b6040516001600160a01b039091168152602001610119565b3480156101c457600080fd5b506101d86101d3366004610f5f565b61053c565b005b3480156101e657600080fd5b506040517f00000000000000000000000000000000000000000000000000000000000000008152602001610119565b34801561022157600080fd5b506101d86105d5565b34801561023657600080fd5b506000546001600160a01b03166101a0565b34801561025457600080fd5b5061010d610263366004610f8b565b6105e9565b34801561027457600080fd5b5061010d610283366004610ff3565b61063a565b34801561029457600080fd5b5061016d6102a3366004611094565b63bc197c8160e01b95945050505050565b3480156102c057600080fd5b5061016d6102cf366004611141565b63f23a6e6160e01b95945050505050565b3480156102ec57600080fd5b506101d86102fb3660046111a9565b61064c565b34801561030c57600080fd5b506101d861031b3660046111a9565b6106ca565b60006001600160e01b03198216630271189760e51b148061035157506301ffc9a760e01b6001600160e01b03198316145b92915050565b600061036161077f565b600080808061037b61037660208801886111c6565b6107d8565b919550935091506103988383610391898061120c565b919061085f565b90506103b4898989876103ab8b8061120c565b939291906108a5565b60006103e86103c3888061120c565b6103d490604081019060200161122c565b6001600160401b03168360809190911b1790565b90506103f3816108da565b15610411576040516370de22b760e01b815260040160405180910390fd5b60008a6001600160a01b03168a8a60405161042d929190611255565b6000604051808303816000865af19150503d806000811461046a576040519150601f19603f3d011682016040523d82523d6000602084013e61046f565b606091505b505090508015610524576040516306449da160e41b815260026004820152602481018390526001604482015273f5b2d8c81cde4d6238bbf20d3d77db37df13f73590636449da109060640160006040518083038186803b1580156104d257600080fd5b505af41580156104e6573d6000803e3d6000fd5b505050507f0eb7ee080f865f1cadc4f54daf58cc3b8879e888832867d13351edcec0fbdc548260405161051b91815260200190565b60405180910390a15b9550505050505061053460018055565b949350505050565b33301461055c5760405163a08d601d60e01b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146105a9576040519150601f19603f3d011682016040523d82523d6000602084013e6105ae565b606091505b50509050806105d057604051630ce8f45160e31b815260040160405180910390fd5b505050565b6105dd610958565b6105e760006109b2565b565b60008080806105fe61037660208701876111c6565b919450925090506106148282610391888061120c565b5061062d878785610625898061120c565b929190610a02565b5060019695505050505050565b6000608082901b8317610534816108da565b610654610958565b6001600160a01b0381166106be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6106c7816109b2565b50565b6106d2610958565b600380546001600160a01b0319166001600160a01b0383169081179091556040805163b688a36360e01b8152905163b688a3639160048082019260009290919082900301818387803b15801561072757600080fd5b505af115801561073b573d6000803e3d6000fd5b50506040516001600160a01b03841681527f4991c6f37185659e276ff918a96f3e20e6c5abcd8c9aab450dc19c2f7ad35cb59250602001905060405180910390a150565b6002600154036107d15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106b5565b6002600155565b60035460405163035e6a0960e61b8152600091829182916001600160a01b03169063d79a8240906108119030908990899060040161128e565b606060405180830381865afa15801561082e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085291906112bc565b9250925092509250925092565b60008061086f602086018661122c565b610882906001600160401b0316856112ea565b9050828111156105345760405163fd9ae91f60e01b815260040160405180910390fd5b60006108b2858585610a29565b90506108d2868284606083013560255b6001600160401b03166015610a58565b505050505050565b6040516303fbaf7360e01b8152600260048201526024810182905260009073f5b2d8c81cde4d6238bbf20d3d77db37df13f735906303fbaf7390604401602060405180830381865af4158015610934573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610351919061130b565b6000546001600160a01b031633146105e75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610a0e8484610cfe565b9050610a22858284608083013560256108c2565b5050505050565b6060838383604051602001610a409392919061128e565b60405160208183030381529060405290509392505050565b6040805160608089013560208301526080808a01359383019390935260a0890135908201528591016040516020818303038152906040528051906020012014610ab457604051636fbd3b7160e11b815260040160405180910390fd5b827333436035441927df1a73fe3aac5906854632e53d6379de4601610af0610adf60208b018b61122c565b60051b681fffffffffffffffe01690565b60058660408c0135610b0560e08e018e61132d565b6040518763ffffffff1660e01b8152600401610b2696959493929190611376565b602060405180830381865af4158015610b43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6791906113d9565b14610b8557604051634371daa160e11b815260040160405180910390fd5b60007333436035441927df1a73fe3aac5906854632e53d63c84583a18780519060200120604051602001610bbb91815260200190565b60408051601f19818403018152908290526001600160e01b031960e084901b168252610bec916005906004016113f2565b602060405180830381865af4158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906113d9565b905086604001357333436035441927df1a73fe3aac5906854632e53d6379de4601610c648a6020016020810190610adf919061122c565b60058686610c7560c08f018f61132d565b6040518763ffffffff1660e01b8152600401610c9696959493929190611376565b602060405180830381865af4158015610cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd791906113d9565b14610cf55760405163017c689560e61b815260040160405180910390fd5b50505050505050565b60608282604051602001610d13929190611450565b604051602081830303815290604052905092915050565b600060208284031215610d3c57600080fd5b81356001600160e01b031981168114610d5457600080fd5b9392505050565b6001600160a01b03811681146106c757600080fd5b60008083601f840112610d8257600080fd5b5081356001600160401b03811115610d9957600080fd5b602083019150836020828501011115610db157600080fd5b9250929050565b600060408284031215610dca57600080fd5b50919050565b60008060008060608587031215610de657600080fd5b8435610df181610d5b565b935060208501356001600160401b0380821115610e0d57600080fd5b610e1988838901610d70565b90955093506040870135915080821115610e3257600080fd5b50610e3f87828801610db8565b91505092959194509250565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715610e8957610e89610e4b565b604052919050565b600082601f830112610ea257600080fd5b81356001600160401b03811115610ebb57610ebb610e4b565b610ece601f8201601f1916602001610e61565b818152846020838601011115610ee357600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215610f1657600080fd5b8435610f2181610d5b565b93506020850135610f3181610d5b565b92506040850135915060608501356001600160401b03811115610f5357600080fd5b610e3f87828801610e91565b60008060408385031215610f7257600080fd5b8235610f7d81610d5b565b946020939093013593505050565b600080600060408486031215610fa057600080fd5b83356001600160401b0380821115610fb757600080fd5b610fc387838801610d70565b90955093506020860135915080821115610fdc57600080fd5b50610fe986828701610db8565b9150509250925092565b6000806040838503121561100657600080fd5b50508035926020909101359150565b600082601f83011261102657600080fd5b813560206001600160401b0382111561104157611041610e4b565b8160051b611050828201610e61565b928352848101820192828101908785111561106a57600080fd5b83870192505b8483101561108957823582529183019190830190611070565b979650505050505050565b600080600080600060a086880312156110ac57600080fd5b85356110b781610d5b565b945060208601356110c781610d5b565b935060408601356001600160401b03808211156110e357600080fd5b6110ef89838a01611015565b9450606088013591508082111561110557600080fd5b61111189838a01611015565b9350608088013591508082111561112757600080fd5b5061113488828901610e91565b9150509295509295909350565b600080600080600060a0868803121561115957600080fd5b853561116481610d5b565b9450602086013561117481610d5b565b9350604086013592506060860135915060808601356001600160401b0381111561119d57600080fd5b61113488828901610e91565b6000602082840312156111bb57600080fd5b8135610d5481610d5b565b6000808335601e198436030181126111dd57600080fd5b8301803591506001600160401b038211156111f757600080fd5b602001915036819003821315610db157600080fd5b6000823560fe1983360301811261122257600080fd5b9190910192915050565b60006020828403121561123e57600080fd5b81356001600160401b0381168114610d5457600080fd5b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03841681526040602082018190526000906112b39083018486611265565b95945050505050565b6000806000606084860312156112d157600080fd5b8351925060208401519150604084015190509250925092565b8082018082111561035157634e487b7160e01b600052601160045260246000fd5b60006020828403121561131d57600080fd5b81518015158114610d5457600080fd5b6000808335601e1984360301811261134457600080fd5b8301803591506001600160401b0382111561135e57600080fd5b6020019150600581901b3603821315610db157600080fd5b6001600160401b03878116825286166020820152604081018590526060810184905260a060808201819052810182905260006001600160fb1b038311156113bc57600080fd5b8260051b808560c08501379190910160c001979650505050505050565b6000602082840312156113eb57600080fd5b5051919050565b604081526000835180604084015260005b818110156114205760208187018101516060868401015201611403565b506000606082850101526060601f19601f8301168401019150506001600160401b03831660208301529392505050565b60208152600061053460208301848661126556fea2646970667358221220981835fbbf44aedaeb41e0c0c9001ffe55187a0b5606db0cdbf7500fc7c5e30e64736f6c634300081300330000000000000000000000009db17b9426e6d3d517a969994e7addadbca9c45f0000000000000000000000000e28a8f88c6266df0fe274c15c1d4b27f8b373c064523866b6437fd593d8c0c65f88f59717f2eefa81422cc4921214423c819bf2
Deployed Bytecode
0x6080604052600436106100e15760003560e01c80638da5cb5b1161007f578063bc197c8111610059578063bc197c8114610288578063f23a6e61146102b4578063f2fde38b146102e0578063fc4116831461030057600080fd5b80638da5cb5b1461022a57806396487d46146102485780639d9b11451461026857600080fd5b8063179e740b116100bb578063179e740b14610186578063522f6815146101b857806361b12c66146101da578063715018a61461021557600080fd5b806301ffc9a7146100ed5780631250482f14610122578063150b7a021461014257600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004610d2a565b610320565b60405190151581526020015b60405180910390f35b34801561012e57600080fd5b5061010d61013d366004610dd0565b610357565b34801561014e57600080fd5b5061016d61015d366004610f00565b630a85bd0160e11b949350505050565b6040516001600160e01b03199091168152602001610119565b34801561019257600080fd5b506003546001600160a01b03165b6040516001600160a01b039091168152602001610119565b3480156101c457600080fd5b506101d86101d3366004610f5f565b61053c565b005b3480156101e657600080fd5b506040517f64523866b6437fd593d8c0c65f88f59717f2eefa81422cc4921214423c819bf28152602001610119565b34801561022157600080fd5b506101d86105d5565b34801561023657600080fd5b506000546001600160a01b03166101a0565b34801561025457600080fd5b5061010d610263366004610f8b565b6105e9565b34801561027457600080fd5b5061010d610283366004610ff3565b61063a565b34801561029457600080fd5b5061016d6102a3366004611094565b63bc197c8160e01b95945050505050565b3480156102c057600080fd5b5061016d6102cf366004611141565b63f23a6e6160e01b95945050505050565b3480156102ec57600080fd5b506101d86102fb3660046111a9565b61064c565b34801561030c57600080fd5b506101d861031b3660046111a9565b6106ca565b60006001600160e01b03198216630271189760e51b148061035157506301ffc9a760e01b6001600160e01b03198316145b92915050565b600061036161077f565b600080808061037b61037660208801886111c6565b6107d8565b919550935091506103988383610391898061120c565b919061085f565b90506103b4898989876103ab8b8061120c565b939291906108a5565b60006103e86103c3888061120c565b6103d490604081019060200161122c565b6001600160401b03168360809190911b1790565b90506103f3816108da565b15610411576040516370de22b760e01b815260040160405180910390fd5b60008a6001600160a01b03168a8a60405161042d929190611255565b6000604051808303816000865af19150503d806000811461046a576040519150601f19603f3d011682016040523d82523d6000602084013e61046f565b606091505b505090508015610524576040516306449da160e41b815260026004820152602481018390526001604482015273f5b2d8c81cde4d6238bbf20d3d77db37df13f73590636449da109060640160006040518083038186803b1580156104d257600080fd5b505af41580156104e6573d6000803e3d6000fd5b505050507f0eb7ee080f865f1cadc4f54daf58cc3b8879e888832867d13351edcec0fbdc548260405161051b91815260200190565b60405180910390a15b9550505050505061053460018055565b949350505050565b33301461055c5760405163a08d601d60e01b815260040160405180910390fd5b6000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146105a9576040519150601f19603f3d011682016040523d82523d6000602084013e6105ae565b606091505b50509050806105d057604051630ce8f45160e31b815260040160405180910390fd5b505050565b6105dd610958565b6105e760006109b2565b565b60008080806105fe61037660208701876111c6565b919450925090506106148282610391888061120c565b5061062d878785610625898061120c565b929190610a02565b5060019695505050505050565b6000608082901b8317610534816108da565b610654610958565b6001600160a01b0381166106be5760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201526564647265737360d01b60648201526084015b60405180910390fd5b6106c7816109b2565b50565b6106d2610958565b600380546001600160a01b0319166001600160a01b0383169081179091556040805163b688a36360e01b8152905163b688a3639160048082019260009290919082900301818387803b15801561072757600080fd5b505af115801561073b573d6000803e3d6000fd5b50506040516001600160a01b03841681527f4991c6f37185659e276ff918a96f3e20e6c5abcd8c9aab450dc19c2f7ad35cb59250602001905060405180910390a150565b6002600154036107d15760405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c0060448201526064016106b5565b6002600155565b60035460405163035e6a0960e61b8152600091829182916001600160a01b03169063d79a8240906108119030908990899060040161128e565b606060405180830381865afa15801561082e573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061085291906112bc565b9250925092509250925092565b60008061086f602086018661122c565b610882906001600160401b0316856112ea565b9050828111156105345760405163fd9ae91f60e01b815260040160405180910390fd5b60006108b2858585610a29565b90506108d2868284606083013560255b6001600160401b03166015610a58565b505050505050565b6040516303fbaf7360e01b8152600260048201526024810182905260009073f5b2d8c81cde4d6238bbf20d3d77db37df13f735906303fbaf7390604401602060405180830381865af4158015610934573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610351919061130b565b6000546001600160a01b031633146105e75760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657260448201526064016106b5565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b6000610a0e8484610cfe565b9050610a22858284608083013560256108c2565b5050505050565b6060838383604051602001610a409392919061128e565b60405160208183030381529060405290509392505050565b6040805160608089013560208301526080808a01359383019390935260a0890135908201528591016040516020818303038152906040528051906020012014610ab457604051636fbd3b7160e11b815260040160405180910390fd5b827333436035441927df1a73fe3aac5906854632e53d6379de4601610af0610adf60208b018b61122c565b60051b681fffffffffffffffe01690565b60058660408c0135610b0560e08e018e61132d565b6040518763ffffffff1660e01b8152600401610b2696959493929190611376565b602060405180830381865af4158015610b43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6791906113d9565b14610b8557604051634371daa160e11b815260040160405180910390fd5b60007333436035441927df1a73fe3aac5906854632e53d63c84583a18780519060200120604051602001610bbb91815260200190565b60408051601f19818403018152908290526001600160e01b031960e084901b168252610bec916005906004016113f2565b602060405180830381865af4158015610c09573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c2d91906113d9565b905086604001357333436035441927df1a73fe3aac5906854632e53d6379de4601610c648a6020016020810190610adf919061122c565b60058686610c7560c08f018f61132d565b6040518763ffffffff1660e01b8152600401610c9696959493929190611376565b602060405180830381865af4158015610cb3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cd791906113d9565b14610cf55760405163017c689560e61b815260040160405180910390fd5b50505050505050565b60608282604051602001610d13929190611450565b604051602081830303815290604052905092915050565b600060208284031215610d3c57600080fd5b81356001600160e01b031981168114610d5457600080fd5b9392505050565b6001600160a01b03811681146106c757600080fd5b60008083601f840112610d8257600080fd5b5081356001600160401b03811115610d9957600080fd5b602083019150836020828501011115610db157600080fd5b9250929050565b600060408284031215610dca57600080fd5b50919050565b60008060008060608587031215610de657600080fd5b8435610df181610d5b565b935060208501356001600160401b0380821115610e0d57600080fd5b610e1988838901610d70565b90955093506040870135915080821115610e3257600080fd5b50610e3f87828801610db8565b91505092959194509250565b634e487b7160e01b600052604160045260246000fd5b604051601f8201601f191681016001600160401b0381118282101715610e8957610e89610e4b565b604052919050565b600082601f830112610ea257600080fd5b81356001600160401b03811115610ebb57610ebb610e4b565b610ece601f8201601f1916602001610e61565b818152846020838601011115610ee357600080fd5b816020850160208301376000918101602001919091529392505050565b60008060008060808587031215610f1657600080fd5b8435610f2181610d5b565b93506020850135610f3181610d5b565b92506040850135915060608501356001600160401b03811115610f5357600080fd5b610e3f87828801610e91565b60008060408385031215610f7257600080fd5b8235610f7d81610d5b565b946020939093013593505050565b600080600060408486031215610fa057600080fd5b83356001600160401b0380821115610fb757600080fd5b610fc387838801610d70565b90955093506020860135915080821115610fdc57600080fd5b50610fe986828701610db8565b9150509250925092565b6000806040838503121561100657600080fd5b50508035926020909101359150565b600082601f83011261102657600080fd5b813560206001600160401b0382111561104157611041610e4b565b8160051b611050828201610e61565b928352848101820192828101908785111561106a57600080fd5b83870192505b8483101561108957823582529183019190830190611070565b979650505050505050565b600080600080600060a086880312156110ac57600080fd5b85356110b781610d5b565b945060208601356110c781610d5b565b935060408601356001600160401b03808211156110e357600080fd5b6110ef89838a01611015565b9450606088013591508082111561110557600080fd5b61111189838a01611015565b9350608088013591508082111561112757600080fd5b5061113488828901610e91565b9150509295509295909350565b600080600080600060a0868803121561115957600080fd5b853561116481610d5b565b9450602086013561117481610d5b565b9350604086013592506060860135915060808601356001600160401b0381111561119d57600080fd5b61113488828901610e91565b6000602082840312156111bb57600080fd5b8135610d5481610d5b565b6000808335601e198436030181126111dd57600080fd5b8301803591506001600160401b038211156111f757600080fd5b602001915036819003821315610db157600080fd5b6000823560fe1983360301811261122257600080fd5b9190910192915050565b60006020828403121561123e57600080fd5b81356001600160401b0381168114610d5457600080fd5b8183823760009101908152919050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6001600160a01b03841681526040602082018190526000906112b39083018486611265565b95945050505050565b6000806000606084860312156112d157600080fd5b8351925060208401519150604084015190509250925092565b8082018082111561035157634e487b7160e01b600052601160045260246000fd5b60006020828403121561131d57600080fd5b81518015158114610d5457600080fd5b6000808335601e1984360301811261134457600080fd5b8301803591506001600160401b0382111561135e57600080fd5b6020019150600581901b3603821315610db157600080fd5b6001600160401b03878116825286166020820152604081018590526060810184905260a060808201819052810182905260006001600160fb1b038311156113bc57600080fd5b8260051b808560c08501379190910160c001979650505050505050565b6000602082840312156113eb57600080fd5b5051919050565b604081526000835180604084015260005b818110156114205760208187018101516060868401015201611403565b506000606082850101526060601f19601f8301168401019150506001600160401b03831660208301529392505050565b60208152600061053460208301848661126556fea2646970667358221220981835fbbf44aedaeb41e0c0c9001ffe55187a0b5606db0cdbf7500fc7c5e30e64736f6c63430008130033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000009db17b9426e6d3d517a969994e7addadbca9c45f0000000000000000000000000e28a8f88c6266df0fe274c15c1d4b27f8b373c064523866b6437fd593d8c0c65f88f59717f2eefa81422cc4921214423c819bf2
-----Decoded View---------------
Arg [0] : _consensus (address): 0x9DB17B9426E6d3d517a969994E7ADDadbCa9C45f
Arg [1] : _owner (address): 0x0e28A8f88C6266dF0FE274c15c1d4b27f8B373C0
Arg [2] : _templateHash (bytes32): 0x64523866b6437fd593d8c0c65f88f59717f2eefa81422cc4921214423c819bf2
-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : 0000000000000000000000009db17b9426e6d3d517a969994e7addadbca9c45f
Arg [1] : 0000000000000000000000000e28a8f88c6266df0fe274c15c1d4b27f8b373c0
Arg [2] : 64523866b6437fd593d8c0c65f88f59717f2eefa81422cc4921214423c819bf2
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 31 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|---|---|---|---|---|
ETH | 100.00% | $0.110427 | 1,772,889 | $195,774.62 |
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.