diff --git a/echo-js/Dockerfile b/echo-js/Dockerfile new file mode 100644 index 00000000..84aa72f5 --- /dev/null +++ b/echo-js/Dockerfile @@ -0,0 +1,5 @@ +# syntax=docker.io/docker/dockerfile:1.4 +FROM cartesi/toolchain:0.10.0 as dapp-build + +WORKDIR /opt/cartesi/dapp +COPY . . diff --git a/echo-js/README.md b/echo-js/README.md new file mode 100644 index 00000000..be3048a3 --- /dev/null +++ b/echo-js/README.md @@ -0,0 +1,157 @@ +# echo-js DApp + +echo-js is a customized DApp written in Javascript, which originally resembles the one provided by the sample [Echo Python DApp](https://github.com/cartesi/rollups-examples/tree/main/echo-python). + +The documentation below reflects the original application code, and should also be used as a basis for documenting any DApp created with this mechanism. + +## Requirements + +Please refer to the [rollups-examples requirements](https://github.com/cartesi/rollups-examples/tree/main/README.md#requirements). + +## Building + +To build the application, run the following command: + +```shell +docker buildx bake -f docker-bake.hcl -f docker-bake.override.hcl --load +``` + +## Running + +To start the application, execute the following command: + +```shell +docker compose -f ../docker-compose.yml -f ./docker-compose.override.yml up +``` + +The application can afterwards be shut down with the following command: + +```shell +docker compose -f ../docker-compose.yml -f ./docker-compose.override.yml down -v +``` + +## Interacting with the application + +We can use the rollups-examples [frontend-console](https://github.com/cartesi/rollups-examples/tree/main/frontend-console) application to interact with the DApp. +Ensure that the [application has already been built](https://github.com/cartesi/rollups-examples/tree/main/frontend-console/README.md#building) before using it. + +From within the `frontend-console` directory, you can send an input as follows: + +```shell +yarn start send --input "Hello there" +``` + +In order to verify the notices generated by your inputs, run the command: + +```shell +yarn start notices +``` + +The response should be something like this: + +```shell +[ { epoch: '0', input: '1', notice: '0', payload: 'Hello there' } ] +``` + +## Deploying to a testnet + +Deploying the application to a blockchain requires creating a smart contract on that network, as well as running a validator node for the DApp. + +The first step is to build the DApp's back-end machine, which will produce a hash that serves as a unique identifier. + +```shell +docker buildx bake -f docker-bake.hcl -f docker-bake.override.hcl machine --load +``` + +Once the machine docker image is ready, we can use it to deploy a corresponding Rollups smart contract. This requires you to define a few environment variables to specify which network you are deploying to, which account to use, and which RPC gateway to use when submitting the deploy transaction. + +```shell +export NETWORK= +export MNEMONIC= +export RPC_URL= +``` + +For example, to deploy to the Goerli testnet using an Alchemy RPC node, you could execute: + +```shell +export NETWORK=goerli +export MNEMONIC= +export RPC_URL=https://eth-goerli.alchemyapi.io/v2/ +``` + +With that in place, you can submit a deploy transaction to the Cartesi DApp Factory contract on the target network by executing the following command: + +```shell +DAPP_NAME=echo-js docker compose -f ./deploy-testnet.yml up +``` + +This will create a file at `./deployments//echo-js.address` with the deployed contract's address. +Once the command finishes, it is advisable to stop the docker compose and remove the volumes created when executing it. + +```shell +DAPP_NAME=echo-js docker compose -f ./deploy-testnet.yml down -v +``` + +After that, a corresponding Cartesi Validator Node must also be instantiated in order to interact with the deployed smart contract on the target network and handle the back-end logic of the DApp. +Aside from the environment variables defined above, the node will also need a secure websocket endpoint for the RPC gateway (WSS URL) and the chain ID of the target network. + +For example, for Goerli and Alchemy, you would set the following additional variables: + +```shell +export WSS_URL=wss://eth-goerli.alchemyapi.io/v2/ +export CHAIN_ID=5 +``` + +Then, the node itself can be started by running a docker compose as follows: + +```shell +DAPP_NAME=mydapp docker compose -f ./docker-compose-testnet.yml -f ./docker-compose.override.yml up +``` + +## Interacting with the deployed application + +With the node running, you can interact with the deployed DApp using the [frontend-console](https://github.com/cartesi/rollups-examples/tree/main/frontend-console), as described [previously](#interacting-with-the-application). +This time, however, you need to specify the appropriate connectivity configurations. + +First of all, in the separate terminal for the frontend-console, define the `MNEMONIC` and `RPC_URL` variables as before: + +```shell +export MNEMONIC= +export RPC_URL= +``` + +Then, inputs can be sent by specifying the DApp contract's address, as follows: + +```shell +yarn start send --input "Hello there" --addressFile path/to/echo-js/deployments//echo-js.address +``` + +Resulting notices can then be retrieved by querying the local Cartesi Node, as before: + +```shell +yarn start notices +``` + +## Running the back-end in host mode + +When developing an application, it is often important to easily test and debug it. For that matter, it is possible to run the Cartesi Rollups environment in [host mode](https://github.com/cartesi/rollups-examples/tree/main/README.md#host-mode), so that the DApp's back-end can be executed directly on the host machine, allowing it to be debugged using regular development tools such as an IDE. + +This DApp's back-end is written in `Javascript` that using `QuickJS` engine, so to run it in your machine you need to have `QuickJS` installed. + +In order to start the back-end, run the following commands in a dedicated terminal: + +```shell +# DIR ../echo-js/ +ROLLUP_HTTP_SERVER_URL="http://127.0.0.1:5004" qjs server/src/echo-server.js +``` + +The final command will effectively run the back-end and send corresponding outputs to port `5004`. + +After the back-end successfully starts, it should print an output like the following: + +```log +HTTP rollup_server url is http://127.0.0.1:5004 +Sending finish +``` + +After that, you can interact with the application normally [as explained above](#interacting-with-the-application). diff --git a/echo-js/config/bs-config.toml b/echo-js/config/bs-config.toml new file mode 100644 index 00000000..2ae813e6 --- /dev/null +++ b/echo-js/config/bs-config.toml @@ -0,0 +1,10 @@ +[block_subscriber] + +# max delay between retries in seconds +max_delay = 64 + +# max number of retries +max_retries = 5 + +# timeout for block subscriber in seconds +timeout = 120 diff --git a/echo-js/config/indexer-config.toml b/echo-js/config/indexer-config.toml new file mode 100644 index 00000000..0ed19efa --- /dev/null +++ b/echo-js/config/indexer-config.toml @@ -0,0 +1,15 @@ +[indexer_config] + +# unique session identifier for machine manager +session_id = "default_rollups_id" + +# node starts syncing from inital epoch +initial_epoch = 0 + +# polling interval +interval = 10 + +# end points +postgres_endpoint = "postgres://postgres:password@database/postgres" +state_server_endpoint = "http://state_server:50051" +mm_endpoint = "http://server_manager:5001" diff --git a/echo-js/config/logic-config.toml b/echo-js/config/logic-config.toml new file mode 100644 index 00000000..46535525 --- /dev/null +++ b/echo-js/config/logic-config.toml @@ -0,0 +1,23 @@ +[logic_config] + +# unique session identifier for machine manager +session_id = "default_rollups_id" + +# node starts syncing from inital epoch +initial_epoch = 0 + +# gas estimation/price multiplier +gas_multiplier = 1 +gas_price_multiplier = 1 + +# number of blocks before resubmting tx +rate = 20 + +# depth of blocks before considering tx finalized +confirmations = 10 + +# end points +provider_http_endpoint = "http://hardhat:8545" +ws_endpoint = "ws://hardhat:8545" +state_fold_grpc_endpoint = "http://state_server:50051" +mm_endpoint = "http://server_manager:5001" diff --git a/echo-js/config/sf-config.toml b/echo-js/config/sf-config.toml new file mode 100644 index 00000000..a28d8eb8 --- /dev/null +++ b/echo-js/config/sf-config.toml @@ -0,0 +1,13 @@ +[state_fold] + +# concurrent events fetch for state fold access +concurrent_events_fetch = 16 + +# genesis block number for state fold access +genesis_block = "0x1" + +# query limit error for state fold access +query_limit_error_codes = [-32005] + +# number of blocks (depth) before considering state finalized +safety_margin = 0 diff --git a/echo-js/config/tm-config.toml b/echo-js/config/tm-config.toml new file mode 100644 index 00000000..24c5727f --- /dev/null +++ b/echo-js/config/tm-config.toml @@ -0,0 +1,10 @@ +[tx_manager] + +# max delay between retries in seconds +max_delay = 64 + +# max number of retries +max_retries = 5 + +# timeout for a sent transaction in seconds +transaction_timeout = 5 diff --git a/echo-js/dapp.json b/echo-js/dapp.json new file mode 100644 index 00000000..597c7969 --- /dev/null +++ b/echo-js/dapp.json @@ -0,0 +1,8 @@ +{ + "fs": { + "files": [ + "server", + "entrypoint.sh" + ] + } +} diff --git a/echo-js/deploy-testnet.yml b/echo-js/deploy-testnet.yml new file mode 100644 index 00000000..66596abf --- /dev/null +++ b/echo-js/deploy-testnet.yml @@ -0,0 +1,32 @@ +version: "3.9" + +services: + machine: + image: cartesi/dapp:${DAPP_NAME:?undefined DAPP_NAME}-devel-machine + command: xxd -c 256 -p hash; sleep 3 + volumes: + - machine:/opt/cartesi/share/dapp-bin + + deployer: + image: cartesi/rollups-cli:0.3.0 + depends_on: + machine: + condition: service_started + command: + [ + "create", + "--rpc", + "${RPC_URL:?undefined RPC_URL}", + "--mnemonic", + "${MNEMONIC:?undefined MNEMONIC}", + "--templateHashFile", + "/opt/cartesi/share/dapp-bin/hash", + "--outputFile", + "/deployments/${NETWORK:?undefined NETWORK}/${DAPP_NAME:?undefined DAPP_NAME}.address", + ] + volumes: + - machine:/opt/cartesi/share/dapp-bin:ro + - ./deployments:/deployments + +volumes: + machine: {} diff --git a/echo-js/deployments/localhost/.chainId b/echo-js/deployments/localhost/.chainId new file mode 100644 index 00000000..027791f4 --- /dev/null +++ b/echo-js/deployments/localhost/.chainId @@ -0,0 +1 @@ +31337 \ No newline at end of file diff --git a/echo-js/deployments/localhost/Bank.json b/echo-js/deployments/localhost/Bank.json new file mode 100644 index 00000000..175fe87c --- /dev/null +++ b/echo-js/deployments/localhost/Bank.json @@ -0,0 +1,239 @@ +{ + "address": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_token", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Deposit", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "depositTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getToken", + "outputs": [ + { + "internalType": "contract IERC20", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "transferTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xc21d4634243103d1e2f07d9000244ebab6b75ffa6b0728b40c5d0eb554af2a65", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E", + "transactionIndex": 0, + "gasUsed": "337439", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3f9310e49ca623e973fc2d1ac5b83a9104434d09c8a11e290b441ca674ab60b5", + "transactionHash": "0xc21d4634243103d1e2f07d9000244ebab6b75ffa6b0728b40c5d0eb554af2a65", + "logs": [], + "blockNumber": 31, + "cumulativeGasUsed": "337439", + "status": 1, + "byzantium": true + }, + "args": [ + "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" + ], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_token\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Deposit\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"depositTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getToken\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"balanceOf(address)\":{\"params\":{\"_owner\":\"account owner\"}},\"depositTokens(address,uint256)\":{\"details\":\"you may need to call `token.approve(bank, _value)`\",\"params\":{\"_to\":\"account that will have their balance increased by `_value`\",\"_value\":\"amount of tokens to be transfered\"}},\"transferTokens(address,uint256)\":{\"params\":{\"_to\":\"account that will receive `_value` tokens\",\"_value\":\"amount of tokens to be transfered\"}}},\"version\":1},\"userdoc\":{\"events\":{\"Deposit(address,address,uint256)\":{\"notice\":\"`value` tokens were transfered from `from` to bankthe balance of `to` was increased by `value`\"},\"Transfer(address,address,uint256)\":{\"notice\":\"`value` tokens were transfered from the bank to `to`the balance of `from` was decreased by `value`\"}},\"kind\":\"user\",\"methods\":{\"balanceOf(address)\":{\"notice\":\"get balance of `_owner`\"},\"depositTokens(address,uint256)\":{\"notice\":\"transfer `_value` tokens from caller to bankincrease the balance of `_to` by `_value`\"},\"getToken()\":{\"notice\":\"returns the token used internally\"},\"transferTokens(address,uint256)\":{\"notice\":\"transfer `_value` tokens from bank to `_to`decrease the balance of caller by `_value`\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Bank.sol\":\"Bank\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/Bank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank contract\\npragma solidity ^0.8.0;\\n\\nimport {IBank} from \\\"./IBank.sol\\\";\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ncontract Bank is IBank {\\n IERC20 private immutable token;\\n\\n // `balances` maps account/contract addresses to balances\\n mapping(address => uint256) private balances;\\n\\n constructor(address _token) {\\n require(_token != address(0), \\\"Bank: invalid token\\\");\\n token = IERC20(_token);\\n }\\n\\n function getToken() public view override returns (IERC20) {\\n return token;\\n }\\n\\n function balanceOf(address _owner) public view override returns (uint256) {\\n return balances[_owner];\\n }\\n\\n function transferTokens(address _to, uint256 _value) public override {\\n // checks\\n uint256 balance = balances[msg.sender];\\n require(_value <= balance, \\\"Bank: not enough balance\\\");\\n\\n // effects\\n // Note: this should not underflow because we checked that\\n // `_value <= balance` in the `require` above\\n unchecked {\\n balances[msg.sender] = balance - _value;\\n }\\n\\n // interactions\\n // Note: a well-implemented ERC-20 contract should already\\n // require the recipient (in this case, `_to`) to be different\\n // than address(0), so we don't need to check it ourselves\\n require(token.transfer(_to, _value), \\\"Bank: transfer failed\\\");\\n emit Transfer(msg.sender, _to, _value);\\n }\\n\\n function depositTokens(address _to, uint256 _value) public override {\\n // checks\\n require(_to != address(0), \\\"Bank: invalid recipient\\\");\\n\\n // effects\\n // Note: this should not overflow because `IERC20.totalSupply`\\n // returns a `uint256` value, so there can't be more than\\n // `uint256.max` tokens in an ERC-20 contract.\\n balances[_to] += _value;\\n\\n // interactions\\n // Note: transfers tokens to bank, but emits `Deposit` event\\n // with recipient being `_to`\\n require(\\n token.transferFrom(msg.sender, address(this), _value),\\n \\\"Bank: transferFrom failed\\\"\\n );\\n emit Deposit(msg.sender, _to, _value);\\n }\\n}\\n\",\"keccak256\":\"0x1a0ebcbd1c823c592b224959a3b9c4603489c4a3d878b2809c6552528fed672b\",\"license\":\"Apache-2.0\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60a060405234801561001057600080fd5b5060405161060b38038061060b83398101604081905261002f9161009a565b6001600160a01b0381166100895760405162461bcd60e51b815260206004820152601360248201527f42616e6b3a20696e76616c696420746f6b656e00000000000000000000000000604482015260640160405180910390fd5b6001600160a01b03166080526100ca565b6000602082840312156100ac57600080fd5b81516001600160a01b03811681146100c357600080fd5b9392505050565b6080516105196100f260003960008181605e01528181610196015261033901526105196000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c806321df0da71461005157806366168bd71461008d57806370a08231146100a2578063bec3fa17146100d9575b600080fd5b6040516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001681526020015b60405180910390f35b6100a061009b36600461044f565b6100ec565b005b6100cb6100b0366004610479565b6001600160a01b031660009081526020819052604090205490565b604051908152602001610084565b6100a06100e736600461044f565b61029f565b6001600160a01b0382166101475760405162461bcd60e51b815260206004820152601760248201527f42616e6b3a20696e76616c696420726563697069656e7400000000000000000060448201526064015b60405180910390fd5b6001600160a01b0382166000908152602081905260408120805483929061016f90849061049b565b90915550506040516323b872dd60e01b8152336004820152306024820152604481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156101e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020b91906104c1565b6102575760405162461bcd60e51b815260206004820152601960248201527f42616e6b3a207472616e7366657246726f6d206661696c656400000000000000604482015260640161013e565b60408051338152602081018390526001600160a01b038416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b33600090815260208190526040902054808211156102ff5760405162461bcd60e51b815260206004820152601860248201527f42616e6b3a206e6f7420656e6f7567682062616c616e63650000000000000000604482015260640161013e565b336000908152602081905260409081902083830390555163a9059cbb60e01b81526001600160a01b038481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a691906104c1565b6103ea5760405162461bcd60e51b815260206004820152601560248201527410985b9ace881d1c985b9cd9995c8819985a5b1959605a1b604482015260640161013e565b604080516001600160a01b03851681526020810184905233917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a2505050565b80356001600160a01b038116811461044a57600080fd5b919050565b6000806040838503121561046257600080fd5b61046b83610433565b946020939093013593505050565b60006020828403121561048b57600080fd5b61049482610433565b9392505050565b600082198211156104bc57634e487b7160e01b600052601160045260246000fd5b500190565b6000602082840312156104d357600080fd5b8151801515811461049457600080fdfea26469706673582212202f52a7f24915f76bd55f8533504eca6464ea1199be7010f33418e3e3cb53374564736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c806321df0da71461005157806366168bd71461008d57806370a08231146100a2578063bec3fa17146100d9575b600080fd5b6040516001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001681526020015b60405180910390f35b6100a061009b36600461044f565b6100ec565b005b6100cb6100b0366004610479565b6001600160a01b031660009081526020819052604090205490565b604051908152602001610084565b6100a06100e736600461044f565b61029f565b6001600160a01b0382166101475760405162461bcd60e51b815260206004820152601760248201527f42616e6b3a20696e76616c696420726563697069656e7400000000000000000060448201526064015b60405180910390fd5b6001600160a01b0382166000908152602081905260408120805483929061016f90849061049b565b90915550506040516323b872dd60e01b8152336004820152306024820152604481018290527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316906323b872dd906064016020604051808303816000875af11580156101e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020b91906104c1565b6102575760405162461bcd60e51b815260206004820152601960248201527f42616e6b3a207472616e7366657246726f6d206661696c656400000000000000604482015260640161013e565b60408051338152602081018390526001600160a01b038416917f5548c837ab068cf56a2c2479df0882a4922fd203edb7517321831d95078c5f62910160405180910390a25050565b33600090815260208190526040902054808211156102ff5760405162461bcd60e51b815260206004820152601860248201527f42616e6b3a206e6f7420656e6f7567682062616c616e63650000000000000000604482015260640161013e565b336000908152602081905260409081902083830390555163a9059cbb60e01b81526001600160a01b038481166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015610382573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103a691906104c1565b6103ea5760405162461bcd60e51b815260206004820152601560248201527410985b9ace881d1c985b9cd9995c8819985a5b1959605a1b604482015260640161013e565b604080516001600160a01b03851681526020810184905233917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a2505050565b80356001600160a01b038116811461044a57600080fd5b919050565b6000806040838503121561046257600080fd5b61046b83610433565b946020939093013593505050565b60006020828403121561048b57600080fd5b61049482610433565b9392505050565b600082198211156104bc57634e487b7160e01b600052601160045260246000fd5b500190565b6000602082840312156104d357600080fd5b8151801515811461049457600080fdfea26469706673582212202f52a7f24915f76bd55f8533504eca6464ea1199be7010f33418e3e3cb53374564736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "balanceOf(address)": { + "params": { + "_owner": "account owner" + } + }, + "depositTokens(address,uint256)": { + "details": "you may need to call `token.approve(bank, _value)`", + "params": { + "_to": "account that will have their balance increased by `_value`", + "_value": "amount of tokens to be transfered" + } + }, + "transferTokens(address,uint256)": { + "params": { + "_to": "account that will receive `_value` tokens", + "_value": "amount of tokens to be transfered" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "Deposit(address,address,uint256)": { + "notice": "`value` tokens were transfered from `from` to bankthe balance of `to` was increased by `value`" + }, + "Transfer(address,address,uint256)": { + "notice": "`value` tokens were transfered from the bank to `to`the balance of `from` was decreased by `value`" + } + }, + "kind": "user", + "methods": { + "balanceOf(address)": { + "notice": "get balance of `_owner`" + }, + "depositTokens(address,uint256)": { + "notice": "transfer `_value` tokens from caller to bankincrease the balance of `_to` by `_value`" + }, + "getToken()": { + "notice": "returns the token used internally" + }, + "transferTokens(address,uint256)": { + "notice": "transfer `_value` tokens from bank to `_to`decrease the balance of caller by `_value`" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 3434, + "contract": "contracts/Bank.sol:Bank", + "label": "balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + } + } + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/Bitmask.json b/echo-js/deployments/localhost/Bitmask.json new file mode 100644 index 00000000..632d5fef --- /dev/null +++ b/echo-js/deployments/localhost/Bitmask.json @@ -0,0 +1,49 @@ +{ + "address": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "abi": [], + "transactionHash": "0xc6885a17a35d339e5d669b8beb485b75cfe164f192703a913fe371ee351eba5a", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "transactionIndex": 0, + "gasUsed": "164134", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x2780cdc0c935fc9d320292c8c263afcc2ecb2ecc5ab1a156aeeba93f07a5f3f2", + "transactionHash": "0xc6885a17a35d339e5d669b8beb485b75cfe164f192703a913fe371ee351eba5a", + "logs": [], + "blockNumber": 2, + "cumulativeGasUsed": "164134", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"author\":\"Stephen Chen\",\"kind\":\"dev\",\"methods\":{},\"title\":\"Bit Mask Library\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getBit(mapping(uint256 => uint256) storage,uint256)\":{\"notice\":\"Get a bit in the bit mask\"},\"setBit(mapping(uint256 => uint256) storage,uint256,bool)\":{\"notice\":\"Set a bit in the bit mask\"}},\"notice\":\"Implements bit mask with dynamic array\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Bitmask.sol\":\"Bitmask\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/Bitmask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\npragma solidity ^0.8.0;\\n\\n/// @title Bit Mask Library\\n/// @author Stephen Chen\\n/// @notice Implements bit mask with dynamic array\\nlibrary Bitmask {\\n /// @notice Set a bit in the bit mask\\n function setBit(\\n mapping(uint256 => uint256) storage bitmask,\\n uint256 _bit,\\n bool _value\\n ) public {\\n // calculate the number of bits has been store in bitmask now\\n uint256 positionOfMask = uint256(_bit / 256);\\n uint256 positionOfBit = _bit % 256;\\n\\n if (_value) {\\n bitmask[positionOfMask] =\\n bitmask[positionOfMask] |\\n (1 << positionOfBit);\\n } else {\\n bitmask[positionOfMask] =\\n bitmask[positionOfMask] &\\n ~(1 << positionOfBit);\\n }\\n }\\n\\n /// @notice Get a bit in the bit mask\\n function getBit(mapping(uint256 => uint256) storage bitmask, uint256 _bit)\\n public\\n view\\n returns (bool)\\n {\\n // calculate the number of bits has been store in bitmask now\\n uint256 positionOfMask = uint256(_bit / 256);\\n uint256 positionOfBit = _bit % 256;\\n\\n return ((bitmask[positionOfMask] & (1 << positionOfBit)) != 0);\\n }\\n}\\n\",\"keccak256\":\"0xe35cf68672f5844589c0e56f36aa3813ca4ffb882a55a46d15adac7e3cc889bd\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x61020161003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c806303fbaf73146100455780636449da101461006c575b600080fd5b610058610053366004610130565b61008e565b604051901515815260200160405180910390f35b81801561007857600080fd5b5061008c610087366004610151565b6100ce565b005b60008061009d6101008461018d565b905060006100ad610100856101a1565b6000928352602095909552506040902054600190931b909216151592915050565b60006100dc6101008461018d565b905060006100ec610100856101a1565b9050821561011057600082815260208690526040902080546001831b179055610129565b600082815260208690526040902080546001831b191690555b5050505050565b60008060408385031215610142578182fd5b50508035926020909101359150565b600080600060608486031215610165578081fd5b833592506020840135915060408401358015158114610182578182fd5b809150509250925092565b60008261019c5761019c6101b5565b500490565b6000826101b0576101b06101b5565b500690565b634e487b7160e01b600052601260045260246000fdfea26469706673582212200f8e0f4b82404ab41a0a463ebfd6ceb825dcf1eb840a650cbfc02d268876dbf464736f6c63430008040033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100405760003560e01c806303fbaf73146100455780636449da101461006c575b600080fd5b610058610053366004610130565b61008e565b604051901515815260200160405180910390f35b81801561007857600080fd5b5061008c610087366004610151565b6100ce565b005b60008061009d6101008461018d565b905060006100ad610100856101a1565b6000928352602095909552506040902054600190931b909216151592915050565b60006100dc6101008461018d565b905060006100ec610100856101a1565b9050821561011057600082815260208690526040902080546001831b179055610129565b600082815260208690526040902080546001831b191690555b5050505050565b60008060408385031215610142578182fd5b50508035926020909101359150565b600080600060608486031215610165578081fd5b833592506020840135915060408401358015158114610182578182fd5b809150509250925092565b60008261019c5761019c6101b5565b500490565b6000826101b0576101b06101b5565b500690565b634e487b7160e01b600052601260045260246000fdfea26469706673582212200f8e0f4b82404ab41a0a463ebfd6ceb825dcf1eb840a650cbfc02d268876dbf464736f6c63430008040033", + "devdoc": { + "author": "Stephen Chen", + "kind": "dev", + "methods": {}, + "title": "Bit Mask Library", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "getBit(mapping(uint256 => uint256) storage,uint256)": { + "notice": "Get a bit in the bit mask" + }, + "setBit(mapping(uint256 => uint256) storage,uint256,bool)": { + "notice": "Set a bit in the bit mask" + } + }, + "notice": "Implements bit mask with dynamic array", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/BitsManipulation.json b/echo-js/deployments/localhost/BitsManipulation.json new file mode 100644 index 00000000..5b0b717e --- /dev/null +++ b/echo-js/deployments/localhost/BitsManipulation.json @@ -0,0 +1,165 @@ +{ + "address": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "abi": [ + { + "inputs": [ + { + "internalType": "int32", + "name": "number", + "type": "int32" + }, + { + "internalType": "uint32", + "name": "wordSize", + "type": "uint32" + } + ], + "name": "int32SignExtension", + "outputs": [ + { + "internalType": "int32", + "name": "", + "type": "int32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint32", + "name": "num", + "type": "uint32" + } + ], + "name": "uint32SwapEndian", + "outputs": [ + { + "internalType": "uint32", + "name": "", + "type": "uint32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "number", + "type": "uint64" + }, + { + "internalType": "uint64", + "name": "wordSize", + "type": "uint64" + } + ], + "name": "uint64SignExtension", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint64", + "name": "num", + "type": "uint64" + } + ], + "name": "uint64SwapEndian", + "outputs": [ + { + "internalType": "uint64", + "name": "", + "type": "uint64" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x517498de54c1c30525a68a79974070af07067770e913a9f25a8c7844df64b3a0", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x5FbDB2315678afecb367f032d93F642f64180aa3", + "transactionIndex": 0, + "gasUsed": "376733", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe8dedd4dd3534a61b48227e10ac64c8b8f88f27d36559141b2cc2f94621cc23c", + "transactionHash": "0x517498de54c1c30525a68a79974070af07067770e913a9f25a8c7844df64b3a0", + "logs": [], + "blockNumber": 1, + "cumulativeGasUsed": "376733", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"int32\",\"name\":\"number\",\"type\":\"int32\"},{\"internalType\":\"uint32\",\"name\":\"wordSize\",\"type\":\"uint32\"}],\"name\":\"int32SignExtension\",\"outputs\":[{\"internalType\":\"int32\",\"name\":\"\",\"type\":\"int32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint32\",\"name\":\"num\",\"type\":\"uint32\"}],\"name\":\"uint32SwapEndian\",\"outputs\":[{\"internalType\":\"uint32\",\"name\":\"\",\"type\":\"uint32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"number\",\"type\":\"uint64\"},{\"internalType\":\"uint64\",\"name\":\"wordSize\",\"type\":\"uint64\"}],\"name\":\"uint64SignExtension\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint64\",\"name\":\"num\",\"type\":\"uint64\"}],\"name\":\"uint64SwapEndian\",\"outputs\":[{\"internalType\":\"uint64\",\"name\":\"\",\"type\":\"uint64\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Felipe Argento / Stephen Chen\",\"kind\":\"dev\",\"methods\":{\"int32SignExtension(int32,uint32)\":{\"params\":{\"number\":\"signed number to be extended\",\"wordSize\":\"number of bits of the signed number, ie, 8 for int8\"}},\"uint32SwapEndian(uint32)\":{\"params\":{\"num\":\"number to have bytes swapped\"}},\"uint64SignExtension(uint64,uint64)\":{\"params\":{\"number\":\"signed number to be extended\",\"wordSize\":\"number of bits of the signed number, ie, 8 for int8\"}},\"uint64SwapEndian(uint64)\":{\"params\":{\"num\":\"number to have bytes swapped\"}}},\"title\":\"Bits Manipulation Library\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"int32SignExtension(int32,uint32)\":{\"notice\":\"Sign extend a shorter signed value to the full int32\"},\"uint32SwapEndian(uint32)\":{\"notice\":\"Swap byte order of unsigned ints with 32 bytes\"},\"uint64SignExtension(uint64,uint64)\":{\"notice\":\"Sign extend a shorter signed value to the full uint64\"},\"uint64SwapEndian(uint64)\":{\"notice\":\"Swap byte order of unsigned ints with 64 bytes\"}},\"notice\":\"Implements bit manipulation helper functions\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/BitsManipulation.sol\":\"BitsManipulation\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/BitsManipulation.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\npragma solidity ^0.8.0;\\n\\n/// @title Bits Manipulation Library\\n/// @author Felipe Argento / Stephen Chen\\n/// @notice Implements bit manipulation helper functions\\nlibrary BitsManipulation {\\n\\n /// @notice Sign extend a shorter signed value to the full int32\\n /// @param number signed number to be extended\\n /// @param wordSize number of bits of the signed number, ie, 8 for int8\\n function int32SignExtension(int32 number, uint32 wordSize)\\n public pure returns(int32)\\n {\\n uint32 uNumber = uint32(number);\\n bool isNegative = ((uint64(1) << (wordSize - 1)) & uNumber) > 0;\\n uint32 mask = ((uint32(2) ** wordSize) - 1);\\n\\n if (isNegative) {\\n uNumber = uNumber | ~mask;\\n }\\n\\n return int32(uNumber);\\n }\\n\\n /// @notice Sign extend a shorter signed value to the full uint64\\n /// @param number signed number to be extended\\n /// @param wordSize number of bits of the signed number, ie, 8 for int8\\n function uint64SignExtension(uint64 number, uint64 wordSize)\\n public pure returns(uint64)\\n {\\n uint64 uNumber = number;\\n bool isNegative = ((uint64(1) << (wordSize - 1)) & uNumber) > 0;\\n uint64 mask = ((uint64(2) ** wordSize) - 1);\\n\\n if (isNegative) {\\n uNumber = uNumber | ~mask;\\n }\\n\\n return uNumber;\\n }\\n\\n /// @notice Swap byte order of unsigned ints with 64 bytes\\n /// @param num number to have bytes swapped\\n function uint64SwapEndian(uint64 num) public pure returns(uint64) {\\n uint64 output = ((num & 0x00000000000000ff) << 56)|\\n ((num & 0x000000000000ff00) << 40)|\\n ((num & 0x0000000000ff0000) << 24)|\\n ((num & 0x00000000ff000000) << 8) |\\n ((num & 0x000000ff00000000) >> 8) |\\n ((num & 0x0000ff0000000000) >> 24)|\\n ((num & 0x00ff000000000000) >> 40)|\\n ((num & 0xff00000000000000) >> 56);\\n\\n return output;\\n }\\n\\n /// @notice Swap byte order of unsigned ints with 32 bytes\\n /// @param num number to have bytes swapped\\n function uint32SwapEndian(uint32 num) public pure returns(uint32) {\\n uint32 output = ((num >> 24) & 0xff) | ((num << 8) & 0xff0000) | ((num >> 8) & 0xff00) | ((num << 24) & 0xff000000);\\n return output;\\n }\\n}\\n\\n\",\"keccak256\":\"0x09e8d9397126dfc40a92d4099060c1615a4fbd99edd12afea5e5163ec8ce8aba\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x6105da61003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100565760003560e01c8063240034ec1461005b578063bf1924c5146100b0578063ef7c79491461014d578063f69c389b14610160575b600080fd5b6100966100693660046102ab565b601881811b63ff00000016600883811c61ff00169084901b62ff0000169390921c60ff1692909217171790565b60405163ffffffff90911681526020015b60405180910390f35b6101356100be3660046102cc565b603881811b67ff0000000000000016602883811b66ff0000000000001691909117601884811b65ff00000000001691909117600885811b64ff00000000169190911763ff0000009186901c919091161762ff00009185901c919091161761ff009184901c919091161760ff9290911c919091161790565b6040516001600160401b0390911681526020016100a7565b61013561015b3660046102e6565b610186565b61017361016e366004610272565b6101f0565b60405160039190910b81526020016100a7565b600082818082610197600187610572565b6001600160401b031660016001600160401b0316901b166001600160401b0316119050600060018560026101cb91906103b1565b6101d59190610572565b905081156101e4578019831792505b50909150505b92915050565b600082818063ffffffff831661020760018761054d565b63ffffffff1660016001600160401b0316901b166001600160401b0316119050600060018560026102389190610394565b6101d5919061054d565b803563ffffffff8116811461025657600080fd5b919050565b80356001600160401b038116811461025657600080fd5b60008060408385031215610284578182fd5b82358060030b8114610294578283fd5b91506102a260208401610242565b90509250929050565b6000602082840312156102bc578081fd5b6102c582610242565b9392505050565b6000602082840312156102dd578081fd5b6102c58261025b565b600080604083850312156102f8578182fd5b6103018361025b565b91506102a26020840161025b565b600181815b8085111561034c578163ffffffff048211156103325761033261058e565b8085161561033f57918102915b93841c9390800290610314565b509250929050565b600181815b8085111561034c57816001600160401b030482111561037a5761037a61058e565b8085161561038757918102915b93841c9390800290610359565b600063ffffffff6103a98185168285166103c9565b949350505050565b60006001600160401b036103a9818516828516610495565b6000826103d8575060016101ea565b816103e5575060006101ea565b81600181146103fb576002811461040557610436565b60019150506101ea565b60ff8411156104165761041661058e565b6001841b915063ffffffff8211156104305761043061058e565b506101ea565b5060208310610133831016604e8410600b841016171561046d575081810a63ffffffff8111156104685761046861058e565b6101ea565b610477838361030f565b8063ffffffff0482111561048d5761048d61058e565b029392505050565b6000826104a4575060016101ea565b816104b1575060006101ea565b81600181146103fb57600281146104c7576104f5565b60ff8411156104d8576104d861058e565b6001841b91506001600160401b038211156104305761043061058e565b5060208310610133831016604e8410600b841016171561052a575081810a6001600160401b038111156104685761046861058e565b6105348383610354565b806001600160401b030482111561048d5761048d61058e565b600063ffffffff8381169083168181101561056a5761056a61058e565b039392505050565b60006001600160401b038381169083168181101561056a5761056a5b634e487b7160e01b600052601160045260246000fdfea2646970667358221220d1a282b405bea3ac1b1041d4f9042915951dc97e60ea81d0a585311c188e81e664736f6c63430008040033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100565760003560e01c8063240034ec1461005b578063bf1924c5146100b0578063ef7c79491461014d578063f69c389b14610160575b600080fd5b6100966100693660046102ab565b601881811b63ff00000016600883811c61ff00169084901b62ff0000169390921c60ff1692909217171790565b60405163ffffffff90911681526020015b60405180910390f35b6101356100be3660046102cc565b603881811b67ff0000000000000016602883811b66ff0000000000001691909117601884811b65ff00000000001691909117600885811b64ff00000000169190911763ff0000009186901c919091161762ff00009185901c919091161761ff009184901c919091161760ff9290911c919091161790565b6040516001600160401b0390911681526020016100a7565b61013561015b3660046102e6565b610186565b61017361016e366004610272565b6101f0565b60405160039190910b81526020016100a7565b600082818082610197600187610572565b6001600160401b031660016001600160401b0316901b166001600160401b0316119050600060018560026101cb91906103b1565b6101d59190610572565b905081156101e4578019831792505b50909150505b92915050565b600082818063ffffffff831661020760018761054d565b63ffffffff1660016001600160401b0316901b166001600160401b0316119050600060018560026102389190610394565b6101d5919061054d565b803563ffffffff8116811461025657600080fd5b919050565b80356001600160401b038116811461025657600080fd5b60008060408385031215610284578182fd5b82358060030b8114610294578283fd5b91506102a260208401610242565b90509250929050565b6000602082840312156102bc578081fd5b6102c582610242565b9392505050565b6000602082840312156102dd578081fd5b6102c58261025b565b600080604083850312156102f8578182fd5b6103018361025b565b91506102a26020840161025b565b600181815b8085111561034c578163ffffffff048211156103325761033261058e565b8085161561033f57918102915b93841c9390800290610314565b509250929050565b600181815b8085111561034c57816001600160401b030482111561037a5761037a61058e565b8085161561038757918102915b93841c9390800290610359565b600063ffffffff6103a98185168285166103c9565b949350505050565b60006001600160401b036103a9818516828516610495565b6000826103d8575060016101ea565b816103e5575060006101ea565b81600181146103fb576002811461040557610436565b60019150506101ea565b60ff8411156104165761041661058e565b6001841b915063ffffffff8211156104305761043061058e565b506101ea565b5060208310610133831016604e8410600b841016171561046d575081810a63ffffffff8111156104685761046861058e565b6101ea565b610477838361030f565b8063ffffffff0482111561048d5761048d61058e565b029392505050565b6000826104a4575060016101ea565b816104b1575060006101ea565b81600181146103fb57600281146104c7576104f5565b60ff8411156104d8576104d861058e565b6001841b91506001600160401b038211156104305761043061058e565b5060208310610133831016604e8410600b841016171561052a575081810a6001600160401b038111156104685761046861058e565b6105348383610354565b806001600160401b030482111561048d5761048d61058e565b600063ffffffff8381169083168181101561056a5761056a61058e565b039392505050565b60006001600160401b038381169083168181101561056a5761056a5b634e487b7160e01b600052601160045260246000fdfea2646970667358221220d1a282b405bea3ac1b1041d4f9042915951dc97e60ea81d0a585311c188e81e664736f6c63430008040033", + "devdoc": { + "author": "Felipe Argento / Stephen Chen", + "kind": "dev", + "methods": { + "int32SignExtension(int32,uint32)": { + "params": { + "number": "signed number to be extended", + "wordSize": "number of bits of the signed number, ie, 8 for int8" + } + }, + "uint32SwapEndian(uint32)": { + "params": { + "num": "number to have bytes swapped" + } + }, + "uint64SignExtension(uint64,uint64)": { + "params": { + "number": "signed number to be extended", + "wordSize": "number of bits of the signed number, ie, 8 for int8" + } + }, + "uint64SwapEndian(uint64)": { + "params": { + "num": "number to have bytes swapped" + } + } + }, + "title": "Bits Manipulation Library", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "int32SignExtension(int32,uint32)": { + "notice": "Sign extend a shorter signed value to the full int32" + }, + "uint32SwapEndian(uint32)": { + "notice": "Swap byte order of unsigned ints with 32 bytes" + }, + "uint64SignExtension(uint64,uint64)": { + "notice": "Sign extend a shorter signed value to the full uint64" + }, + "uint64SwapEndian(uint64)": { + "notice": "Swap byte order of unsigned ints with 64 bytes" + } + }, + "notice": "Implements bit manipulation helper functions", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/CartesiDAppFactory.json b/echo-js/deployments/localhost/CartesiDAppFactory.json new file mode 100644 index 00000000..0a4c3c63 --- /dev/null +++ b/echo-js/deployments/localhost/CartesiDAppFactory.json @@ -0,0 +1,477 @@ +{ + "address": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690", + "abi": [ + { + "inputs": [ + { + "components": [ + { + "internalType": "contract IDiamondCut", + "name": "diamondCutFacet", + "type": "address" + }, + { + "internalType": "contract DiamondInit", + "name": "diamondInit", + "type": "address" + }, + { + "internalType": "contract IBank", + "name": "feeManagerBank", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut", + "type": "tuple[]" + } + ], + "internalType": "struct CartesiDAppFactory.FactoryConfig", + "name": "_fConfig", + "type": "tuple" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract CartesiDApp", + "name": "application", + "type": "address" + }, + { + "components": [ + { + "internalType": "address", + "name": "diamondOwner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "templateHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "inputDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "challengePeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inputLog2Size", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feePerClaim", + "type": "uint256" + }, + { + "internalType": "address", + "name": "feeManagerOwner", + "type": "address" + }, + { + "internalType": "address payable[]", + "name": "validators", + "type": "address[]" + } + ], + "indexed": false, + "internalType": "struct ICartesiDAppFactory.AppConfig", + "name": "config", + "type": "tuple" + } + ], + "name": "ApplicationCreated", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "name": "diamondCut", + "outputs": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "diamondCutFacet", + "outputs": [ + { + "internalType": "contract IDiamondCut", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "diamondInit", + "outputs": [ + { + "internalType": "contract DiamondInit", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "feeManagerBank", + "outputs": [ + { + "internalType": "contract IBank", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "diamondOwner", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "templateHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "inputDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "challengePeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inputLog2Size", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feePerClaim", + "type": "uint256" + }, + { + "internalType": "address", + "name": "feeManagerOwner", + "type": "address" + }, + { + "internalType": "address payable[]", + "name": "validators", + "type": "address[]" + } + ], + "internalType": "struct ICartesiDAppFactory.AppConfig", + "name": "_appConfig", + "type": "tuple" + } + ], + "name": "newApplication", + "outputs": [ + { + "internalType": "contract CartesiDApp", + "name": "", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x4d734e09fce02f10d7448da1d1c8e1f314baa9ab05cb559c3ce8dc9b5b06c075", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xc3e53F4d16Ae77Db1c982e75a937B9f60FE63690", + "transactionIndex": 0, + "gasUsed": "3301783", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xa6cf4b826a9506cdd281c119dcde42a2b2733e1d017ed11af9259484f7908169", + "transactionHash": "0x4d734e09fce02f10d7448da1d1c8e1f314baa9ab05cb559c3ce8dc9b5b06c075", + "logs": [], + "blockNumber": 32, + "cumulativeGasUsed": "3301783", + "status": 1, + "byzantium": true + }, + "args": [ + { + "diamondCutFacet": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e", + "diamondInit": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933", + "feeManagerBank": "0xE6E340D132b5f46d1e472DebcD681B2aBc16e57E", + "diamondCut": [ + { + "facetAddress": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "action": 0, + "functionSelectors": [ + "0xcdffacc6", + "0x52ef6b2c", + "0xadfca15e", + "0x7a0ed627", + "0x01ffc9a7" + ] + }, + { + "facetAddress": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", + "action": 0, + "functionSelectors": [ + "0x8da5cb5b", + "0xf2fde38b" + ] + }, + { + "facetAddress": "0x59b670e9fA9D0A427751Af201D676719a970857b", + "action": 0, + "functionSelectors": [ + "0xcb1061a6" + ] + }, + { + "facetAddress": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1", + "action": 0, + "functionSelectors": [ + "0x15e55ce5", + "0x150b7a02" + ] + }, + { + "facetAddress": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44", + "action": 0, + "functionSelectors": [ + "0x2abfe7b3", + "0x74956b94" + ] + }, + { + "facetAddress": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f", + "action": 0, + "functionSelectors": [ + "0x6e964cea", + "0xa859b983", + "0xe8f56171", + "0xde7a8d11", + "0x7a5bf67c" + ] + }, + { + "facetAddress": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319", + "action": 0, + "functionSelectors": [ + "0xf32078e8", + "0x1ab6dcab", + "0xa459600e", + "0xe7955244" + ] + }, + { + "facetAddress": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", + "action": 0, + "functionSelectors": [ + "0x6190d81e", + "0x3c0d9958", + "0xa2382036", + "0xf3af7efd", + "0x10517cfc", + "0x8021be81", + "0x83552b4d", + "0xa981588a", + "0x3ad58a27", + "0x5e439a0c" + ] + }, + { + "facetAddress": "0x09635F643e140090A9A8Dcd712eD6285858ceBef", + "action": 0, + "functionSelectors": [ + "0xbd66528a", + "0x82ae9ef7", + "0x7864b77d", + "0xb97dd9e2", + "0xa3a40ea5", + "0xddf7bcf0", + "0xe17ba012", + "0x54ee1da5", + "0x61b12c66" + ] + }, + { + "facetAddress": "0xc5a5C42992dECbae36851359345FE25997F5C42d", + "action": 0, + "functionSelectors": [ + "0x101494ce", + "0xf6023815", + "0x8219fda4", + "0xd2992f54", + "0x55564a70", + "0xcc8a2451", + "0x1fcc449e" + ] + } + ] + } + ], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"internalType\":\"contract IDiamondCut\",\"name\":\"diamondCutFacet\",\"type\":\"address\"},{\"internalType\":\"contract DiamondInit\",\"name\":\"diamondInit\",\"type\":\"address\"},{\"internalType\":\"contract IBank\",\"name\":\"feeManagerBank\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut\",\"type\":\"tuple[]\"}],\"internalType\":\"struct CartesiDAppFactory.FactoryConfig\",\"name\":\"_fConfig\",\"type\":\"tuple\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract CartesiDApp\",\"name\":\"application\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"address\",\"name\":\"diamondOwner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"templateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inputDuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inputLog2Size\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feePerClaim\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeManagerOwner\",\"type\":\"address\"},{\"internalType\":\"address payable[]\",\"name\":\"validators\",\"type\":\"address[]\"}],\"indexed\":false,\"internalType\":\"struct ICartesiDAppFactory.AppConfig\",\"name\":\"config\",\"type\":\"tuple\"}],\"name\":\"ApplicationCreated\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"name\":\"diamondCut\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"diamondCutFacet\",\"outputs\":[{\"internalType\":\"contract IDiamondCut\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"diamondInit\",\"outputs\":[{\"internalType\":\"contract DiamondInit\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"feeManagerBank\",\"outputs\":[{\"internalType\":\"contract IBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"diamondOwner\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"templateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inputDuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inputLog2Size\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feePerClaim\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeManagerOwner\",\"type\":\"address\"},{\"internalType\":\"address payable[]\",\"name\":\"validators\",\"type\":\"address[]\"}],\"internalType\":\"struct ICartesiDAppFactory.AppConfig\",\"name\":\"_appConfig\",\"type\":\"tuple\"}],\"name\":\"newApplication\",\"outputs\":[{\"internalType\":\"contract CartesiDApp\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"newApplication((address,bytes32,uint256,uint256,uint256,uint256,address,address[]))\":{\"params\":{\"_appConfig\":\"application configurations\"},\"returns\":{\"_0\":\"application address\"}}},\"version\":1},\"userdoc\":{\"events\":{\"ApplicationCreated(address,(address,bytes32,uint256,uint256,uint256,uint256,address,address[]))\":{\"notice\":\"Event emitted when a new application is deployed\"}},\"kind\":\"user\",\"methods\":{\"newApplication((address,bytes32,uint256,uint256,uint256,uint256,address,address[]))\":{\"notice\":\"Deploy a new application\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/CartesiDAppFactory.sol\":\"CartesiDAppFactory\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/CartesiDApp.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n*\\n* Implementation of a diamond.\\n/******************************************************************************/\\n\\nimport {LibDiamond} from \\\"./libraries/LibDiamond.sol\\\";\\nimport {IDiamondCut} from \\\"./interfaces/IDiamondCut.sol\\\";\\n\\ncontract CartesiDApp {\\n constructor(address _contractOwner, address _diamondCutFacet) payable {\\n LibDiamond.setContractOwner(_contractOwner);\\n\\n // Add the diamondCut external function from the diamondCutFacet\\n IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);\\n bytes4[] memory functionSelectors = new bytes4[](1);\\n functionSelectors[0] = IDiamondCut.diamondCut.selector;\\n cut[0] = IDiamondCut.FacetCut({\\n facetAddress: _diamondCutFacet,\\n action: IDiamondCut.FacetCutAction.Add,\\n functionSelectors: functionSelectors\\n });\\n LibDiamond.diamondCut(cut, address(0), \\\"\\\");\\n }\\n\\n // Find facet for function that is called and execute the\\n // function if a facet is found and return any value.\\n fallback() external payable {\\n LibDiamond.DiamondStorage storage ds;\\n bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;\\n // get diamond storage\\n assembly {\\n ds.slot := position\\n }\\n // get facet from function selector\\n address facet = address(bytes20(ds.facets[msg.sig]));\\n require(facet != address(0), \\\"Diamond: Function does not exist\\\");\\n // Execute external function from facet using delegatecall and return any value.\\n assembly {\\n // copy function selector and any arguments\\n calldatacopy(0, 0, calldatasize())\\n // execute function call using the facet\\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\\n // get any return value\\n returndatacopy(0, 0, returndatasize())\\n // return any return value or error back to the caller\\n switch result\\n case 0 {\\n revert(0, returndatasize())\\n }\\n default {\\n return(0, returndatasize())\\n }\\n }\\n }\\n\\n receive() external payable {}\\n}\\n\",\"keccak256\":\"0x5dcf7607e87afc097540bc36b53f4bf6cf5e037027441218ec5d78362fa7f3b7\",\"license\":\"MIT\"},\"contracts/CartesiDAppFactory.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Cartesi DApp Factory\\npragma solidity ^0.8.0;\\n\\nimport {ICartesiDAppFactory} from \\\"./ICartesiDAppFactory.sol\\\";\\nimport {CartesiDApp} from \\\"./CartesiDApp.sol\\\";\\nimport {IDiamondCut} from \\\"./interfaces/IDiamondCut.sol\\\";\\nimport {IERC173} from \\\"./interfaces/IERC173.sol\\\";\\nimport {DiamondInit, DiamondConfig} from \\\"./upgrade_initializers/DiamondInit.sol\\\";\\nimport {IBank} from \\\"./IBank.sol\\\";\\n\\ncontract CartesiDAppFactory is ICartesiDAppFactory {\\n IDiamondCut public immutable diamondCutFacet;\\n DiamondInit public immutable diamondInit;\\n IBank public immutable feeManagerBank;\\n IDiamondCut.FacetCut[] public diamondCut;\\n\\n struct FactoryConfig {\\n IDiamondCut diamondCutFacet;\\n DiamondInit diamondInit;\\n IBank feeManagerBank;\\n IDiamondCut.FacetCut[] diamondCut;\\n }\\n\\n constructor(FactoryConfig memory _fConfig) {\\n diamondCutFacet = _fConfig.diamondCutFacet;\\n diamondInit = _fConfig.diamondInit;\\n feeManagerBank = _fConfig.feeManagerBank;\\n for (uint256 i; i < _fConfig.diamondCut.length; ++i) {\\n diamondCut.push(_fConfig.diamondCut[i]);\\n }\\n }\\n\\n function newApplication(AppConfig calldata _appConfig)\\n public\\n returns (CartesiDApp)\\n {\\n CartesiDApp application = new CartesiDApp(\\n address(this),\\n address(diamondCutFacet)\\n );\\n DiamondConfig memory dConfig = DiamondConfig({\\n templateHash: _appConfig.templateHash,\\n inputDuration: _appConfig.inputDuration,\\n challengePeriod: _appConfig.challengePeriod,\\n inputLog2Size: _appConfig.inputLog2Size,\\n feePerClaim: _appConfig.feePerClaim,\\n feeManagerBank: address(feeManagerBank),\\n feeManagerOwner: _appConfig.feeManagerOwner,\\n validators: _appConfig.validators\\n });\\n IDiamondCut(address(application)).diamondCut(\\n diamondCut,\\n address(diamondInit),\\n abi.encodeWithSelector(DiamondInit.init.selector, dConfig)\\n );\\n IERC173(address(application)).transferOwnership(\\n _appConfig.diamondOwner\\n );\\n emit ApplicationCreated(application, _appConfig);\\n return application;\\n }\\n}\\n\",\"keccak256\":\"0x5b457605c89dfaa9dcbb49d49c0fa5de6cddd16ad53459ffddb2137bb843fc08\",\"license\":\"Apache-2.0\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/ICartesiDAppFactory.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Cartesi DApp Factory interface\\npragma solidity ^0.8.0;\\n\\nimport {CartesiDApp} from \\\"./CartesiDApp.sol\\\";\\n\\ninterface ICartesiDAppFactory {\\n /// @notice application configurations\\n /// @param diamondOwner diamond owner\\n /// @param templateHash state hash of the cartesi machine at t0\\n /// @param inputDuration duration of input accumulation phase in seconds\\n /// @param challengePeriod duration of challenge period in seconds\\n /// @param inputLog2Size size of the input memory range in this machine\\n /// @param feePerClaim fee per claim to reward the validators\\n /// @param feeManagerOwner fee manager owner address\\n /// @param validators initial validator set\\n /// @dev validators have to be unique, if the same validator is added twice\\n /// consensus will never be reached\\n struct AppConfig {\\n // DiamondCutFacet\\n address diamondOwner;\\n // RollupsFacet\\n bytes32 templateHash;\\n uint256 inputDuration;\\n uint256 challengePeriod;\\n // InputFacet\\n uint256 inputLog2Size;\\n // FeeManagerFacet\\n uint256 feePerClaim;\\n address feeManagerOwner;\\n // ValidatorManagerFacet\\n address payable[] validators;\\n }\\n\\n /// @notice Deploy a new application\\n /// @param _appConfig application configurations\\n /// @return application address\\n function newApplication(AppConfig calldata _appConfig)\\n external\\n returns (CartesiDApp);\\n\\n /// @notice Event emitted when a new application is deployed\\n /// @param application application address\\n /// @param config application configurations\\n event ApplicationCreated(CartesiDApp indexed application, AppConfig config);\\n}\\n\",\"keccak256\":\"0x2aab51e8e50a25183ff902a19680e2e47602624a631fbcdd1f61259adbb60609\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\\n}\\n\",\"keccak256\":\"0x6a3129be1f39b6fec871f2c94bf7debf2d6a4e665547a4d83e7f2def38359e44\",\"license\":\"MIT\"},\"contracts/interfaces/IDiamondLoupe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\n// A loupe is a small magnifying glass used to look at diamonds.\\n// These functions look at diamonds\\ninterface IDiamondLoupe {\\n /// These functions are expected to be called frequently\\n /// by tools.\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Gets all facet addresses and their four byte function selectors.\\n /// @return facets_ Facet\\n function facets() external view returns (Facet[] memory facets_);\\n\\n /// @notice Gets all the function selectors supported by a specific facet.\\n /// @param _facet The facet address.\\n /// @return facetFunctionSelectors_\\n function facetFunctionSelectors(address _facet)\\n external\\n view\\n returns (bytes4[] memory facetFunctionSelectors_);\\n\\n /// @notice Get all the facet addresses used by a diamond.\\n /// @return facetAddresses_\\n function facetAddresses()\\n external\\n view\\n returns (address[] memory facetAddresses_);\\n\\n /// @notice Gets the facet that supports the given selector.\\n /// @dev If facet is not found return address(0).\\n /// @param _functionSelector The function selector.\\n /// @return facetAddress_ The facet address.\\n function facetAddress(bytes4 _functionSelector)\\n external\\n view\\n returns (address facetAddress_);\\n}\\n\",\"keccak256\":\"0xd6c3796a7c45baea6e47fdd5f2cec95d7796991bc9a949604f99875590962a67\",\"license\":\"MIT\"},\"contracts/interfaces/IERC173.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\",\"keccak256\":\"0xc47289cda9c9cdb749612eb82ccb9abf9ab08dca74bdca22292ae7f765a15a5f\",\"license\":\"MIT\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // maps function selectors to the facets that execute the functions.\\n // and maps the selectors to their position in the selectorSlots array.\\n // func selector => address facet, selector position\\n mapping(bytes4 => bytes32) facets;\\n // array of slots of function selectors.\\n // each slot holds 8 function selectors.\\n mapping(uint256 => bytes32) selectorSlots;\\n // The number of function selectors in selectorSlots\\n uint16 selectorCount;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(\\n msg.sender == diamondStorage().contractOwner,\\n \\\"LibDiamond: Must be contract owner\\\"\\n );\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] diamondCut,\\n address init,\\n bytes callData\\n );\\n\\n bytes32 constant CLEAR_ADDRESS_MASK =\\n bytes32(uint256(0xffffffffffffffffffffffff));\\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\\n\\n // Internal function version of diamondCut\\n // This code is almost the same as the external diamondCut,\\n // except it is using 'Facet[] memory _diamondCut' instead of\\n // 'Facet[] calldata _diamondCut'.\\n // The code is duplicated to prevent copying calldata to memory which\\n // causes an error for a two dimensional array.\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n DiamondStorage storage ds = diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addReplaceRemoveFacetSelectors(\\n uint256 _selectorCount,\\n bytes32 _selectorSlot,\\n address _newFacetAddress,\\n IDiamondCut.FacetCutAction _action,\\n bytes4[] memory _selectors\\n ) internal returns (uint256, bytes32) {\\n DiamondStorage storage ds = diamondStorage();\\n require(\\n _selectors.length > 0,\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\n );\\n if (_action == IDiamondCut.FacetCutAction.Add) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Add facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) == address(0),\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\n );\\n // add facet for selector\\n ds.facets[selector] =\\n bytes20(_newFacetAddress) |\\n bytes32(_selectorCount);\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\\n // clear selector position in slot and add selector\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\\n (bytes32(selector) >> selectorInSlotPosition);\\n // if slot is full then write it to storage\\n if (selectorInSlotPosition == 224) {\\n // \\\"_selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"_selectorSlot / 8\\\"\\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\\n _selectorSlot = 0;\\n }\\n _selectorCount++;\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Replace facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n address oldFacetAddress = address(bytes20(oldFacet));\\n // only useful if immutable functions exist\\n require(\\n oldFacetAddress != address(this),\\n \\\"LibDiamondCut: Can't replace immutable function\\\"\\n );\\n require(\\n oldFacetAddress != _newFacetAddress,\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\n );\\n require(\\n oldFacetAddress != address(0),\\n \\\"LibDiamondCut: Can't replace function that doesn't exist\\\"\\n );\\n // replace old facet address\\n ds.facets[selector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(_newFacetAddress);\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\\n require(\\n _newFacetAddress == address(0),\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\n );\\n // \\\"_selectorCount >> 3\\\" is a gas efficient division by 8 \\\"_selectorCount / 8\\\"\\n uint256 selectorSlotCount = _selectorCount >> 3;\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotIndex = _selectorCount & 7;\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n if (_selectorSlot == 0) {\\n // get last selectorSlot\\n selectorSlotCount--;\\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\\n selectorInSlotIndex = 7;\\n } else {\\n selectorInSlotIndex--;\\n }\\n bytes4 lastSelector;\\n uint256 oldSelectorsSlotCount;\\n uint256 oldSelectorInSlotPosition;\\n // adding a block here prevents stack too deep error\\n {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) != address(0),\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\n );\\n // only useful if immutable functions exist\\n require(\\n address(bytes20(oldFacet)) != address(this),\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\n );\\n // replace selector with last selector in ds.facets\\n // gets the last selector\\n lastSelector = bytes4(\\n _selectorSlot << (selectorInSlotIndex << 5)\\n );\\n if (lastSelector != selector) {\\n // update last selector slot position info\\n ds.facets[lastSelector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(ds.facets[lastSelector]);\\n }\\n delete ds.facets[selector];\\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\\n // \\\"oldSelectorCount >> 3\\\" is a gas efficient division by 8 \\\"oldSelectorCount / 8\\\"\\n oldSelectorsSlotCount = oldSelectorCount >> 3;\\n // \\\"oldSelectorCount & 7\\\" is a gas efficient modulo by eight \\\"oldSelectorCount % 8\\\"\\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\\n }\\n if (oldSelectorsSlotCount != selectorSlotCount) {\\n bytes32 oldSelectorSlot = ds.selectorSlots[\\n oldSelectorsSlotCount\\n ];\\n // clears the selector we are deleting and puts the last selector in its place.\\n oldSelectorSlot =\\n (oldSelectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n // update storage with the modified slot\\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\\n } else {\\n // clears the selector we are deleting and puts the last selector in its place.\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n }\\n if (selectorInSlotIndex == 0) {\\n delete ds.selectorSlots[selectorSlotCount];\\n _selectorSlot = 0;\\n }\\n }\\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n return (_selectorCount, _selectorSlot);\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\n internal\\n {\\n if (_init == address(0)) {\\n require(\\n _calldata.length == 0,\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\n );\\n } else {\\n require(\\n _calldata.length > 0,\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\n );\\n if (_init != address(this)) {\\n enforceHasContractCode(\\n _init,\\n \\\"LibDiamondCut: _init address has no code\\\"\\n );\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(\\n address _contract,\\n string memory _errorMessage\\n ) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x740ea3845282f09bb822e66a189ed431ac799ab08184de7457ef53799b2e99d6\",\"license\":\"MIT\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"},\"contracts/upgrade_initializers/DiamondInit.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Diamond Initialization Contract\\npragma solidity ^0.8.0;\\n\\n// Rollups-related dependencies\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\n// Diamond-related dependencies\\nimport {LibDiamond} from \\\"../libraries/LibDiamond.sol\\\";\\nimport {IDiamondLoupe} from \\\"../interfaces/IDiamondLoupe.sol\\\";\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\nimport {IERC173} from \\\"../interfaces/IERC173.sol\\\"; // not in openzeppelin-contracts yet\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\n/// @notice diamond configurations\\n/// @param templateHash state hash of the cartesi machine at t0\\n/// @param inputDuration duration of input accumulation phase in seconds\\n/// @param challengePeriod duration of challenge period in seconds\\n/// @param inputLog2Size size of the input memory range in this machine\\n/// @param feePerClaim fee per claim to reward the validators\\n/// @param feeManagerBank fee manager bank address\\n/// @param feeManagerOwner fee manager owner address\\n/// @param validators initial validator set\\n/// @dev validators have to be unique, if the same validator is added twice\\n/// consensus will never be reached\\nstruct DiamondConfig {\\n // RollupsFacet\\n bytes32 templateHash;\\n uint256 inputDuration;\\n uint256 challengePeriod;\\n // InputFacet\\n uint256 inputLog2Size;\\n // FeeManagerFacet\\n uint256 feePerClaim;\\n address feeManagerBank;\\n address feeManagerOwner;\\n // ValidatorManagerFacet\\n address payable[] validators;\\n}\\n\\ncontract DiamondInit {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibInput for LibInput.DiamondStorage;\\n\\n /// @notice initialize the diamond\\n /// @param _dConfig diamond configurations\\n function init(DiamondConfig calldata _dConfig) external {\\n initERC165();\\n initValidatorManager(_dConfig.validators);\\n initRollups(\\n _dConfig.templateHash,\\n _dConfig.inputDuration,\\n _dConfig.challengePeriod\\n );\\n initFeeManager(\\n _dConfig.feePerClaim,\\n _dConfig.feeManagerBank,\\n _dConfig.feeManagerOwner\\n );\\n initInput(_dConfig.inputLog2Size);\\n }\\n\\n /// @notice initialize ERC165 data\\n function initERC165() private {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n ds.supportedInterfaces[type(IERC165).interfaceId] = true;\\n ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;\\n ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;\\n ds.supportedInterfaces[type(IERC173).interfaceId] = true;\\n }\\n\\n /// @notice initalize the Input facet\\n /// @param _inputLog2Size size of the input memory range in this machine\\n function initInput(uint256 _inputLog2Size) private {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n\\n require(\\n _inputLog2Size >= 3 && _inputLog2Size <= 64,\\n \\\"Log of input size: [3,64]\\\"\\n );\\n\\n inputDS.inputDriveSize = (1 << _inputLog2Size);\\n\\n // input box gets initialized with one empty input\\n // so that the L2 DApp knows it's own address\\n inputDS.addInternalInput(\\\"\\\");\\n }\\n\\n /// @notice initialize the Validator Manager facet\\n /// @param _validators initial validator set\\n function initValidatorManager(address payable[] memory _validators)\\n private\\n {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n uint256 maxNumValidators = _validators.length;\\n\\n require(maxNumValidators <= 8, \\\"up to 8 validators\\\");\\n\\n validatorManagerDS.validators = _validators;\\n validatorManagerDS.maxNumValidators = maxNumValidators;\\n\\n // create a new ClaimsMask, with only the consensus goal set,\\n // according to the number of validators\\n validatorManagerDS.claimsMask = LibClaimsMask\\n .newClaimsMaskWithConsensusGoalSet(maxNumValidators);\\n }\\n\\n /// @notice rollups contract initialized\\n /// @param inputDuration duration of input accumulation phase in seconds\\n /// @param challengePeriod duration of challenge period in seconds\\n event RollupsInitialized(uint256 inputDuration, uint256 challengePeriod);\\n\\n /// @notice initialize the Rollups facet\\n /// @param _templateHash state hash of the cartesi machine at t0\\n /// @param _inputDuration duration of input accumulation phase in seconds\\n /// @param _challengePeriod duration of challenge period in seconds\\n function initRollups(\\n bytes32 _templateHash,\\n uint256 _inputDuration,\\n uint256 _challengePeriod\\n ) private {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n rollupsDS.templateHash = _templateHash;\\n rollupsDS.inputDuration = uint32(_inputDuration);\\n rollupsDS.challengePeriod = uint32(_challengePeriod);\\n rollupsDS.inputAccumulationStart = uint32(block.timestamp);\\n rollupsDS.currentPhase_int = uint32(Phase.InputAccumulation);\\n\\n emit RollupsInitialized(_inputDuration, _challengePeriod);\\n }\\n\\n /// @notice FeeManagerImpl contract initialized\\n /// @param feePerClaim fee per claim to reward the validators\\n /// @param feeManagerBank fee manager bank address\\n /// @param feeManagerOwner fee manager owner address\\n event FeeManagerInitialized(\\n uint256 feePerClaim,\\n address feeManagerBank,\\n address feeManagerOwner\\n );\\n\\n /// @notice initalize the Fee Manager facet\\n /// @param _feePerClaim fee per claim to reward the validators\\n /// @param _feeManagerBank fee manager bank address\\n /// @param _feeManagerOwner fee manager owner address\\n function initFeeManager(\\n uint256 _feePerClaim,\\n address _feeManagerBank,\\n address _feeManagerOwner\\n ) private {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n\\n feeManagerDS.feePerClaim = _feePerClaim;\\n feeManagerDS.bank = IBank(_feeManagerBank);\\n feeManagerDS.owner = _feeManagerOwner;\\n\\n emit FeeManagerInitialized(\\n _feePerClaim,\\n _feeManagerBank,\\n _feeManagerOwner\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe627b754df9ee7265f1031cc946bb27d1de8dbb29a7e745453682420b5d9ee76\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60e06040523480156200001157600080fd5b5060405162003159380380620031598339810160408190526200003491620002d9565b80516001600160a01b039081166080526020820151811660a05260408201511660c05260005b8160600151518110156200012f57600082606001518281518110620000835762000083620004e0565b60209081029190910181015182546001810184556000938452928290208151600294850290910180546001600160a01b039092166001600160a01b0319831681178255938301519294909384926001600160a81b0319161790600160a01b908490811115620000f657620000f6620004f6565b0217905550604082015180516200011891600184019160209091019062000137565b5050508062000127906200050c565b90506200005a565b505062000534565b82805482825590600052602060002090600701600890048101928215620001d85791602002820160005b83821115620001a457835183826101000a81548163ffffffff021916908360e01c0217905550926020019260040160208160030104928301926001030262000161565b8015620001d65782816101000a81549063ffffffff0219169055600401602081600301049283019260010302620001a4565b505b50620001e6929150620001ea565b5090565b5b80821115620001e65760008155600101620001eb565b634e487b7160e01b600052604160045260246000fd5b604051608081016001600160401b03811182821017156200023c576200023c62000201565b60405290565b604051606081016001600160401b03811182821017156200023c576200023c62000201565b604051601f8201601f191681016001600160401b038111828210171562000292576200029262000201565b604052919050565b6001600160a01b0381168114620002b057600080fd5b50565b60006001600160401b03821115620002cf57620002cf62000201565b5060051b60200190565b60006020808385031215620002ed57600080fd5b82516001600160401b03808211156200030557600080fd5b90840190608082870312156200031a57600080fd5b6200032462000217565b825162000331816200029a565b81528284015162000342816200029a565b81850152604083015162000356816200029a565b60408201526060830151828111156200036e57600080fd5b80840193505086601f8401126200038457600080fd5b82516200039b6200039582620002b3565b62000267565b81815260059190911b84018501908581019089831115620003bb57600080fd5b8686015b83811015620004cd57805186811115620003d857600080fd5b87016060818d03601f19011215620003ef57600080fd5b620003f962000242565b8982015162000408816200029a565b81526040820151600381106200041d57600080fd5b818b01526060820151888111156200043457600080fd5b8083019250508c603f8301126200044a57600080fd5b898201516200045d6200039582620002b3565b81815260059190911b8301604001908b8101908f8311156200047e57600080fd5b6040850194505b82851015620004b75784516001600160e01b031981168114620004a757600080fd5b8252938c0193908c019062000485565b60408401525050845250918701918701620003bf565b5060608401525090979650505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b6000600182016200052d57634e487b7160e01b600052601160045260246000fd5b5060010190565b60805160a05160c051612be2620005776000396000818160f1015261022201526000818161011901526102ce01526000818160c9015261017c0152612be26000f3fe60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806304c01cc7146200006357806394a28f321462000093578063a051e9b314620000c3578063aa9a6e9114620000eb578063e6ee1d4f1462000113575b600080fd5b6200007a6200007436600462000456565b6200013b565b6040516200008a92919062000493565b60405180910390f35b620000aa620000a4366004620004b9565b62000176565b6040516001600160a01b0390911681526020016200008a565b620000aa7f000000000000000000000000000000000000000000000000000000000000000081565b620000aa7f000000000000000000000000000000000000000000000000000000000000000081565b620000aa7f000000000000000000000000000000000000000000000000000000000000000081565b600081815481106200014c57600080fd5b60009182526020909120600290910201546001600160a01b0381169150600160a01b900460ff1682565b600080307f0000000000000000000000000000000000000000000000000000000000000000604051620001a99062000448565b6001600160a01b03928316815291166020820152604001604051809103906000f080158015620001dd573d6000803e3d6000fd5b5090506000604051806101000160405280856020013581526020018560400135815260200185606001358152602001856080013581526020018560a0013581526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018560c001602081019062000264919062000523565b6001600160a01b031681526020016200028160e087018762000543565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509390945250506040519293506001600160a01b03851692631f931c1c92507f00000000000000000000000000000000000000000000000000000000000000009063af52770160e01b9062000307908790602401620005dd565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e086901b909216825262000350939291600401620006b8565b600060405180830381600087803b1580156200036b57600080fd5b505af115801562000380573d6000803e3d6000fd5b5050506001600160a01b038316905063f2fde38b620003a3602087018762000523565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015620003e557600080fd5b505af1158015620003fa573d6000803e3d6000fd5b50505050816001600160a01b03167f43883daeb0f23afe0fbb9658d1d4c08379520e9654a30f7ea3a9fb3a8f5195bb8560405162000439919062000a2b565b60405180910390a25092915050565b6120df8062000ace83390190565b6000602082840312156200046957600080fd5b5035919050565b600381106200048f57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160a01b038316815260408101620004b2602083018462000470565b9392505050565b600060208284031215620004cc57600080fd5b813567ffffffffffffffff811115620004e457600080fd5b82016101008185031215620004b257600080fd5b6001600160a01b03811681146200050e57600080fd5b50565b80356200051e81620004f8565b919050565b6000602082840312156200053657600080fd5b8135620004b281620004f8565b6000808335601e198436030181126200055b57600080fd5b83018035915067ffffffffffffffff8211156200057757600080fd5b6020019150600581901b36038213156200059057600080fd5b9250929050565b600081518084526020808501945080840160005b83811015620005d25781516001600160a01b031687529582019590820190600101620005ab565b509495945050505050565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a083015160018060a01b0380821660c08501528060c08601511660e0850152505060e08301516101008081850152506200065261012084018262000597565b949350505050565b6001600160e01b0319169052565b6000815180845260005b81811015620006905760208185018101518683018201520162000672565b81811115620006a3576000602083870101525b50601f01601f19169290920160200192915050565b60608152600060608201855480825260808401915060808160051b8501018760005260208060002060005b848110156200096d57878403607f1901865281546001600160a01b038116855260608501906200071d85870160a083901c60ff1662000470565b506060604086015260018381018054808452600091825260208083209401905b80600784011015620008055784546200075a838260e01b6200065a565b6001600160e01b031962000777848b0160c084901b83166200065a565b6200078b60408501828460a01b166200065a565b6200079f60608501828460801b166200065a565b620007b360808501828460601b166200065a565b620007c760a08501828460401b166200065a565b620007da60c0850182848d1b166200065a565b620007eb60e085018284166200065a565b50506101008201915083850194506008830192506200073d565b93549380831015620008295762000820828660e01b6200065a565b91830191908701905b8083101562000855576200084c8260c087901b6001600160e01b0319166200065a565b91830191908701905b808310156200088157620008788260a087901b6001600160e01b0319166200065a565b91830191908701905b80831015620008ad57620008a482608087901b6001600160e01b0319166200065a565b91830191908701905b80831015620008d957620008d082606087901b6001600160e01b0319166200065a565b91830191908701905b808310156200090557620008fc82604087901b6001600160e01b0319166200065a565b91830191908701905b808310156200092f576200092682868a1b6001600160e01b0319166200065a565b91830191908701905b8083101562000953576200094e826001600160e01b031987166200065a565b908701905b5098860198965050506002929092019150600101620006e3565b50506001600160a01b03881690860152848103604086015262000991818762000668565b98975050505050505050565b6000808335601e19843603018112620009b557600080fd5b830160208101925035905067ffffffffffffffff811115620009d657600080fd5b8060051b36038313156200059057600080fd5b8183526000602080850194508260005b85811015620005d257813562000a0f81620004f8565b6001600160a01b031687529582019590820190600101620009f9565b602081526000823562000a3e81620004f8565b60018060a01b038116602084015250602083013560408301526040830135606083015260608301356080830152608083013560a083015260a083013560c083015262000a8d60c0840162000511565b6001600160a01b03811660e08401525062000aac60e08401846200099d565b6101008481015262000ac461012085018284620009e9565b9594505050505056fe6080604052604051620020df380380620020df833981016040819052620000269162000ddc565b6200003c826200015660201b620000b01760201c565b604080516001808252818301909252600091816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081620000535750506040805160018082528183019092529192506000919060208083019080368337019050509050631f931c1c60e01b81600081518110620000c657620000c662000e14565b6001600160e01b031990921660209283029190910182015260408051606081019091526001600160a01b038516815290810160008152602001828152508260008151811062000119576200011962000e14565b60200260200101819052506200014c82600060405180602001604052806000815250620001da60201b620001331760201c565b5050505062001067565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b038481169182179093556040516000805160206200204b833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e546000805160206200204b8339815191529061ffff811690819060009060071615620002395750600381901c60009081526001840160205260409020545b60005b8751811015620002d557620002bb83838a848151811062000261576200026162000e14565b6020026020010151600001518b858151811062000282576200028262000e14565b6020026020010151602001518c8681518110620002a357620002a362000e14565b6020026020010151604001516200036760201b60201c565b909350915080620002cc8162000e56565b9150506200023c565b50828214620002f25760028401805461ffff191661ffff84161790555b60078216156200031557600382901c600090815260018501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516200034a9392919062000ecf565b60405180910390a16200035e868662000b76565b50505050505050565b600080806000805160206200204b83398151915290506000845111620003e85760405162461bcd60e51b815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201526a1858d95d081d1bc818dd5d60aa1b60648201526084015b60405180910390fd5b6000856002811115620003ff57620003ff62000e2a565b0362000585576200042a866040518060600160405280602481526020016200206b6024913962000d9b565b60005b84518110156200057e5760008582815181106200044e576200044e62000e14565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c15620004f15760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401620003df565b6001600160e01b031980831660008181526020879052604090206001600160601b031960608d901b168e17905560e060058e901b811692831c199c909c1690821c179a819003620005565760038c901c600090815260018601602052604081209b909b555b8b620005628162000e56565b9c50505050508080620005759062000e56565b9150506200042d565b5062000b6a565b60018560028111156200059c576200059c62000e2a565b03620007b557620005c786604051806060016040528060288152602001620020b76028913962000d9b565b60005b84518110156200057e576000858281518110620005eb57620005eb62000e14565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c308103620006825760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e2774207265706c61636520696d6d60448201526e3aba30b1363290333ab731ba34b7b760891b6064820152608401620003df565b896001600160a01b0316816001600160a01b031603620006fa5760405162461bcd60e51b815260206004820152603860248201526000805160206200202b83398151915260448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401620003df565b6001600160a01b038116620007675760405162461bcd60e51b815260206004820152603860248201526000805160206200202b83398151915260448201527f6374696f6e207468617420646f65736e277420657869737400000000000000006064820152608401620003df565b506001600160e01b031990911660009081526020849052604090206001600160601b03919091166001600160601b031960608a901b1617905580620007ac8162000e56565b915050620005ca565b6002856002811115620007cc57620007cc62000e2a565b0362000b11576001600160a01b03861615620008515760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401620003df565b600388901c6007891660005b865181101562000aec5760008a90036200089e57826200087d8162000fd6565b60008181526001870160205260409020549b50935060079250620008ae9050565b81620008aa8162000fd6565b9250505b6000806000808a8581518110620008c957620008c962000e14565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c6200096b5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401620003df565b30606082901c03620009d75760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401620003df565b600587901b8f901b94506001600160e01b03198086169083161462000a29576001600160e01b03198516600090815260208a90526040902080546001600160601b0319166001600160601b0383161790555b6001600160e01b031991909116600090815260208990526040812055600381901c611fff16925060051b60e016905085821462000a90576000828152600188016020526040902080546001600160e01b031980841c19909116908516831c17905562000ab4565b80836001600160e01b031916901c816001600160e01b031960001b901c198e16179c505b8460000362000ad357600086815260018801602052604081208190559c505b505050808062000ae39062000e56565b9150506200085d565b508062000afb83600862000ff0565b62000b07919062001012565b9950505062000b6a565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401620003df565b50959694955050505050565b6001600160a01b03821662000c005780511562000bfc5760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401620003df565b5050565b600081511162000c795760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401620003df565b6001600160a01b038216301462000caf5762000caf826040518060600160405280602881526020016200208f6028913962000d9b565b600080836001600160a01b03168360405162000ccc91906200102d565b600060405180830381855af49150503d806000811462000d09576040519150601f19603f3d011682016040523d82523d6000602084013e62000d0e565b606091505b50915091508162000d955780511562000d3d578060405162461bcd60e51b8152600401620003df91906200104b565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401620003df565b50505050565b813b818162000d955760405162461bcd60e51b8152600401620003df91906200104b565b80516001600160a01b038116811462000dd757600080fd5b919050565b6000806040838503121562000df057600080fd5b62000dfb8362000dbf565b915062000e0b6020840162000dbf565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162000e6b5762000e6b62000e40565b5060010190565b60005b8381101562000e8f57818101518382015260200162000e75565b8381111562000d955750506000910152565b6000815180845262000ebb81602086016020860162000e72565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b8481101562000fa457898403607f19018652815180516001600160a01b0316855283810151898601906003811062000f4057634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b8083101562000f8e5783516001600160e01b031916825292860192600192909201919086019062000f62565b5097850197955050509082019060010162000ef8565b50506001600160a01b038a1690880152868103604088015262000fc8818962000ea1565b9a9950505050505050505050565b60008162000fe85762000fe862000e40565b506000190190565b60008160001904831182151516156200100d576200100d62000e40565b500290565b6000821982111562001028576200102862000e40565b500190565b600082516200104181846020870162000e72565b9190910192915050565b60208152600062001060602083018462000ea1565b9392505050565b610fb480620010776000396000f3fe60806040523661000b57005b600080356001600160e01b0319168152600080516020610eeb8339815191526020819052604090912054819060601c8061008c5760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b3660008037600080366000845af43d6000803e8080156100ab573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b03848116918217909355604051600080516020610eeb833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54600080516020610eeb8339815191529061ffff8116908190600090600716156101905750600381901c60009081526001840160205260409020545b60005b87518110156102175761020083838a84815181106101b3576101b3610cb3565b6020026020010151600001518b85815181106101d1576101d1610cb3565b6020026020010151602001518c86815181106101ef576101ef610cb3565b6020026020010151604001516102a3565b90935091508061020f81610cdf565b915050610193565b508282146102335760028401805461ffff191661ffff84161790555b600782161561025557600382901c600090815260018501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67387878760405161028893929190610d66565b60405180910390a161029a8686610a7f565b50505050505050565b60008080600080516020610eeb8339815191529050600084511161031d5760405162461bcd60e51b815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401610083565b600085600281111561033157610331610cf8565b0361049e5761035886604051806060016040528060248152602001610f0b60249139610c92565b60005b845181101561049857600085828151811061037857610378610cb3565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c156104115760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610083565b6001600160e01b031980831660008181526020879052604090206001600160601b031960608d901b168e17905560e060058e901b811692831c199c909c1690821c179a8190036104755760038c901c600090815260018601602052604081209b909b555b8b61047f81610cdf565b9c5050505050808061049090610cdf565b91505061035b565b50610a73565b60018560028111156104b2576104b2610cf8565b036106e1576104d986604051806060016040528060288152602001610f5760289139610c92565b60005b84518110156104985760008582815181106104f9576104f9610cb3565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c30810361058e5760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e2774207265706c61636520696d6d60448201526e3aba30b1363290333ab731ba34b7b760891b6064820152608401610083565b896001600160a01b0316816001600160a01b0316036106155760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610083565b6001600160a01b0381166106915760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e207468617420646f65736e277420657869737400000000000000006064820152608401610083565b506001600160e01b031990911660009081526020849052604090206bffffffffffffffffffffffff919091166001600160601b031960608a901b16179055806106d981610cdf565b9150506104dc565b60028560028111156106f5576106f5610cf8565b03610a1b576001600160a01b038616156107705760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610083565b600388901c6007891660005b86518110156109fb5760008a90036107b8578261079881610e66565b60008181526001870160205260409020549b509350600792506107c69050565b816107c281610e66565b9250505b6000806000808a85815181106107de576107de610cb3565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c61087e5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610083565b30606082901c036108e85760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401610083565b600587901b8f901b94506001600160e01b03198086169083161461093e576001600160e01b03198516600090815260208a90526040902080546001600160601b0319166bffffffffffffffffffffffff83161790555b6001600160e01b031991909116600090815260208990526040812055600381901c611fff16925060051b60e01690508582146109a3576000828152600188016020526040902080546001600160e01b031980841c19909116908516831c1790556109c7565b80836001600160e01b031916901c816001600160e01b031960001b901c198e16179c505b846000036109e557600086815260018801602052604081208190559c505b50505080806109f390610cdf565b91505061077c565b5080610a08836008610e7d565b610a129190610e9c565b99505050610a73565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610083565b50959694955050505050565b6001600160a01b038216610b0657805115610b025760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401610083565b5050565b6000815111610b7d5760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401610083565b6001600160a01b0382163014610baf57610baf82604051806060016040528060288152602001610f2f60289139610c92565b600080836001600160a01b031683604051610bca9190610eb4565b600060405180830381855af49150503d8060008114610c05576040519150601f19603f3d011682016040523d82523d6000602084013e610c0a565b606091505b509150915081610c8c57805115610c35578060405162461bcd60e51b81526004016100839190610ed0565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401610083565b50505050565b813b8181610c8c5760405162461bcd60e51b81526004016100839190610ed0565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610cf157610cf1610cc9565b5060010190565b634e487b7160e01b600052602160045260246000fd5b60005b83811015610d29578181015183820152602001610d11565b83811115610c8c5750506000910152565b60008151808452610d52816020860160208601610d0e565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015610e3657898403607f19018652815180516001600160a01b03168552838101518986019060038110610dd557634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610e215783516001600160e01b0319168252928601926001929092019190860190610df7565b50978501979550505090820190600101610d8f565b50506001600160a01b038a16908801528681036040880152610e588189610d3a565b9a9950505050505050505050565b600081610e7557610e75610cc9565b506000190190565b6000816000190483118215151615610e9757610e97610cc9565b500290565b60008219821115610eaf57610eaf610cc9565b500190565b60008251610ec6818460208701610d0e565b9190910192915050565b602081526000610ee36020830184610d3a565b939250505056fec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a26469706673582212204e6b6e58423be59a39c21641051d6bd7ed7f64b27b6fdcbcf32291c98ddd811464736f6c634300080d00334c69624469616d6f6e644375743a2043616e2774207265706c6163652066756ec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a26469706673582212201c0e6f375f8505b9e5db7032e1ce2d96f6ef6969666f191881207364ed6a5e7e64736f6c634300080d0033", + "deployedBytecode": "0x60806040523480156200001157600080fd5b50600436106200005e5760003560e01c806304c01cc7146200006357806394a28f321462000093578063a051e9b314620000c3578063aa9a6e9114620000eb578063e6ee1d4f1462000113575b600080fd5b6200007a6200007436600462000456565b6200013b565b6040516200008a92919062000493565b60405180910390f35b620000aa620000a4366004620004b9565b62000176565b6040516001600160a01b0390911681526020016200008a565b620000aa7f000000000000000000000000000000000000000000000000000000000000000081565b620000aa7f000000000000000000000000000000000000000000000000000000000000000081565b620000aa7f000000000000000000000000000000000000000000000000000000000000000081565b600081815481106200014c57600080fd5b60009182526020909120600290910201546001600160a01b0381169150600160a01b900460ff1682565b600080307f0000000000000000000000000000000000000000000000000000000000000000604051620001a99062000448565b6001600160a01b03928316815291166020820152604001604051809103906000f080158015620001dd573d6000803e3d6000fd5b5090506000604051806101000160405280856020013581526020018560400135815260200185606001358152602001856080013581526020018560a0013581526020017f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031681526020018560c001602081019062000264919062000523565b6001600160a01b031681526020016200028160e087018762000543565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201829052509390945250506040519293506001600160a01b03851692631f931c1c92507f00000000000000000000000000000000000000000000000000000000000000009063af52770160e01b9062000307908790602401620005dd565b60408051601f198184030181529181526020820180516001600160e01b03166001600160e01b03199485161790525160e086901b909216825262000350939291600401620006b8565b600060405180830381600087803b1580156200036b57600080fd5b505af115801562000380573d6000803e3d6000fd5b5050506001600160a01b038316905063f2fde38b620003a3602087018762000523565b6040516001600160e01b031960e084901b1681526001600160a01b039091166004820152602401600060405180830381600087803b158015620003e557600080fd5b505af1158015620003fa573d6000803e3d6000fd5b50505050816001600160a01b03167f43883daeb0f23afe0fbb9658d1d4c08379520e9654a30f7ea3a9fb3a8f5195bb8560405162000439919062000a2b565b60405180910390a25092915050565b6120df8062000ace83390190565b6000602082840312156200046957600080fd5b5035919050565b600381106200048f57634e487b7160e01b600052602160045260246000fd5b9052565b6001600160a01b038316815260408101620004b2602083018462000470565b9392505050565b600060208284031215620004cc57600080fd5b813567ffffffffffffffff811115620004e457600080fd5b82016101008185031215620004b257600080fd5b6001600160a01b03811681146200050e57600080fd5b50565b80356200051e81620004f8565b919050565b6000602082840312156200053657600080fd5b8135620004b281620004f8565b6000808335601e198436030181126200055b57600080fd5b83018035915067ffffffffffffffff8211156200057757600080fd5b6020019150600581901b36038213156200059057600080fd5b9250929050565b600081518084526020808501945080840160005b83811015620005d25781516001600160a01b031687529582019590820190600101620005ab565b509495945050505050565b6020815281516020820152602082015160408201526040820151606082015260608201516080820152608082015160a0820152600060a083015160018060a01b0380821660c08501528060c08601511660e0850152505060e08301516101008081850152506200065261012084018262000597565b949350505050565b6001600160e01b0319169052565b6000815180845260005b81811015620006905760208185018101518683018201520162000672565b81811115620006a3576000602083870101525b50601f01601f19169290920160200192915050565b60608152600060608201855480825260808401915060808160051b8501018760005260208060002060005b848110156200096d57878403607f1901865281546001600160a01b038116855260608501906200071d85870160a083901c60ff1662000470565b506060604086015260018381018054808452600091825260208083209401905b80600784011015620008055784546200075a838260e01b6200065a565b6001600160e01b031962000777848b0160c084901b83166200065a565b6200078b60408501828460a01b166200065a565b6200079f60608501828460801b166200065a565b620007b360808501828460601b166200065a565b620007c760a08501828460401b166200065a565b620007da60c0850182848d1b166200065a565b620007eb60e085018284166200065a565b50506101008201915083850194506008830192506200073d565b93549380831015620008295762000820828660e01b6200065a565b91830191908701905b8083101562000855576200084c8260c087901b6001600160e01b0319166200065a565b91830191908701905b808310156200088157620008788260a087901b6001600160e01b0319166200065a565b91830191908701905b80831015620008ad57620008a482608087901b6001600160e01b0319166200065a565b91830191908701905b80831015620008d957620008d082606087901b6001600160e01b0319166200065a565b91830191908701905b808310156200090557620008fc82604087901b6001600160e01b0319166200065a565b91830191908701905b808310156200092f576200092682868a1b6001600160e01b0319166200065a565b91830191908701905b8083101562000953576200094e826001600160e01b031987166200065a565b908701905b5098860198965050506002929092019150600101620006e3565b50506001600160a01b03881690860152848103604086015262000991818762000668565b98975050505050505050565b6000808335601e19843603018112620009b557600080fd5b830160208101925035905067ffffffffffffffff811115620009d657600080fd5b8060051b36038313156200059057600080fd5b8183526000602080850194508260005b85811015620005d257813562000a0f81620004f8565b6001600160a01b031687529582019590820190600101620009f9565b602081526000823562000a3e81620004f8565b60018060a01b038116602084015250602083013560408301526040830135606083015260608301356080830152608083013560a083015260a083013560c083015262000a8d60c0840162000511565b6001600160a01b03811660e08401525062000aac60e08401846200099d565b6101008481015262000ac461012085018284620009e9565b9594505050505056fe6080604052604051620020df380380620020df833981016040819052620000269162000ddc565b6200003c826200015660201b620000b01760201c565b604080516001808252818301909252600091816020015b60408051606080820183526000808352602083015291810191909152815260200190600190039081620000535750506040805160018082528183019092529192506000919060208083019080368337019050509050631f931c1c60e01b81600081518110620000c657620000c662000e14565b6001600160e01b031990921660209283029190910182015260408051606081019091526001600160a01b038516815290810160008152602001828152508260008151811062000119576200011962000e14565b60200260200101819052506200014c82600060405180602001604052806000815250620001da60201b620001331760201c565b5050505062001067565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b038481169182179093556040516000805160206200204b833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e546000805160206200204b8339815191529061ffff811690819060009060071615620002395750600381901c60009081526001840160205260409020545b60005b8751811015620002d557620002bb83838a848151811062000261576200026162000e14565b6020026020010151600001518b858151811062000282576200028262000e14565b6020026020010151602001518c8681518110620002a357620002a362000e14565b6020026020010151604001516200036760201b60201c565b909350915080620002cc8162000e56565b9150506200023c565b50828214620002f25760028401805461ffff191661ffff84161790555b60078216156200031557600382901c600090815260018501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738787876040516200034a9392919062000ecf565b60405180910390a16200035e868662000b76565b50505050505050565b600080806000805160206200204b83398151915290506000845111620003e85760405162461bcd60e51b815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201526a1858d95d081d1bc818dd5d60aa1b60648201526084015b60405180910390fd5b6000856002811115620003ff57620003ff62000e2a565b0362000585576200042a866040518060600160405280602481526020016200206b6024913962000d9b565b60005b84518110156200057e5760008582815181106200044e576200044e62000e14565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c15620004f15760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c72656164792065786973747300000000000000000000006064820152608401620003df565b6001600160e01b031980831660008181526020879052604090206001600160601b031960608d901b168e17905560e060058e901b811692831c199c909c1690821c179a819003620005565760038c901c600090815260018601602052604081209b909b555b8b620005628162000e56565b9c50505050508080620005759062000e56565b9150506200042d565b5062000b6a565b60018560028111156200059c576200059c62000e2a565b03620007b557620005c786604051806060016040528060288152602001620020b76028913962000d9b565b60005b84518110156200057e576000858281518110620005eb57620005eb62000e14565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c308103620006825760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e2774207265706c61636520696d6d60448201526e3aba30b1363290333ab731ba34b7b760891b6064820152608401620003df565b896001600160a01b0316816001600160a01b031603620006fa5760405162461bcd60e51b815260206004820152603860248201526000805160206200202b83398151915260448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401620003df565b6001600160a01b038116620007675760405162461bcd60e51b815260206004820152603860248201526000805160206200202b83398151915260448201527f6374696f6e207468617420646f65736e277420657869737400000000000000006064820152608401620003df565b506001600160e01b031990911660009081526020849052604090206001600160601b03919091166001600160601b031960608a901b1617905580620007ac8162000e56565b915050620005ca565b6002856002811115620007cc57620007cc62000e2a565b0362000b11576001600160a01b03861615620008515760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d7573742062652061646472657373283029000000000000000000006064820152608401620003df565b600388901c6007891660005b865181101562000aec5760008a90036200089e57826200087d8162000fd6565b60008181526001870160205260409020549b50935060079250620008ae9050565b81620008aa8162000fd6565b9250505b6000806000808a8581518110620008c957620008c962000e14565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c6200096b5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401620003df565b30606082901c03620009d75760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401620003df565b600587901b8f901b94506001600160e01b03198086169083161462000a29576001600160e01b03198516600090815260208a90526040902080546001600160601b0319166001600160601b0383161790555b6001600160e01b031991909116600090815260208990526040812055600381901c611fff16925060051b60e016905085821462000a90576000828152600188016020526040902080546001600160e01b031980841c19909116908516831c17905562000ab4565b80836001600160e01b031916901c816001600160e01b031960001b901c198e16179c505b8460000362000ad357600086815260018801602052604081208190559c505b505050808062000ae39062000e56565b9150506200085d565b508062000afb83600862000ff0565b62000b07919062001012565b9950505062000b6a565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401620003df565b50959694955050505050565b6001600160a01b03821662000c005780511562000bfc5760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401620003df565b5050565b600081511162000c795760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401620003df565b6001600160a01b038216301462000caf5762000caf826040518060600160405280602881526020016200208f6028913962000d9b565b600080836001600160a01b03168360405162000ccc91906200102d565b600060405180830381855af49150503d806000811462000d09576040519150601f19603f3d011682016040523d82523d6000602084013e62000d0e565b606091505b50915091508162000d955780511562000d3d578060405162461bcd60e51b8152600401620003df91906200104b565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401620003df565b50505050565b813b818162000d955760405162461bcd60e51b8152600401620003df91906200104b565b80516001600160a01b038116811462000dd757600080fd5b919050565b6000806040838503121562000df057600080fd5b62000dfb8362000dbf565b915062000e0b6020840162000dbf565b90509250929050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b60006001820162000e6b5762000e6b62000e40565b5060010190565b60005b8381101562000e8f57818101518382015260200162000e75565b8381111562000d955750506000910152565b6000815180845262000ebb81602086016020860162000e72565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b8481101562000fa457898403607f19018652815180516001600160a01b0316855283810151898601906003811062000f4057634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b8083101562000f8e5783516001600160e01b031916825292860192600192909201919086019062000f62565b5097850197955050509082019060010162000ef8565b50506001600160a01b038a1690880152868103604088015262000fc8818962000ea1565b9a9950505050505050505050565b60008162000fe85762000fe862000e40565b506000190190565b60008160001904831182151516156200100d576200100d62000e40565b500290565b6000821982111562001028576200102862000e40565b500190565b600082516200104181846020870162000e72565b9190910192915050565b60208152600062001060602083018462000ea1565b9392505050565b610fb480620010776000396000f3fe60806040523661000b57005b600080356001600160e01b0319168152600080516020610eeb8339815191526020819052604090912054819060601c8061008c5760405162461bcd60e51b815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b3660008037600080366000845af43d6000803e8080156100ab573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b03848116918217909355604051600080516020610eeb833981519152939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54600080516020610eeb8339815191529061ffff8116908190600090600716156101905750600381901c60009081526001840160205260409020545b60005b87518110156102175761020083838a84815181106101b3576101b3610cb3565b6020026020010151600001518b85815181106101d1576101d1610cb3565b6020026020010151602001518c86815181106101ef576101ef610cb3565b6020026020010151604001516102a3565b90935091508061020f81610cdf565b915050610193565b508282146102335760028401805461ffff191661ffff84161790555b600782161561025557600382901c600090815260018501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb67387878760405161028893929190610d66565b60405180910390a161029a8686610a7f565b50505050505050565b60008080600080516020610eeb8339815191529050600084511161031d5760405162461bcd60e51b815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201526a1858d95d081d1bc818dd5d60aa1b6064820152608401610083565b600085600281111561033157610331610cf8565b0361049e5761035886604051806060016040528060248152602001610f0b60249139610c92565b60005b845181101561049857600085828151811061037857610378610cb3565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c156104115760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b6064820152608401610083565b6001600160e01b031980831660008181526020879052604090206001600160601b031960608d901b168e17905560e060058e901b811692831c199c909c1690821c179a8190036104755760038c901c600090815260018601602052604081209b909b555b8b61047f81610cdf565b9c5050505050808061049090610cdf565b91505061035b565b50610a73565b60018560028111156104b2576104b2610cf8565b036106e1576104d986604051806060016040528060288152602001610f5760289139610c92565b60005b84518110156104985760008582815181106104f9576104f9610cb3565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c30810361058e5760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e2774207265706c61636520696d6d60448201526e3aba30b1363290333ab731ba34b7b760891b6064820152608401610083565b896001600160a01b0316816001600160a01b0316036106155760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e00000000000000006064820152608401610083565b6001600160a01b0381166106915760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e207468617420646f65736e277420657869737400000000000000006064820152608401610083565b506001600160e01b031990911660009081526020849052604090206bffffffffffffffffffffffff919091166001600160601b031960608a901b16179055806106d981610cdf565b9150506104dc565b60028560028111156106f5576106f5610cf8565b03610a1b576001600160a01b038616156107705760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b6064820152608401610083565b600388901c6007891660005b86518110156109fb5760008a90036107b8578261079881610e66565b60008181526001870160205260409020549b509350600792506107c69050565b816107c281610e66565b9250505b6000806000808a85815181106107de576107de610cb3565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c61087e5760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e27742065786973740000000000000000006064820152608401610083565b30606082901c036108e85760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b6064820152608401610083565b600587901b8f901b94506001600160e01b03198086169083161461093e576001600160e01b03198516600090815260208a90526040902080546001600160601b0319166bffffffffffffffffffffffff83161790555b6001600160e01b031991909116600090815260208990526040812055600381901c611fff16925060051b60e01690508582146109a3576000828152600188016020526040902080546001600160e01b031980841c19909116908516831c1790556109c7565b80836001600160e01b031916901c816001600160e01b031960001b901c198e16179c505b846000036109e557600086815260018801602052604081208190559c505b50505080806109f390610cdf565b91505061077c565b5080610a08836008610e7d565b610a129190610e9c565b99505050610a73565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b6064820152608401610083565b50959694955050505050565b6001600160a01b038216610b0657805115610b025760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d707479000000006064820152608401610083565b5050565b6000815111610b7d5760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f7420616464726573732830290000006064820152608401610083565b6001600160a01b0382163014610baf57610baf82604051806060016040528060288152602001610f2f60289139610c92565b600080836001600160a01b031683604051610bca9190610eb4565b600060405180830381855af49150503d8060008114610c05576040519150601f19603f3d011682016040523d82523d6000602084013e610c0a565b606091505b509150915081610c8c57805115610c35578060405162461bcd60e51b81526004016100839190610ed0565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b6064820152608401610083565b50505050565b813b8181610c8c5760405162461bcd60e51b81526004016100839190610ed0565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610cf157610cf1610cc9565b5060010190565b634e487b7160e01b600052602160045260246000fd5b60005b83811015610d29578181015183820152602001610d11565b83811115610c8c5750506000910152565b60008151808452610d52816020860160208601610d0e565b601f01601f19169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b84811015610e3657898403607f19018652815180516001600160a01b03168552838101518986019060038110610dd557634e487b7160e01b600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b80831015610e215783516001600160e01b0319168252928601926001929092019190860190610df7565b50978501979550505090820190600101610d8f565b50506001600160a01b038a16908801528681036040880152610e588189610d3a565b9a9950505050505050505050565b600081610e7557610e75610cc9565b506000190190565b6000816000190483118215151615610e9757610e97610cc9565b500290565b60008219821115610eaf57610eaf610cc9565b500190565b60008251610ec6818460208701610d0e565b9190910192915050565b602081526000610ee36020830184610d3a565b939250505056fec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a26469706673582212204e6b6e58423be59a39c21641051d6bd7ed7f64b27b6fdcbcf32291c98ddd811464736f6c634300080d00334c69624469616d6f6e644375743a2043616e2774207265706c6163652066756ec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a26469706673582212201c0e6f375f8505b9e5db7032e1ce2d96f6ef6969666f191881207364ed6a5e7e64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "newApplication((address,bytes32,uint256,uint256,uint256,uint256,address,address[]))": { + "params": { + "_appConfig": "application configurations" + }, + "returns": { + "_0": "application address" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "ApplicationCreated(address,(address,bytes32,uint256,uint256,uint256,uint256,address,address[]))": { + "notice": "Event emitted when a new application is deployed" + } + }, + "kind": "user", + "methods": { + "newApplication((address,bytes32,uint256,uint256,uint256,uint256,address,address[]))": { + "notice": "Deploy a new application" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 3727, + "contract": "contracts/CartesiDAppFactory.sol:CartesiDAppFactory", + "label": "diamondCut", + "offset": 0, + "slot": "0", + "type": "t_array(t_struct(FacetCut)6808_storage)dyn_storage" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_array(t_bytes4)dyn_storage": { + "base": "t_bytes4", + "encoding": "dynamic_array", + "label": "bytes4[]", + "numberOfBytes": "32" + }, + "t_array(t_struct(FacetCut)6808_storage)dyn_storage": { + "base": "t_struct(FacetCut)6808_storage", + "encoding": "dynamic_array", + "label": "struct IDiamondCut.FacetCut[]", + "numberOfBytes": "32" + }, + "t_bytes4": { + "encoding": "inplace", + "label": "bytes4", + "numberOfBytes": "4" + }, + "t_enum(FacetCutAction)6799": { + "encoding": "inplace", + "label": "enum IDiamondCut.FacetCutAction", + "numberOfBytes": "1" + }, + "t_struct(FacetCut)6808_storage": { + "encoding": "inplace", + "label": "struct IDiamondCut.FacetCut", + "members": [ + { + "astId": 6801, + "contract": "contracts/CartesiDAppFactory.sol:CartesiDAppFactory", + "label": "facetAddress", + "offset": 0, + "slot": "0", + "type": "t_address" + }, + { + "astId": 6804, + "contract": "contracts/CartesiDAppFactory.sol:CartesiDAppFactory", + "label": "action", + "offset": 20, + "slot": "0", + "type": "t_enum(FacetCutAction)6799" + }, + { + "astId": 6807, + "contract": "contracts/CartesiDAppFactory.sol:CartesiDAppFactory", + "label": "functionSelectors", + "offset": 0, + "slot": "1", + "type": "t_array(t_bytes4)dyn_storage" + } + ], + "numberOfBytes": "64" + } + } + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/CartesiMath.json b/echo-js/deployments/localhost/CartesiMath.json new file mode 100644 index 00000000..1db8b0c6 --- /dev/null +++ b/echo-js/deployments/localhost/CartesiMath.json @@ -0,0 +1,218 @@ +{ + "address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + "abi": [ + { + "inputs": [ + { + "internalType": "uint256", + "name": "_num", + "type": "uint256" + } + ], + "name": "clz", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_num", + "type": "uint256" + } + ], + "name": "ctz", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_num", + "type": "uint256" + } + ], + "name": "getLog2Floor", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_num", + "type": "uint256" + } + ], + "name": "getLog2TableTimes1M", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_num", + "type": "uint256" + } + ], + "name": "isPowerOf2", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_num", + "type": "uint256" + } + ], + "name": "log2ApproxTimes1M", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x7ade92f7ba8f601e08c7d0d3c49df65533e1d6cb495b8fcaac7aeef5f63d8659", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0", + "transactionIndex": 0, + "gasUsed": "479702", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x47692e638868cadc92222970bda062e7ea9612e7d7f2fb435e867a9b28ccb718", + "transactionHash": "0x7ade92f7ba8f601e08c7d0d3c49df65533e1d6cb495b8fcaac7aeef5f63d8659", + "logs": [], + "blockNumber": 3, + "cumulativeGasUsed": "479702", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"clz\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"ctz\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"getLog2Floor\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"getLog2TableTimes1M\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"isPowerOf2\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_num\",\"type\":\"uint256\"}],\"name\":\"log2ApproxTimes1M\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"clz(uint256)\":{\"details\":\"this a binary search implementation\",\"params\":{\"_num\":\"number you want the clz of\"}},\"ctz(uint256)\":{\"details\":\"this a binary search implementation\",\"params\":{\"_num\":\"number you want the ctz of\"}},\"getLog2Floor(uint256)\":{\"params\":{\"_num\":\"number to take floor(log2) of\"},\"returns\":{\"_0\":\"floor(log2) of _num\"}},\"getLog2TableTimes1M(uint256)\":{\"params\":{\"_num\":\"number to take log2 of\"},\"returns\":{\"_0\":\"result after table look-up\"}},\"isPowerOf2(uint256)\":{\"params\":{\"_num\":\"number to check\"},\"returns\":{\"_0\":\"true if number is power of 2, false if not\"}},\"log2ApproxTimes1M(uint256)\":{\"params\":{\"_num\":\"number to take log2 * 1M of\"},\"returns\":{\"_0\":\"approximate log2 times 1M\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"clz(uint256)\":{\"notice\":\"count leading zeros\"},\"ctz(uint256)\":{\"notice\":\"count trailing zeros\"},\"getLog2Floor(uint256)\":{\"notice\":\"get floor of log2 of number\"},\"getLog2TableTimes1M(uint256)\":{\"notice\":\"navigates log2tableTimes1M\"},\"isPowerOf2(uint256)\":{\"notice\":\"checks if a number is Power of 2\"},\"log2ApproxTimes1M(uint256)\":{\"notice\":\"Approximates log2 * 1M\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/CartesiMath.sol\":\"CartesiMath\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CartesiMath.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title CartesiMath\\n/// @author Felipe Argento\\npragma solidity ^0.8.0;\\n\\nlibrary CartesiMath {\\n // mapping values are packed as bytes3 each\\n // see test/TestCartesiMath.ts for decimal values\\n bytes constant log2tableTimes1M =\\n hex\\\"0000000F4240182F421E8480236E082771822AD63A2DC6C0305E8532B04834C96736B3C23876D73A187A3B9D4A3D09003E5EA63FA0C540D17741F28843057D440BA745062945F60246DC1047B917488DC7495ABA4A207C4ADF8A4B98544C4B404CF8AA4DA0E64E44434EE3054F7D6D5013B750A61A5134C851BFF05247BD52CC58534DE753CC8D54486954C19C55384255AC75561E50568DE956FB575766B057D00758376F589CFA5900BA5962BC59C3135A21CA5A7EF15ADA945B34BF5B8D805BE4DF5C3AEA5C8FA95CE3265D356C5D86835DD6735E25455E73005EBFAD5F0B525F55F75F9FA25FE85A60302460770860BD0A61023061467F6189FD61CCAE620E98624FBF62902762CFD5630ECD634D12638AA963C7966403DC643F7F647A8264B4E864EEB56527EC6560906598A365D029660724663D9766738566A8F066DDDA6712476746386779AF67ACAF67DF3A6811526842FA68743268A4FC68D55C6905536934E169640A6992CF69C13169EF326A1CD46A4A186A76FF6AA38C6ACFC0\\\";\\n\\n /// @notice Approximates log2 * 1M\\n /// @param _num number to take log2 * 1M of\\n /// @return approximate log2 times 1M\\n function log2ApproxTimes1M(uint256 _num) public pure returns (uint256) {\\n require(_num > 0, \\\"Number cannot be zero\\\");\\n uint256 leading = 0;\\n\\n if (_num == 1) return 0;\\n\\n while (_num > 128) {\\n _num = _num >> 1;\\n leading += 1;\\n }\\n return (leading * uint256(1000000)) + (getLog2TableTimes1M(_num));\\n }\\n\\n /// @notice navigates log2tableTimes1M\\n /// @param _num number to take log2 of\\n /// @return result after table look-up\\n function getLog2TableTimes1M(uint256 _num) public pure returns (uint256) {\\n bytes3 result = 0;\\n for (uint8 i = 0; i < 3; i++) {\\n bytes3 tempResult = log2tableTimes1M[(_num - 1) * 3 + i];\\n result = result | (tempResult >> (i * 8));\\n }\\n\\n return uint256(uint24(result));\\n }\\n\\n /// @notice get floor of log2 of number\\n /// @param _num number to take floor(log2) of\\n /// @return floor(log2) of _num\\n function getLog2Floor(uint256 _num) public pure returns (uint8) {\\n require(_num != 0, \\\"log of zero is undefined\\\");\\n\\n return uint8(255 - clz(_num));\\n }\\n\\n /// @notice checks if a number is Power of 2\\n /// @param _num number to check\\n /// @return true if number is power of 2, false if not\\n function isPowerOf2(uint256 _num) public pure returns (bool) {\\n if (_num == 0) return false;\\n\\n return _num & (_num - 1) == 0;\\n }\\n\\n /// @notice count trailing zeros\\n /// @param _num number you want the ctz of\\n /// @dev this a binary search implementation\\n function ctz(uint256 _num) public pure returns (uint256) {\\n if (_num == 0) return 256;\\n\\n uint256 n = 0;\\n if (_num & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { n = n + 128; _num = _num >> 128; }\\n if (_num & 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF == 0) { n = n + 64; _num = _num >> 64; }\\n if (_num & 0x00000000000000000000000000000000000000000000000000000000FFFFFFFF == 0) { n = n + 32; _num = _num >> 32; }\\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000FFFF == 0) { n = n + 16; _num = _num >> 16; }\\n if (_num & 0x00000000000000000000000000000000000000000000000000000000000000FF == 0) { n = n + 8; _num = _num >> 8; }\\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000000F == 0) { n = n + 4; _num = _num >> 4; }\\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000003 == 0) { n = n + 2; _num = _num >> 2; }\\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000001 == 0) { n = n + 1; }\\n\\n return n;\\n }\\n\\n /// @notice count leading zeros\\n /// @param _num number you want the clz of\\n /// @dev this a binary search implementation\\n function clz(uint256 _num) public pure returns (uint256) {\\n if (_num == 0) return 256;\\n\\n uint256 n = 0;\\n if (_num & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 == 0) { n = n + 128; _num = _num << 128; }\\n if (_num & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 == 0) { n = n + 64; _num = _num << 64; }\\n if (_num & 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 == 0) { n = n + 32; _num = _num << 32; }\\n if (_num & 0xFFFF000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 16; _num = _num << 16; }\\n if (_num & 0xFF00000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 8; _num = _num << 8; }\\n if (_num & 0xF000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 4; _num = _num << 4; }\\n if (_num & 0xC000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 2; _num = _num << 2; }\\n if (_num & 0x8000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 1; }\\n\\n return n;\\n }\\n}\\n\",\"keccak256\":\"0x28b74012e966438edff701decdc5ffd207b3f0244af65fbd7d397050986e58d4\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x6107b661003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061006c5760003560e01c806306c8e54b14610071578063296e7af81461009b57806330244f7a146100bc57806332ef283b146100cf578063d82ae4b1146100e2578063e3581b6814610105575b600080fd5b61008461007f36600461053b565b610118565b60405160ff90911681526020015b60405180910390f35b6100ae6100a936600461053b565b610186565b604051908152602001610092565b6100ae6100ca36600461053b565b610297565b6100ae6100dd36600461053b565b6103bc565b6100f56100f036600461053b565b61047b565b6040519015158152602001610092565b6100ae61011336600461053b565b61049e565b60008161016c5760405162461bcd60e51b815260206004820152601860248201527f6c6f67206f66207a65726f20697320756e646566696e6564000000000000000060448201526064015b60405180910390fd5b61017582610297565b6101809060ff6105b3565b92915050565b6000816101965750610100919050565b60006fffffffffffffffffffffffffffffffff83166101c4576101ba816080610553565b9050608083901c92505b67ffffffffffffffff83166101e8576101de816040610553565b9050604083901c92505b63ffffffff8316610208576101fe816020610553565b9050602083901c92505b61ffff83166102265761021c816010610553565b9050601083901c92505b60ff831661024357610239816008610553565b9050600883901c92505b600f831661026057610256816004610553565b9050600483901c92505b6003831661027d57610273816002610553565b9050600283901c92505b6001831661018057610290816001610553565b9392505050565b6000816102a75750610100919050565b60006fffffffffffffffffffffffffffffffff1983166102d6576102cc816080610553565b9050608083901b92505b6001600160c01b031983166102fa576102f0816040610553565b9050604083901b92505b6001600160e01b0319831661031e57610314816020610553565b9050602083901b92505b6001600160f01b0319831661034257610338816010610553565b9050601083901b92505b6001600160f81b031983166103665761035c816008610553565b9050600883901b92505b600f60fc1b83166103865761037c816004610553565b9050600483901b92505b600360fe1b83166103a65761039c816002610553565b9050600283901b92505b600160ff1b831661018057610290816001610553565b600080805b60038160ff161015610471576000604051806101a001604052806101808152602001610601610180913960ff83166103fa6001886105b3565b61040590600361056b565b61040f9190610553565b8151811061042d57634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916905061044982600861058a565b60ff16816001600160e81b031916901c83179250508080610469906105ca565b9150506103c1565b5060e81c92915050565b60008161048a57506000919050565b6104956001836105b3565b90911615919050565b60008082116104e75760405162461bcd60e51b81526020600482015260156024820152744e756d6265722063616e6e6f74206265207a65726f60581b6044820152606401610163565b600082600114156104fb5750600092915050565b608083111561051b57600192831c926105149082610553565b90506104fb565b610524836103bc565b610531620f42408361056b565b6102909190610553565b60006020828403121561054c578081fd5b5035919050565b60008219821115610566576105666105ea565b500190565b6000816000190483118215151615610585576105856105ea565b500290565b600060ff821660ff84168160ff04811182151516156105ab576105ab6105ea565b029392505050565b6000828210156105c5576105c56105ea565b500390565b600060ff821660ff8114156105e1576105e16105ea565b60010192915050565b634e487b7160e01b600052601160045260246000fdfe0000000f4240182f421e8480236e082771822ad63a2dc6c0305e8532b04834c96736b3c23876d73a187a3b9d4a3d09003e5ea63fa0c540d17741f28843057d440ba745062945f60246dc1047b917488dc7495aba4a207c4adf8a4b98544c4b404cf8aa4da0e64e44434ee3054f7d6d5013b750a61a5134c851bff05247bd52cc58534de753cc8d54486954c19c55384255ac75561e50568de956fb575766b057d00758376f589cfa5900ba5962bc59c3135a21ca5a7ef15ada945b34bf5b8d805be4df5c3aea5c8fa95ce3265d356c5d86835dd6735e25455e73005ebfad5f0b525f55f75f9fa25fe85a60302460770860bd0a61023061467f6189fd61ccae620e98624fbf62902762cfd5630ecd634d12638aa963c7966403dc643f7f647a8264b4e864eeb56527ec6560906598a365d029660724663d9766738566a8f066ddda6712476746386779af67acaf67df3a6811526842fa68743268a4fc68d55c6905536934e169640a6992cf69c13169ef326a1cd46a4a186a76ff6aa38c6acfc0a26469706673582212209ec06539722b047c33e8d359cfc9b7cd43d1170f471e94162e8503d48b06b59e64736f6c63430008040033", + "deployedBytecode": "0x730000000000000000000000000000000000000000301460806040526004361061006c5760003560e01c806306c8e54b14610071578063296e7af81461009b57806330244f7a146100bc57806332ef283b146100cf578063d82ae4b1146100e2578063e3581b6814610105575b600080fd5b61008461007f36600461053b565b610118565b60405160ff90911681526020015b60405180910390f35b6100ae6100a936600461053b565b610186565b604051908152602001610092565b6100ae6100ca36600461053b565b610297565b6100ae6100dd36600461053b565b6103bc565b6100f56100f036600461053b565b61047b565b6040519015158152602001610092565b6100ae61011336600461053b565b61049e565b60008161016c5760405162461bcd60e51b815260206004820152601860248201527f6c6f67206f66207a65726f20697320756e646566696e6564000000000000000060448201526064015b60405180910390fd5b61017582610297565b6101809060ff6105b3565b92915050565b6000816101965750610100919050565b60006fffffffffffffffffffffffffffffffff83166101c4576101ba816080610553565b9050608083901c92505b67ffffffffffffffff83166101e8576101de816040610553565b9050604083901c92505b63ffffffff8316610208576101fe816020610553565b9050602083901c92505b61ffff83166102265761021c816010610553565b9050601083901c92505b60ff831661024357610239816008610553565b9050600883901c92505b600f831661026057610256816004610553565b9050600483901c92505b6003831661027d57610273816002610553565b9050600283901c92505b6001831661018057610290816001610553565b9392505050565b6000816102a75750610100919050565b60006fffffffffffffffffffffffffffffffff1983166102d6576102cc816080610553565b9050608083901b92505b6001600160c01b031983166102fa576102f0816040610553565b9050604083901b92505b6001600160e01b0319831661031e57610314816020610553565b9050602083901b92505b6001600160f01b0319831661034257610338816010610553565b9050601083901b92505b6001600160f81b031983166103665761035c816008610553565b9050600883901b92505b600f60fc1b83166103865761037c816004610553565b9050600483901b92505b600360fe1b83166103a65761039c816002610553565b9050600283901b92505b600160ff1b831661018057610290816001610553565b600080805b60038160ff161015610471576000604051806101a001604052806101808152602001610601610180913960ff83166103fa6001886105b3565b61040590600361056b565b61040f9190610553565b8151811061042d57634e487b7160e01b600052603260045260246000fd5b01602001516001600160f81b031916905061044982600861058a565b60ff16816001600160e81b031916901c83179250508080610469906105ca565b9150506103c1565b5060e81c92915050565b60008161048a57506000919050565b6104956001836105b3565b90911615919050565b60008082116104e75760405162461bcd60e51b81526020600482015260156024820152744e756d6265722063616e6e6f74206265207a65726f60581b6044820152606401610163565b600082600114156104fb5750600092915050565b608083111561051b57600192831c926105149082610553565b90506104fb565b610524836103bc565b610531620f42408361056b565b6102909190610553565b60006020828403121561054c578081fd5b5035919050565b60008219821115610566576105666105ea565b500190565b6000816000190483118215151615610585576105856105ea565b500290565b600060ff821660ff84168160ff04811182151516156105ab576105ab6105ea565b029392505050565b6000828210156105c5576105c56105ea565b500390565b600060ff821660ff8114156105e1576105e16105ea565b60010192915050565b634e487b7160e01b600052601160045260246000fdfe0000000f4240182f421e8480236e082771822ad63a2dc6c0305e8532b04834c96736b3c23876d73a187a3b9d4a3d09003e5ea63fa0c540d17741f28843057d440ba745062945f60246dc1047b917488dc7495aba4a207c4adf8a4b98544c4b404cf8aa4da0e64e44434ee3054f7d6d5013b750a61a5134c851bff05247bd52cc58534de753cc8d54486954c19c55384255ac75561e50568de956fb575766b057d00758376f589cfa5900ba5962bc59c3135a21ca5a7ef15ada945b34bf5b8d805be4df5c3aea5c8fa95ce3265d356c5d86835dd6735e25455e73005ebfad5f0b525f55f75f9fa25fe85a60302460770860bd0a61023061467f6189fd61ccae620e98624fbf62902762cfd5630ecd634d12638aa963c7966403dc643f7f647a8264b4e864eeb56527ec6560906598a365d029660724663d9766738566a8f066ddda6712476746386779af67acaf67df3a6811526842fa68743268a4fc68d55c6905536934e169640a6992cf69c13169ef326a1cd46a4a186a76ff6aa38c6acfc0a26469706673582212209ec06539722b047c33e8d359cfc9b7cd43d1170f471e94162e8503d48b06b59e64736f6c63430008040033", + "devdoc": { + "kind": "dev", + "methods": { + "clz(uint256)": { + "details": "this a binary search implementation", + "params": { + "_num": "number you want the clz of" + } + }, + "ctz(uint256)": { + "details": "this a binary search implementation", + "params": { + "_num": "number you want the ctz of" + } + }, + "getLog2Floor(uint256)": { + "params": { + "_num": "number to take floor(log2) of" + }, + "returns": { + "_0": "floor(log2) of _num" + } + }, + "getLog2TableTimes1M(uint256)": { + "params": { + "_num": "number to take log2 of" + }, + "returns": { + "_0": "result after table look-up" + } + }, + "isPowerOf2(uint256)": { + "params": { + "_num": "number to check" + }, + "returns": { + "_0": "true if number is power of 2, false if not" + } + }, + "log2ApproxTimes1M(uint256)": { + "params": { + "_num": "number to take log2 * 1M of" + }, + "returns": { + "_0": "approximate log2 times 1M" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "clz(uint256)": { + "notice": "count leading zeros" + }, + "ctz(uint256)": { + "notice": "count trailing zeros" + }, + "getLog2Floor(uint256)": { + "notice": "get floor of log2 of number" + }, + "getLog2TableTimes1M(uint256)": { + "notice": "navigates log2tableTimes1M" + }, + "isPowerOf2(uint256)": { + "notice": "checks if a number is Power of 2" + }, + "log2ApproxTimes1M(uint256)": { + "notice": "Approximates log2 * 1M" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/CartesiToken.json b/echo-js/deployments/localhost/CartesiToken.json new file mode 100644 index 00000000..02fb264c --- /dev/null +++ b/echo-js/deployments/localhost/CartesiToken.json @@ -0,0 +1,536 @@ +{ + "address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "sender", + "type": "address" + }, + { + "name": "recipient", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "DECIMALS", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "INITIAL_SUPPLY", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_extraLockTime", + "type": "uint256" + } + ], + "name": "extendMintLockTime", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "addMinter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceMinter", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "NAME", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "recipient", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "account", + "type": "address" + } + ], + "name": "isMinter", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "SYMBOL", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "extendedBy", + "type": "uint256" + }, + { + "indexed": false, + "name": "deadline", + "type": "uint256" + } + ], + "name": "LocktimeExteded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "account", + "type": "address" + } + ], + "name": "MinterAdded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "account", + "type": "address" + } + ], + "name": "MinterRemoved", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + } + ], + "transactionHash": "0x9e6456832276fd0e80320a2f6f772142620914632ca43399920bfb8fcf4b5643", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "transactionIndex": 0, + "gasUsed": "1770294", + "logsBloom": "0x00800000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000010040000010000000000000000000000020000000000000100000800000000008000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000200000000000000000000000002000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x16d422a59cdd3487a977f9bde8985c98045f873d2595dde9c5263a5f4d3575e2", + "transactionHash": "0x9e6456832276fd0e80320a2f6f772142620914632ca43399920bfb8fcf4b5643", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 8, + "transactionHash": "0x9e6456832276fd0e80320a2f6f772142620914632ca43399920bfb8fcf4b5643", + "address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "topics": [ + "0x6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f6", + "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x16d422a59cdd3487a977f9bde8985c98045f873d2595dde9c5263a5f4d3575e2" + }, + { + "transactionIndex": 0, + "blockNumber": 8, + "transactionHash": "0x9e6456832276fd0e80320a2f6f772142620914632ca43399920bfb8fcf4b5643", + "address": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "topics": [ + "0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" + ], + "data": "0x0000000000000000000000000000000000000000033b2e3c9fd0803ce8000000", + "logIndex": 1, + "blockHash": "0x16d422a59cdd3487a977f9bde8985c98045f873d2595dde9c5263a5f4d3575e2" + } + ], + "blockNumber": 8, + "cumulativeGasUsed": "1770294", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "bytecode": "0x60806040523480156200001157600080fd5b506040518060400160405280600d81526020017f4361727465736920546f6b656e000000000000000000000000000000000000008152506040518060400160405280600481526020017f43545349000000000000000000000000000000000000000000000000000000008152506012620000a0620000946200011c60201b60201c565b6200012460201b60201c565b8260049080519060200190620000b8929190620005a4565b508160059080519060200190620000d1929190620005a4565b5080600660006101000a81548160ff021916908360ff160217905550505050426008819055506200011633601260ff16600a0a633b9aca00026200018560201b60201c565b62000653565b600033905090565b6200013f8160036200035160201b620018971790919060201c565b8073ffffffffffffffffffffffffffffffffffffffff167f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f660405160405180910390a250565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156200022b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b62000247816002546200043760201b620014bc1790919060201c565b600281905550620002a5816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546200043760201b620014bc1790919060201c565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b620003638282620004c260201b60201c565b151515620003d9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f526f6c65733a206163636f756e7420616c72656164792068617320726f6c650081525060200191505060405180910390fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b6000808284019050838110151515620004b8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156200054d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180620022366022913960400191505060405180910390fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620005e757805160ff191683800117855562000618565b8280016001018555821562000618579182015b8281111562000617578251825591602001919060010190620005fa565b5b5090506200062791906200062b565b5090565b6200065091905b808211156200064c57600081600090555060010162000632565b5090565b90565b611bd380620006636000396000f3fe608060405234801561001057600080fd5b506004361061012c5760003560e01c806370a08231116100ad578063a457c2d711610071578063a457c2d7146105ca578063a9059cbb14610630578063aa271e1a14610696578063dd62ed3e146106f2578063f76f8d781461076a5761012c565b806370a082311461041e57806395d89b4114610476578063983b2d56146104f9578063986502751461053d578063a3f4df7e146105475761012c565b80632ff2e9dc116100f45780632ff2e9dc146102e2578063313ce56714610300578063395093511461032457806340c10f191461038a578063681db92e146103f05761012c565b806306fdde0314610131578063095ea7b3146101b457806318160ddd1461021a57806323b872dd146102385780632e0f2625146102be575b600080fd5b6101396107ed565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017957808201518184015260208101905061015e565b50505050905090810190601f1680156101a65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610200600480360360408110156101ca57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061088f565b604051808215151515815260200191505060405180910390f35b6102226108ad565b6040518082815260200191505060405180910390f35b6102a46004803603606081101561024e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506108b7565b604051808215151515815260200191505060405180910390f35b6102c6610990565b604051808260ff1660ff16815260200191505060405180910390f35b6102ea610995565b6040518082815260200191505060405180910390f35b6103086109a6565b604051808260ff1660ff16815260200191505060405180910390f35b6103706004803603604081101561033a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109bd565b604051808215151515815260200191505060405180910390f35b6103d6600480360360408110156103a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610a70565b604051808215151515815260200191505060405180910390f35b61041c6004803603602081101561040657600080fd5b8101908080359060200190929190505050610b0c565b005b6104606004803603602081101561043457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bcd565b6040518082815260200191505060405180910390f35b61047e610c15565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104be5780820151818401526020810190506104a3565b50505050905090810190601f1680156104eb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61053b6004803603602081101561050f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb7565b005b610545610d2a565b005b61054f610d3c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561058f578082015181840152602081019050610574565b50505050905090810190601f1680156105bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610616600480360360408110156105e057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610d75565b604051808215151515815260200191505060405180910390f35b61067c6004803603604081101561064657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e42565b604051808215151515815260200191505060405180910390f35b6106d8600480360360208110156106ac57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e60565b604051808215151515815260200191505060405180910390f35b6107546004803603604081101561070857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e7d565b6040518082815260200191505060405180910390f35b610772610f04565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107b2578082015181840152602081019050610797565b50505050905090810190601f1680156107df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108855780601f1061085a57610100808354040283529160200191610885565b820191906000526020600020905b81548152906001019060200180831161086857829003601f168201915b5050505050905090565b60006108a361089c610f3d565b8484610f45565b6001905092915050565b6000600254905090565b60006108c4848484611140565b610985846108d0610f3d565b61098085604051806060016040528060288152602001611af060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610936610f3d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113fa9092919063ffffffff16565b610f45565b600190509392505050565b601281565b601260ff16600a0a633b9aca000281565b6000600660009054906101000a900460ff16905090565b6000610a666109ca610f3d565b84610a6185600160006109db610f3d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546114bc90919063ffffffff16565b610f45565b6001905092915050565b6000610a82610a7d610f3d565b610e60565b1515610ad9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611a9f6030913960400191505060405180910390fd5b610ae76008546007546114bc565b421015610af75760009050610b06565b610b018383611546565b600190505b92915050565b610b1c610b17610f3d565b610e60565b1515610b73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611a9f6030913960400191505060405180910390fd5b610b7f600754826114bc565b6007819055507fd04bb4a40cc3220e8987e72af12aa925741bb256bc68dd2d13dc6c524f8873838160075460085401604051808381526020018281526020019250505060405180910390a150565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610cad5780601f10610c8257610100808354040283529160200191610cad565b820191906000526020600020905b815481529060010190602001808311610c9057829003601f168201915b5050505050905090565b610cc7610cc2610f3d565b610e60565b1515610d1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611a9f6030913960400191505060405180910390fd5b610d2781611703565b50565b610d3a610d35610f3d565b61175d565b565b6040518060400160405280600d81526020017f4361727465736920546f6b656e0000000000000000000000000000000000000081525081565b6000610e38610d82610f3d565b84610e3385604051806060016040528060258152602001611b836025913960016000610dac610f3d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113fa9092919063ffffffff16565b610f45565b6001905092915050565b6000610e56610e4f610f3d565b8484611140565b6001905092915050565b6000610e768260036117b790919063ffffffff16565b9050919050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6040518060400160405280600481526020017f435453490000000000000000000000000000000000000000000000000000000081525081565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610fcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611b5f6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611055576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611a576022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156111c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180611b3a6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611250576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611a346023913960400191505060405180910390fd5b6112bb81604051806060016040528060268152602001611a79602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113fa9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061134e816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546114bc90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600083831115829015156114a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561146e578082015181840152602081019050611453565b50505050905090810190601f16801561149b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015151561153c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156115eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b611600816002546114bc90919063ffffffff16565b600281905550611657816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546114bc90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b61171781600361189790919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f660405160405180910390a250565b61177181600361197490919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669260405160405180910390a250565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611840576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611b186022913960400191505060405180910390fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6118a182826117b7565b151515611916576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f526f6c65733a206163636f756e7420616c72656164792068617320726f6c650081525060200191505060405180910390fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b61197e82826117b7565b15156119d5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611acf6021913960400191505060405180910390fd5b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c6545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa165627a7a7230582039dfb521b3deb59a807433e03ea4df6a14208a5489093b57b445fb0fd7c6935e0029526f6c65733a206163636f756e7420697320746865207a65726f2061646472657373", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061012c5760003560e01c806370a08231116100ad578063a457c2d711610071578063a457c2d7146105ca578063a9059cbb14610630578063aa271e1a14610696578063dd62ed3e146106f2578063f76f8d781461076a5761012c565b806370a082311461041e57806395d89b4114610476578063983b2d56146104f9578063986502751461053d578063a3f4df7e146105475761012c565b80632ff2e9dc116100f45780632ff2e9dc146102e2578063313ce56714610300578063395093511461032457806340c10f191461038a578063681db92e146103f05761012c565b806306fdde0314610131578063095ea7b3146101b457806318160ddd1461021a57806323b872dd146102385780632e0f2625146102be575b600080fd5b6101396107ed565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561017957808201518184015260208101905061015e565b50505050905090810190601f1680156101a65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610200600480360360408110156101ca57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061088f565b604051808215151515815260200191505060405180910390f35b6102226108ad565b6040518082815260200191505060405180910390f35b6102a46004803603606081101561024e57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506108b7565b604051808215151515815260200191505060405180910390f35b6102c6610990565b604051808260ff1660ff16815260200191505060405180910390f35b6102ea610995565b6040518082815260200191505060405180910390f35b6103086109a6565b604051808260ff1660ff16815260200191505060405180910390f35b6103706004803603604081101561033a57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506109bd565b604051808215151515815260200191505060405180910390f35b6103d6600480360360408110156103a057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610a70565b604051808215151515815260200191505060405180910390f35b61041c6004803603602081101561040657600080fd5b8101908080359060200190929190505050610b0c565b005b6104606004803603602081101561043457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610bcd565b6040518082815260200191505060405180910390f35b61047e610c15565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156104be5780820151818401526020810190506104a3565b50505050905090810190601f1680156104eb5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b61053b6004803603602081101561050f57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610cb7565b005b610545610d2a565b005b61054f610d3c565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561058f578082015181840152602081019050610574565b50505050905090810190601f1680156105bc5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610616600480360360408110156105e057600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610d75565b604051808215151515815260200191505060405180910390f35b61067c6004803603604081101561064657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050610e42565b604051808215151515815260200191505060405180910390f35b6106d8600480360360208110156106ac57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e60565b604051808215151515815260200191505060405180910390f35b6107546004803603604081101561070857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610e7d565b6040518082815260200191505060405180910390f35b610772610f04565b6040518080602001828103825283818151815260200191508051906020019080838360005b838110156107b2578082015181840152602081019050610797565b50505050905090810190601f1680156107df5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b606060048054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156108855780601f1061085a57610100808354040283529160200191610885565b820191906000526020600020905b81548152906001019060200180831161086857829003601f168201915b5050505050905090565b60006108a361089c610f3d565b8484610f45565b6001905092915050565b6000600254905090565b60006108c4848484611140565b610985846108d0610f3d565b61098085604051806060016040528060288152602001611af060289139600160008b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000610936610f3d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113fa9092919063ffffffff16565b610f45565b600190509392505050565b601281565b601260ff16600a0a633b9aca000281565b6000600660009054906101000a900460ff16905090565b6000610a666109ca610f3d565b84610a6185600160006109db610f3d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008973ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546114bc90919063ffffffff16565b610f45565b6001905092915050565b6000610a82610a7d610f3d565b610e60565b1515610ad9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611a9f6030913960400191505060405180910390fd5b610ae76008546007546114bc565b421015610af75760009050610b06565b610b018383611546565b600190505b92915050565b610b1c610b17610f3d565b610e60565b1515610b73576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611a9f6030913960400191505060405180910390fd5b610b7f600754826114bc565b6007819055507fd04bb4a40cc3220e8987e72af12aa925741bb256bc68dd2d13dc6c524f8873838160075460085401604051808381526020018281526020019250505060405180910390a150565b60008060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050919050565b606060058054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015610cad5780601f10610c8257610100808354040283529160200191610cad565b820191906000526020600020905b815481529060010190602001808311610c9057829003601f168201915b5050505050905090565b610cc7610cc2610f3d565b610e60565b1515610d1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526030815260200180611a9f6030913960400191505060405180910390fd5b610d2781611703565b50565b610d3a610d35610f3d565b61175d565b565b6040518060400160405280600d81526020017f4361727465736920546f6b656e0000000000000000000000000000000000000081525081565b6000610e38610d82610f3d565b84610e3385604051806060016040528060258152602001611b836025913960016000610dac610f3d565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008a73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113fa9092919063ffffffff16565b610f45565b6001905092915050565b6000610e56610e4f610f3d565b8484611140565b6001905092915050565b6000610e768260036117b790919063ffffffff16565b9050919050565b6000600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054905092915050565b6040518060400160405280600481526020017f435453490000000000000000000000000000000000000000000000000000000081525081565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1614151515610fcd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180611b5f6024913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611055576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611a576022913960400191505060405180910390fd5b80600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925836040518082815260200191505060405180910390a3505050565b600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16141515156111c8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526025815260200180611b3a6025913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611250576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180611a346023913960400191505060405180910390fd5b6112bb81604051806060016040528060268152602001611a79602691396000808773ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546113fa9092919063ffffffff16565b6000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000208190555061134e816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546114bc90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a3505050565b600083831115829015156114a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561146e578082015181840152602081019050611453565b50505050905090810190601f16801561149b5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5060008385039050809150509392505050565b600080828401905083811015151561153c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16141515156115eb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45524332303a206d696e7420746f20746865207a65726f20616464726573730081525060200191505060405180910390fd5b611600816002546114bc90919063ffffffff16565b600281905550611657816000808573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020546114bc90919063ffffffff16565b6000808473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508173ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040518082815260200191505060405180910390a35050565b61171781600361189790919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167f6ae172837ea30b801fbfcdd4108aa1d5bf8ff775444fd70256b44e6bf3dfc3f660405160405180910390a250565b61177181600361197490919063ffffffff16565b8073ffffffffffffffffffffffffffffffffffffffff167fe94479a9f7e1952cc78f2d6baab678adc1b772d936c6583def489e524cb6669260405160405180910390a250565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614151515611840576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180611b186022913960400191505060405180910390fd5b8260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6118a182826117b7565b151515611916576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f526f6c65733a206163636f756e7420616c72656164792068617320726f6c650081525060200191505060405180910390fd5b60018260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b61197e82826117b7565b15156119d5576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180611acf6021913960400191505060405180910390fd5b60008260000160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff021916908315150217905550505056fe45524332303a207472616e7366657220746f20746865207a65726f206164647265737345524332303a20617070726f766520746f20746865207a65726f206164647265737345524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e63654d696e746572526f6c653a2063616c6c657220646f6573206e6f74206861766520746865204d696e74657220726f6c65526f6c65733a206163636f756e7420646f6573206e6f74206861766520726f6c6545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e6365526f6c65733a206163636f756e7420697320746865207a65726f206164647265737345524332303a207472616e736665722066726f6d20746865207a65726f206164647265737345524332303a20617070726f76652066726f6d20746865207a65726f206164647265737345524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa165627a7a7230582039dfb521b3deb59a807433e03ea4df6a14208a5489093b57b445fb0fd7c6935e0029", + "devdoc": { + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. * Requirements: * - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5,05` (`505 / 10 ** 2`). * Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. * NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. * This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. * Emits an {Approval} event indicating the updated allowance. * Requirements: * - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. * This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. * Emits an {Approval} event indicating the updated allowance. * Requirements: * - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. * Requirements: * - `recipient` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. * Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}; * Requirements: - `sender` and `recipient` cannot be the zero address. - `sender` must have a balance of at least `amount`. - the caller must have allowance for `sender`'s tokens of at least `amount`." + } + } + }, + "userdoc": { + "methods": {} + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/DiamondCutFacet.json b/echo-js/deployments/localhost/DiamondCutFacet.json new file mode 100644 index 00000000..9aed6615 --- /dev/null +++ b/echo-js/deployments/localhost/DiamondCutFacet.json @@ -0,0 +1,135 @@ +{ + "address": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "init", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "name": "DiamondCut", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "_diamondCut", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "_init", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_calldata", + "type": "bytes" + } + ], + "name": "diamondCut", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xf1db64dae4b3bed35faa7eeb7a4a29da3f2fb1e7c18323ce214062c1e38dbe27", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e", + "transactionIndex": 0, + "gasUsed": "1068415", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8dab3765f00ac1fef5910658c774e1152421154187b3688ba3ab967f44c027be", + "transactionHash": "0xf1db64dae4b3bed35faa7eeb7a4a29da3f2fb1e7c18323ce214062c1e38dbe27", + "logs": [], + "blockNumber": 12, + "cumulativeGasUsed": "1068415", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut\",\"type\":\"tuple[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"init\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"name\":\"DiamondCut\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"_diamondCut\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"_init\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_calldata\",\"type\":\"bytes\"}],\"name\":\"diamondCut\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"diamondCut((address,uint8,bytes4[])[],address,bytes)\":{\"params\":{\"_calldata\":\"A function call, including function selector and arguments _calldata is executed with delegatecall on _init\",\"_diamondCut\":\"Contains the facet addresses and function selectors\",\"_init\":\"The address of the contract or facet to execute _calldata\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"diamondCut((address,uint8,bytes4[])[],address,bytes)\":{\"notice\":\"Add/replace/remove any number of functions and optionally execute a function with delegatecall\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/DiamondCutFacet.sol\":\"DiamondCutFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/facets/DiamondCutFacet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\nimport {LibDiamond} from \\\"../libraries/LibDiamond.sol\\\";\\n\\ncontract DiamondCutFacet is IDiamondCut {\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external override {\\n LibDiamond.enforceIsContractOwner();\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorCount >> 3\\\" is a gas efficient division by 8 \\\"selectorCount / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = LibDiamond\\n .addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorCount >> 3\\\" is a gas efficient division by 8 \\\"selectorCount / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n LibDiamond.initializeDiamondCut(_init, _calldata);\\n }\\n}\\n\",\"keccak256\":\"0x8cfd33aae7e3c4209777364ce776d944511d6110223c3f03f2e7a6ed4646d8cc\",\"license\":\"MIT\"},\"contracts/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\\n}\\n\",\"keccak256\":\"0x6a3129be1f39b6fec871f2c94bf7debf2d6a4e665547a4d83e7f2def38359e44\",\"license\":\"MIT\"},\"contracts/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // maps function selectors to the facets that execute the functions.\\n // and maps the selectors to their position in the selectorSlots array.\\n // func selector => address facet, selector position\\n mapping(bytes4 => bytes32) facets;\\n // array of slots of function selectors.\\n // each slot holds 8 function selectors.\\n mapping(uint256 => bytes32) selectorSlots;\\n // The number of function selectors in selectorSlots\\n uint16 selectorCount;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(\\n msg.sender == diamondStorage().contractOwner,\\n \\\"LibDiamond: Must be contract owner\\\"\\n );\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] diamondCut,\\n address init,\\n bytes callData\\n );\\n\\n bytes32 constant CLEAR_ADDRESS_MASK =\\n bytes32(uint256(0xffffffffffffffffffffffff));\\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\\n\\n // Internal function version of diamondCut\\n // This code is almost the same as the external diamondCut,\\n // except it is using 'Facet[] memory _diamondCut' instead of\\n // 'Facet[] calldata _diamondCut'.\\n // The code is duplicated to prevent copying calldata to memory which\\n // causes an error for a two dimensional array.\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n DiamondStorage storage ds = diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addReplaceRemoveFacetSelectors(\\n uint256 _selectorCount,\\n bytes32 _selectorSlot,\\n address _newFacetAddress,\\n IDiamondCut.FacetCutAction _action,\\n bytes4[] memory _selectors\\n ) internal returns (uint256, bytes32) {\\n DiamondStorage storage ds = diamondStorage();\\n require(\\n _selectors.length > 0,\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\n );\\n if (_action == IDiamondCut.FacetCutAction.Add) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Add facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) == address(0),\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\n );\\n // add facet for selector\\n ds.facets[selector] =\\n bytes20(_newFacetAddress) |\\n bytes32(_selectorCount);\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\\n // clear selector position in slot and add selector\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\\n (bytes32(selector) >> selectorInSlotPosition);\\n // if slot is full then write it to storage\\n if (selectorInSlotPosition == 224) {\\n // \\\"_selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"_selectorSlot / 8\\\"\\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\\n _selectorSlot = 0;\\n }\\n _selectorCount++;\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Replace facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n address oldFacetAddress = address(bytes20(oldFacet));\\n // only useful if immutable functions exist\\n require(\\n oldFacetAddress != address(this),\\n \\\"LibDiamondCut: Can't replace immutable function\\\"\\n );\\n require(\\n oldFacetAddress != _newFacetAddress,\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\n );\\n require(\\n oldFacetAddress != address(0),\\n \\\"LibDiamondCut: Can't replace function that doesn't exist\\\"\\n );\\n // replace old facet address\\n ds.facets[selector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(_newFacetAddress);\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\\n require(\\n _newFacetAddress == address(0),\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\n );\\n // \\\"_selectorCount >> 3\\\" is a gas efficient division by 8 \\\"_selectorCount / 8\\\"\\n uint256 selectorSlotCount = _selectorCount >> 3;\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotIndex = _selectorCount & 7;\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n if (_selectorSlot == 0) {\\n // get last selectorSlot\\n selectorSlotCount--;\\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\\n selectorInSlotIndex = 7;\\n } else {\\n selectorInSlotIndex--;\\n }\\n bytes4 lastSelector;\\n uint256 oldSelectorsSlotCount;\\n uint256 oldSelectorInSlotPosition;\\n // adding a block here prevents stack too deep error\\n {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) != address(0),\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\n );\\n // only useful if immutable functions exist\\n require(\\n address(bytes20(oldFacet)) != address(this),\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\n );\\n // replace selector with last selector in ds.facets\\n // gets the last selector\\n lastSelector = bytes4(\\n _selectorSlot << (selectorInSlotIndex << 5)\\n );\\n if (lastSelector != selector) {\\n // update last selector slot position info\\n ds.facets[lastSelector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(ds.facets[lastSelector]);\\n }\\n delete ds.facets[selector];\\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\\n // \\\"oldSelectorCount >> 3\\\" is a gas efficient division by 8 \\\"oldSelectorCount / 8\\\"\\n oldSelectorsSlotCount = oldSelectorCount >> 3;\\n // \\\"oldSelectorCount & 7\\\" is a gas efficient modulo by eight \\\"oldSelectorCount % 8\\\"\\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\\n }\\n if (oldSelectorsSlotCount != selectorSlotCount) {\\n bytes32 oldSelectorSlot = ds.selectorSlots[\\n oldSelectorsSlotCount\\n ];\\n // clears the selector we are deleting and puts the last selector in its place.\\n oldSelectorSlot =\\n (oldSelectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n // update storage with the modified slot\\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\\n } else {\\n // clears the selector we are deleting and puts the last selector in its place.\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n }\\n if (selectorInSlotIndex == 0) {\\n delete ds.selectorSlots[selectorSlotCount];\\n _selectorSlot = 0;\\n }\\n }\\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n return (_selectorCount, _selectorSlot);\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\n internal\\n {\\n if (_init == address(0)) {\\n require(\\n _calldata.length == 0,\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\n );\\n } else {\\n require(\\n _calldata.length > 0,\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\n );\\n if (_init != address(this)) {\\n enforceHasContractCode(\\n _init,\\n \\\"LibDiamondCut: _init address has no code\\\"\\n );\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(\\n address _contract,\\n string memory _errorMessage\\n ) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x740ea3845282f09bb822e66a189ed431ac799ab08184de7457ef53799b2e99d6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061125e806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004361003e366004610d90565b610045565b005b61004d61027b565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e547fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c9061ffff8116908190600090600716156100bc5750600381901c60009081526001840160205260409020545b60005b888110156101b35761019c83838c8c858181106100de576100de610e42565b90506020028101906100f09190610e58565b6100fe906020810190610e78565b8d8d8681811061011057610110610e42565b90506020028101906101229190610e58565b610133906040810190602001610ea9565b8e8e8781811061014557610145610e42565b90506020028101906101579190610e58565b610165906040810190610ec4565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061030992505050565b9093509150806101ab81610f24565b9150506100bf565b508282146101cf5760028401805461ffff191661ffff84161790555b60078216156101f157600382901c600090815260018501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738989898989604051610228959493929190610fcc565b60405180910390a16102708787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610af792505050565b505050505050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c600401546001600160a01b031633146103075760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b60648201526084015b60405180910390fd5b565b600080807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c905060008451116103955760405162461bcd60e51b815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201526a1858d95d081d1bc818dd5d60aa1b60648201526084016102fe565b60008560028111156103a9576103a9610f3d565b03610516576103d0866040518060600160405280602481526020016111b560249139610d0a565b60005b84518110156105105760008582815181106103f0576103f0610e42565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c156104895760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b60648201526084016102fe565b6001600160e01b031980831660008181526020879052604090206001600160601b031960608d901b168e17905560e060058e901b811692831c199c909c1690821c179a8190036104ed5760038c901c600090815260018601602052604081209b909b555b8b6104f781610f24565b9c5050505050808061050890610f24565b9150506103d3565b50610aeb565b600185600281111561052a5761052a610f3d565b03610759576105518660405180606001604052806028815260200161120160289139610d0a565b60005b845181101561051057600085828151811061057157610571610e42565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c3081036106065760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e2774207265706c61636520696d6d60448201526e3aba30b1363290333ab731ba34b7b760891b60648201526084016102fe565b896001600160a01b0316816001600160a01b03160361068d5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e000000000000000060648201526084016102fe565b6001600160a01b0381166107095760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e207468617420646f65736e2774206578697374000000000000000060648201526084016102fe565b506001600160e01b031990911660009081526020849052604090206bffffffffffffffffffffffff919091166001600160601b031960608a901b161790558061075181610f24565b915050610554565b600285600281111561076d5761076d610f3d565b03610a93576001600160a01b038616156107e85760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b60648201526084016102fe565b600388901c6007891660005b8651811015610a735760008a90036108305782610810816110f5565b60008181526001870160205260409020549b5093506007925061083e9050565b8161083a816110f5565b9250505b6000806000808a858151811061085657610856610e42565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c6108f65760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e277420657869737400000000000000000060648201526084016102fe565b30606082901c036109605760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b60648201526084016102fe565b600587901b8f901b94506001600160e01b0319808616908316146109b6576001600160e01b03198516600090815260208a90526040902080546001600160601b0319166bffffffffffffffffffffffff83161790555b6001600160e01b031991909116600090815260208990526040812055600381901c611fff16925060051b60e0169050858214610a1b576000828152600188016020526040902080546001600160e01b031980841c19909116908516831c179055610a3f565b80836001600160e01b031916901c816001600160e01b031960001b901c198e16179c505b84600003610a5d57600086815260018801602052604081208190559c505b5050508080610a6b90610f24565b9150506107f4565b5080610a8083600861110c565b610a8a919061112b565b99505050610aeb565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084016102fe565b50959694955050505050565b6001600160a01b038216610b7e57805115610b7a5760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d7074790000000060648201526084016102fe565b5050565b6000815111610bf55760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f74206164647265737328302900000060648201526084016102fe565b6001600160a01b0382163014610c2757610c27826040518060600160405280602881526020016111d960289139610d0a565b600080836001600160a01b031683604051610c42919061116f565b600060405180830381855af49150503d8060008114610c7d576040519150601f19603f3d011682016040523d82523d6000602084013e610c82565b606091505b509150915081610d0457805115610cad578060405162461bcd60e51b81526004016102fe9190611181565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b60648201526084016102fe565b50505050565b813b8181610d045760405162461bcd60e51b81526004016102fe9190611181565b80356001600160a01b0381168114610d4257600080fd5b919050565b60008083601f840112610d5957600080fd5b50813567ffffffffffffffff811115610d7157600080fd5b602083019150836020828501011115610d8957600080fd5b9250929050565b600080600080600060608688031215610da857600080fd5b853567ffffffffffffffff80821115610dc057600080fd5b818801915088601f830112610dd457600080fd5b813581811115610de357600080fd5b8960208260051b8501011115610df857600080fd5b60208301975080965050610e0e60208901610d2b565b94506040880135915080821115610e2457600080fd5b50610e3188828901610d47565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b60008235605e19833603018112610e6e57600080fd5b9190910192915050565b600060208284031215610e8a57600080fd5b610e9382610d2b565b9392505050565b803560038110610d4257600080fd5b600060208284031215610ebb57600080fd5b610e9382610e9a565b6000808335601e19843603018112610edb57600080fd5b83018035915067ffffffffffffffff821115610ef657600080fd5b6020019150600581901b3603821315610d8957600080fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610f3657610f36610f0e565b5060010190565b634e487b7160e01b600052602160045260246000fd5b818352600060208085019450826000805b86811015610f975782356001600160e01b03198116808214610f84578384fd5b8952509683019691830191600101610f64565b50959695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060808252818101869052600090600560808085019089831b8601018a855b8b8110156110c257878303607f190184528135368e9003605e1901811261101157600080fd5b8d016001600160a01b0361102482610d2b565b1684526020611034818301610e9a565b6003811061105257634e487b7160e01b600052602160045260246000fd5b8582015260408281013536849003601e1901811261106f57600080fd5b8301803567ffffffffffffffff81111561108857600080fd5b808a1b360385131561109957600080fd5b8a838901526110ad8b890182868501610f53565b98840198975050509301925050600101610feb565b50506001600160a01b038916602087015285810360408701526110e681888a610fa3565b9b9a5050505050505050505050565b60008161110457611104610f0e565b506000190190565b600081600019048311821515161561112657611126610f0e565b500290565b6000821982111561113e5761113e610f0e565b500190565b60005b8381101561115e578181015183820152602001611146565b83811115610d045750506000910152565b60008251610e6e818460208701611143565b60208152600082518060208401526111a0816040850160208701611143565b601f01601f1916919091016040019291505056fe4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a26469706673582212204b8b2c4cc9333af346d73b2e4a6dca4f76dd4c5bea51a13e8742c5f94ad18f9f64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c80631f931c1c14610030575b600080fd5b61004361003e366004610d90565b610045565b005b61004d61027b565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e547fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c9061ffff8116908190600090600716156100bc5750600381901c60009081526001840160205260409020545b60005b888110156101b35761019c83838c8c858181106100de576100de610e42565b90506020028101906100f09190610e58565b6100fe906020810190610e78565b8d8d8681811061011057610110610e42565b90506020028101906101229190610e58565b610133906040810190602001610ea9565b8e8e8781811061014557610145610e42565b90506020028101906101579190610e58565b610165906040810190610ec4565b8080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061030992505050565b9093509150806101ab81610f24565b9150506100bf565b508282146101cf5760028401805461ffff191661ffff84161790555b60078216156101f157600382901c600090815260018501602052604090208190555b7f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738989898989604051610228959493929190610fcc565b60405180910390a16102708787878080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250610af792505050565b505050505050505050565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c600401546001600160a01b031633146103075760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b60648201526084015b60405180910390fd5b565b600080807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c905060008451116103955760405162461bcd60e51b815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201526a1858d95d081d1bc818dd5d60aa1b60648201526084016102fe565b60008560028111156103a9576103a9610f3d565b03610516576103d0866040518060600160405280602481526020016111b560249139610d0a565b60005b84518110156105105760008582815181106103f0576103f0610e42565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c156104895760405162461bcd60e51b815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f6044820152746e207468617420616c72656164792065786973747360581b60648201526084016102fe565b6001600160e01b031980831660008181526020879052604090206001600160601b031960608d901b168e17905560e060058e901b811692831c199c909c1690821c179a8190036104ed5760038c901c600090815260018601602052604081209b909b555b8b6104f781610f24565b9c5050505050808061050890610f24565b9150506103d3565b50610aeb565b600185600281111561052a5761052a610f3d565b03610759576105518660405180606001604052806028815260200161120160289139610d0a565b60005b845181101561051057600085828151811061057157610571610e42565b6020908102919091018101516001600160e01b03198116600090815291859052604090912054909150606081901c3081036106065760405162461bcd60e51b815260206004820152602f60248201527f4c69624469616d6f6e644375743a2043616e2774207265706c61636520696d6d60448201526e3aba30b1363290333ab731ba34b7b760891b60648201526084016102fe565b896001600160a01b0316816001600160a01b03160361068d5760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e000000000000000060648201526084016102fe565b6001600160a01b0381166107095760405162461bcd60e51b815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e207468617420646f65736e2774206578697374000000000000000060648201526084016102fe565b506001600160e01b031990911660009081526020849052604090206bffffffffffffffffffffffff919091166001600160601b031960608a901b161790558061075181610f24565b915050610554565b600285600281111561076d5761076d610f3d565b03610a93576001600160a01b038616156107e85760405162461bcd60e51b815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f76652066616365742061646472604482015275657373206d757374206265206164647265737328302960501b60648201526084016102fe565b600388901c6007891660005b8651811015610a735760008a90036108305782610810816110f5565b60008181526001870160205260409020549b5093506007925061083e9050565b8161083a816110f5565b9250505b6000806000808a858151811061085657610856610e42565b6020908102919091018101516001600160e01b031981166000908152918a9052604090912054909150606081901c6108f65760405162461bcd60e51b815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e277420657869737400000000000000000060648201526084016102fe565b30606082901c036109605760405162461bcd60e51b815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201526d3a30b1363290333ab731ba34b7b760911b60648201526084016102fe565b600587901b8f901b94506001600160e01b0319808616908316146109b6576001600160e01b03198516600090815260208a90526040902080546001600160601b0319166bffffffffffffffffffffffff83161790555b6001600160e01b031991909116600090815260208990526040812055600381901c611fff16925060051b60e0169050858214610a1b576000828152600188016020526040902080546001600160e01b031980841c19909116908516831c179055610a3f565b80836001600160e01b031916901c816001600160e01b031960001b901c198e16179c505b84600003610a5d57600086815260018801602052604081208190559c505b5050508080610a6b90610f24565b9150506107f4565b5080610a8083600861110c565b610a8a919061112b565b99505050610aeb565b60405162461bcd60e51b815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f727265637420466163657443756044820152663a20b1ba34b7b760c91b60648201526084016102fe565b50959694955050505050565b6001600160a01b038216610b7e57805115610b7a5760405162461bcd60e51b815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d7074790000000060648201526084016102fe565b5050565b6000815111610bf55760405162461bcd60e51b815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f74206164647265737328302900000060648201526084016102fe565b6001600160a01b0382163014610c2757610c27826040518060600160405280602881526020016111d960289139610d0a565b600080836001600160a01b031683604051610c42919061116f565b600060405180830381855af49150503d8060008114610c7d576040519150601f19603f3d011682016040523d82523d6000602084013e610c82565b606091505b509150915081610d0457805115610cad578060405162461bcd60e51b81526004016102fe9190611181565b60405162461bcd60e51b815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e2072656044820152651d995c9d195960d21b60648201526084016102fe565b50505050565b813b8181610d045760405162461bcd60e51b81526004016102fe9190611181565b80356001600160a01b0381168114610d4257600080fd5b919050565b60008083601f840112610d5957600080fd5b50813567ffffffffffffffff811115610d7157600080fd5b602083019150836020828501011115610d8957600080fd5b9250929050565b600080600080600060608688031215610da857600080fd5b853567ffffffffffffffff80821115610dc057600080fd5b818801915088601f830112610dd457600080fd5b813581811115610de357600080fd5b8960208260051b8501011115610df857600080fd5b60208301975080965050610e0e60208901610d2b565b94506040880135915080821115610e2457600080fd5b50610e3188828901610d47565b969995985093965092949392505050565b634e487b7160e01b600052603260045260246000fd5b60008235605e19833603018112610e6e57600080fd5b9190910192915050565b600060208284031215610e8a57600080fd5b610e9382610d2b565b9392505050565b803560038110610d4257600080fd5b600060208284031215610ebb57600080fd5b610e9382610e9a565b6000808335601e19843603018112610edb57600080fd5b83018035915067ffffffffffffffff821115610ef657600080fd5b6020019150600581901b3603821315610d8957600080fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610f3657610f36610f0e565b5060010190565b634e487b7160e01b600052602160045260246000fd5b818352600060208085019450826000805b86811015610f975782356001600160e01b03198116808214610f84578384fd5b8952509683019691830191600101610f64565b50959695505050505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6060808252818101869052600090600560808085019089831b8601018a855b8b8110156110c257878303607f190184528135368e9003605e1901811261101157600080fd5b8d016001600160a01b0361102482610d2b565b1684526020611034818301610e9a565b6003811061105257634e487b7160e01b600052602160045260246000fd5b8582015260408281013536849003601e1901811261106f57600080fd5b8301803567ffffffffffffffff81111561108857600080fd5b808a1b360385131561109957600080fd5b8a838901526110ad8b890182868501610f53565b98840198975050509301925050600101610feb565b50506001600160a01b038916602087015285810360408701526110e681888a610fa3565b9b9a5050505050505050505050565b60008161110457611104610f0e565b506000190190565b600081600019048311821515161561112657611126610f0e565b500290565b6000821982111561113e5761113e610f0e565b500190565b60005b8381101561115e578181015183820152602001611146565b83811115610d045750506000910152565b60008251610e6e818460208701611143565b60208152600082518060208401526111a0816040850160208701611143565b601f01601f1916919091016040019291505056fe4c69624469616d6f6e644375743a2041646420666163657420686173206e6f20636f64654c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a205265706c61636520666163657420686173206e6f20636f6465a26469706673582212204b8b2c4cc9333af346d73b2e4a6dca4f76dd4c5bea51a13e8742c5f94ad18f9f64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "diamondCut((address,uint8,bytes4[])[],address,bytes)": { + "params": { + "_calldata": "A function call, including function selector and arguments _calldata is executed with delegatecall on _init", + "_diamondCut": "Contains the facet addresses and function selectors", + "_init": "The address of the contract or facet to execute _calldata" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "diamondCut((address,uint8,bytes4[])[],address,bytes)": { + "notice": "Add/replace/remove any number of functions and optionally execute a function with delegatecall" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/DiamondInit.json b/echo-js/deployments/localhost/DiamondInit.json new file mode 100644 index 00000000..06524d03 --- /dev/null +++ b/echo-js/deployments/localhost/DiamondInit.json @@ -0,0 +1,176 @@ +{ + "address": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "feePerClaim", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "feeManagerBank", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "feeManagerOwner", + "type": "address" + } + ], + "name": "FeeManagerInitialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "inputDuration", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "challengePeriod", + "type": "uint256" + } + ], + "name": "RollupsInitialized", + "type": "event" + }, + { + "inputs": [ + { + "components": [ + { + "internalType": "bytes32", + "name": "templateHash", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "inputDuration", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "challengePeriod", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inputLog2Size", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "feePerClaim", + "type": "uint256" + }, + { + "internalType": "address", + "name": "feeManagerBank", + "type": "address" + }, + { + "internalType": "address", + "name": "feeManagerOwner", + "type": "address" + }, + { + "internalType": "address payable[]", + "name": "validators", + "type": "address[]" + } + ], + "internalType": "struct DiamondConfig", + "name": "_dConfig", + "type": "tuple" + } + ], + "name": "init", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x0043e0f7ea63d055c67e444b35395305aeedcdb5eef5f28f22825ddb11581b93", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x67d269191c92Caf3cD7723F116c85e6E9bf55933", + "transactionIndex": 0, + "gasUsed": "644157", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x03b7f7b6d3ae79074203c186eedfec931fa9dd9af10c068ca1dedc090f0c752d", + "transactionHash": "0x0043e0f7ea63d055c67e444b35395305aeedcdb5eef5f28f22825ddb11581b93", + "logs": [], + "blockNumber": 30, + "cumulativeGasUsed": "644157", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"feePerClaim\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"feeManagerBank\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"feeManagerOwner\",\"type\":\"address\"}],\"name\":\"FeeManagerInitialized\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"inputDuration\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"challengePeriod\",\"type\":\"uint256\"}],\"name\":\"RollupsInitialized\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"bytes32\",\"name\":\"templateHash\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"inputDuration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"challengePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inputLog2Size\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"feePerClaim\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"feeManagerBank\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"feeManagerOwner\",\"type\":\"address\"},{\"internalType\":\"address payable[]\",\"name\":\"validators\",\"type\":\"address[]\"}],\"internalType\":\"struct DiamondConfig\",\"name\":\"_dConfig\",\"type\":\"tuple\"}],\"name\":\"init\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"events\":{\"FeeManagerInitialized(uint256,address,address)\":{\"params\":{\"feeManagerBank\":\"fee manager bank address\",\"feeManagerOwner\":\"fee manager owner address\",\"feePerClaim\":\"fee per claim to reward the validators\"}},\"RollupsInitialized(uint256,uint256)\":{\"params\":{\"challengePeriod\":\"duration of challenge period in seconds\",\"inputDuration\":\"duration of input accumulation phase in seconds\"}}},\"kind\":\"dev\",\"methods\":{\"init((bytes32,uint256,uint256,uint256,uint256,address,address,address[]))\":{\"params\":{\"_dConfig\":\"diamond configurations\"}}},\"version\":1},\"userdoc\":{\"events\":{\"FeeManagerInitialized(uint256,address,address)\":{\"notice\":\"FeeManagerImpl contract initialized\"},\"RollupsInitialized(uint256,uint256)\":{\"notice\":\"rollups contract initialized\"}},\"kind\":\"user\",\"methods\":{\"init((bytes32,uint256,uint256,uint256,uint256,address,address,address[]))\":{\"notice\":\"initialize the diamond\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/upgrade_initializers/DiamondInit.sol\":\"DiamondInit\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\\n}\\n\",\"keccak256\":\"0x6a3129be1f39b6fec871f2c94bf7debf2d6a4e665547a4d83e7f2def38359e44\",\"license\":\"MIT\"},\"contracts/interfaces/IDiamondLoupe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\n// A loupe is a small magnifying glass used to look at diamonds.\\n// These functions look at diamonds\\ninterface IDiamondLoupe {\\n /// These functions are expected to be called frequently\\n /// by tools.\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Gets all facet addresses and their four byte function selectors.\\n /// @return facets_ Facet\\n function facets() external view returns (Facet[] memory facets_);\\n\\n /// @notice Gets all the function selectors supported by a specific facet.\\n /// @param _facet The facet address.\\n /// @return facetFunctionSelectors_\\n function facetFunctionSelectors(address _facet)\\n external\\n view\\n returns (bytes4[] memory facetFunctionSelectors_);\\n\\n /// @notice Get all the facet addresses used by a diamond.\\n /// @return facetAddresses_\\n function facetAddresses()\\n external\\n view\\n returns (address[] memory facetAddresses_);\\n\\n /// @notice Gets the facet that supports the given selector.\\n /// @dev If facet is not found return address(0).\\n /// @param _functionSelector The function selector.\\n /// @return facetAddress_ The facet address.\\n function facetAddress(bytes4 _functionSelector)\\n external\\n view\\n returns (address facetAddress_);\\n}\\n\",\"keccak256\":\"0xd6c3796a7c45baea6e47fdd5f2cec95d7796991bc9a949604f99875590962a67\",\"license\":\"MIT\"},\"contracts/interfaces/IERC173.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\",\"keccak256\":\"0xc47289cda9c9cdb749612eb82ccb9abf9ab08dca74bdca22292ae7f765a15a5f\",\"license\":\"MIT\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // maps function selectors to the facets that execute the functions.\\n // and maps the selectors to their position in the selectorSlots array.\\n // func selector => address facet, selector position\\n mapping(bytes4 => bytes32) facets;\\n // array of slots of function selectors.\\n // each slot holds 8 function selectors.\\n mapping(uint256 => bytes32) selectorSlots;\\n // The number of function selectors in selectorSlots\\n uint16 selectorCount;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(\\n msg.sender == diamondStorage().contractOwner,\\n \\\"LibDiamond: Must be contract owner\\\"\\n );\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] diamondCut,\\n address init,\\n bytes callData\\n );\\n\\n bytes32 constant CLEAR_ADDRESS_MASK =\\n bytes32(uint256(0xffffffffffffffffffffffff));\\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\\n\\n // Internal function version of diamondCut\\n // This code is almost the same as the external diamondCut,\\n // except it is using 'Facet[] memory _diamondCut' instead of\\n // 'Facet[] calldata _diamondCut'.\\n // The code is duplicated to prevent copying calldata to memory which\\n // causes an error for a two dimensional array.\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n DiamondStorage storage ds = diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addReplaceRemoveFacetSelectors(\\n uint256 _selectorCount,\\n bytes32 _selectorSlot,\\n address _newFacetAddress,\\n IDiamondCut.FacetCutAction _action,\\n bytes4[] memory _selectors\\n ) internal returns (uint256, bytes32) {\\n DiamondStorage storage ds = diamondStorage();\\n require(\\n _selectors.length > 0,\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\n );\\n if (_action == IDiamondCut.FacetCutAction.Add) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Add facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) == address(0),\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\n );\\n // add facet for selector\\n ds.facets[selector] =\\n bytes20(_newFacetAddress) |\\n bytes32(_selectorCount);\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\\n // clear selector position in slot and add selector\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\\n (bytes32(selector) >> selectorInSlotPosition);\\n // if slot is full then write it to storage\\n if (selectorInSlotPosition == 224) {\\n // \\\"_selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"_selectorSlot / 8\\\"\\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\\n _selectorSlot = 0;\\n }\\n _selectorCount++;\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Replace facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n address oldFacetAddress = address(bytes20(oldFacet));\\n // only useful if immutable functions exist\\n require(\\n oldFacetAddress != address(this),\\n \\\"LibDiamondCut: Can't replace immutable function\\\"\\n );\\n require(\\n oldFacetAddress != _newFacetAddress,\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\n );\\n require(\\n oldFacetAddress != address(0),\\n \\\"LibDiamondCut: Can't replace function that doesn't exist\\\"\\n );\\n // replace old facet address\\n ds.facets[selector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(_newFacetAddress);\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\\n require(\\n _newFacetAddress == address(0),\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\n );\\n // \\\"_selectorCount >> 3\\\" is a gas efficient division by 8 \\\"_selectorCount / 8\\\"\\n uint256 selectorSlotCount = _selectorCount >> 3;\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotIndex = _selectorCount & 7;\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n if (_selectorSlot == 0) {\\n // get last selectorSlot\\n selectorSlotCount--;\\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\\n selectorInSlotIndex = 7;\\n } else {\\n selectorInSlotIndex--;\\n }\\n bytes4 lastSelector;\\n uint256 oldSelectorsSlotCount;\\n uint256 oldSelectorInSlotPosition;\\n // adding a block here prevents stack too deep error\\n {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) != address(0),\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\n );\\n // only useful if immutable functions exist\\n require(\\n address(bytes20(oldFacet)) != address(this),\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\n );\\n // replace selector with last selector in ds.facets\\n // gets the last selector\\n lastSelector = bytes4(\\n _selectorSlot << (selectorInSlotIndex << 5)\\n );\\n if (lastSelector != selector) {\\n // update last selector slot position info\\n ds.facets[lastSelector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(ds.facets[lastSelector]);\\n }\\n delete ds.facets[selector];\\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\\n // \\\"oldSelectorCount >> 3\\\" is a gas efficient division by 8 \\\"oldSelectorCount / 8\\\"\\n oldSelectorsSlotCount = oldSelectorCount >> 3;\\n // \\\"oldSelectorCount & 7\\\" is a gas efficient modulo by eight \\\"oldSelectorCount % 8\\\"\\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\\n }\\n if (oldSelectorsSlotCount != selectorSlotCount) {\\n bytes32 oldSelectorSlot = ds.selectorSlots[\\n oldSelectorsSlotCount\\n ];\\n // clears the selector we are deleting and puts the last selector in its place.\\n oldSelectorSlot =\\n (oldSelectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n // update storage with the modified slot\\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\\n } else {\\n // clears the selector we are deleting and puts the last selector in its place.\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n }\\n if (selectorInSlotIndex == 0) {\\n delete ds.selectorSlots[selectorSlotCount];\\n _selectorSlot = 0;\\n }\\n }\\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n return (_selectorCount, _selectorSlot);\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\n internal\\n {\\n if (_init == address(0)) {\\n require(\\n _calldata.length == 0,\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\n );\\n } else {\\n require(\\n _calldata.length > 0,\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\n );\\n if (_init != address(this)) {\\n enforceHasContractCode(\\n _init,\\n \\\"LibDiamondCut: _init address has no code\\\"\\n );\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(\\n address _contract,\\n string memory _errorMessage\\n ) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x740ea3845282f09bb822e66a189ed431ac799ab08184de7457ef53799b2e99d6\",\"license\":\"MIT\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"},\"contracts/upgrade_initializers/DiamondInit.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Diamond Initialization Contract\\npragma solidity ^0.8.0;\\n\\n// Rollups-related dependencies\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\n// Diamond-related dependencies\\nimport {LibDiamond} from \\\"../libraries/LibDiamond.sol\\\";\\nimport {IDiamondLoupe} from \\\"../interfaces/IDiamondLoupe.sol\\\";\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\nimport {IERC173} from \\\"../interfaces/IERC173.sol\\\"; // not in openzeppelin-contracts yet\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\n/// @notice diamond configurations\\n/// @param templateHash state hash of the cartesi machine at t0\\n/// @param inputDuration duration of input accumulation phase in seconds\\n/// @param challengePeriod duration of challenge period in seconds\\n/// @param inputLog2Size size of the input memory range in this machine\\n/// @param feePerClaim fee per claim to reward the validators\\n/// @param feeManagerBank fee manager bank address\\n/// @param feeManagerOwner fee manager owner address\\n/// @param validators initial validator set\\n/// @dev validators have to be unique, if the same validator is added twice\\n/// consensus will never be reached\\nstruct DiamondConfig {\\n // RollupsFacet\\n bytes32 templateHash;\\n uint256 inputDuration;\\n uint256 challengePeriod;\\n // InputFacet\\n uint256 inputLog2Size;\\n // FeeManagerFacet\\n uint256 feePerClaim;\\n address feeManagerBank;\\n address feeManagerOwner;\\n // ValidatorManagerFacet\\n address payable[] validators;\\n}\\n\\ncontract DiamondInit {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibInput for LibInput.DiamondStorage;\\n\\n /// @notice initialize the diamond\\n /// @param _dConfig diamond configurations\\n function init(DiamondConfig calldata _dConfig) external {\\n initERC165();\\n initValidatorManager(_dConfig.validators);\\n initRollups(\\n _dConfig.templateHash,\\n _dConfig.inputDuration,\\n _dConfig.challengePeriod\\n );\\n initFeeManager(\\n _dConfig.feePerClaim,\\n _dConfig.feeManagerBank,\\n _dConfig.feeManagerOwner\\n );\\n initInput(_dConfig.inputLog2Size);\\n }\\n\\n /// @notice initialize ERC165 data\\n function initERC165() private {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n ds.supportedInterfaces[type(IERC165).interfaceId] = true;\\n ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;\\n ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;\\n ds.supportedInterfaces[type(IERC173).interfaceId] = true;\\n }\\n\\n /// @notice initalize the Input facet\\n /// @param _inputLog2Size size of the input memory range in this machine\\n function initInput(uint256 _inputLog2Size) private {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n\\n require(\\n _inputLog2Size >= 3 && _inputLog2Size <= 64,\\n \\\"Log of input size: [3,64]\\\"\\n );\\n\\n inputDS.inputDriveSize = (1 << _inputLog2Size);\\n\\n // input box gets initialized with one empty input\\n // so that the L2 DApp knows it's own address\\n inputDS.addInternalInput(\\\"\\\");\\n }\\n\\n /// @notice initialize the Validator Manager facet\\n /// @param _validators initial validator set\\n function initValidatorManager(address payable[] memory _validators)\\n private\\n {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n uint256 maxNumValidators = _validators.length;\\n\\n require(maxNumValidators <= 8, \\\"up to 8 validators\\\");\\n\\n validatorManagerDS.validators = _validators;\\n validatorManagerDS.maxNumValidators = maxNumValidators;\\n\\n // create a new ClaimsMask, with only the consensus goal set,\\n // according to the number of validators\\n validatorManagerDS.claimsMask = LibClaimsMask\\n .newClaimsMaskWithConsensusGoalSet(maxNumValidators);\\n }\\n\\n /// @notice rollups contract initialized\\n /// @param inputDuration duration of input accumulation phase in seconds\\n /// @param challengePeriod duration of challenge period in seconds\\n event RollupsInitialized(uint256 inputDuration, uint256 challengePeriod);\\n\\n /// @notice initialize the Rollups facet\\n /// @param _templateHash state hash of the cartesi machine at t0\\n /// @param _inputDuration duration of input accumulation phase in seconds\\n /// @param _challengePeriod duration of challenge period in seconds\\n function initRollups(\\n bytes32 _templateHash,\\n uint256 _inputDuration,\\n uint256 _challengePeriod\\n ) private {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n rollupsDS.templateHash = _templateHash;\\n rollupsDS.inputDuration = uint32(_inputDuration);\\n rollupsDS.challengePeriod = uint32(_challengePeriod);\\n rollupsDS.inputAccumulationStart = uint32(block.timestamp);\\n rollupsDS.currentPhase_int = uint32(Phase.InputAccumulation);\\n\\n emit RollupsInitialized(_inputDuration, _challengePeriod);\\n }\\n\\n /// @notice FeeManagerImpl contract initialized\\n /// @param feePerClaim fee per claim to reward the validators\\n /// @param feeManagerBank fee manager bank address\\n /// @param feeManagerOwner fee manager owner address\\n event FeeManagerInitialized(\\n uint256 feePerClaim,\\n address feeManagerBank,\\n address feeManagerOwner\\n );\\n\\n /// @notice initalize the Fee Manager facet\\n /// @param _feePerClaim fee per claim to reward the validators\\n /// @param _feeManagerBank fee manager bank address\\n /// @param _feeManagerOwner fee manager owner address\\n function initFeeManager(\\n uint256 _feePerClaim,\\n address _feeManagerBank,\\n address _feeManagerOwner\\n ) private {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n\\n feeManagerDS.feePerClaim = _feePerClaim;\\n feeManagerDS.bank = IBank(_feeManagerBank);\\n feeManagerDS.owner = _feeManagerOwner;\\n\\n emit FeeManagerInitialized(\\n _feePerClaim,\\n _feeManagerBank,\\n _feeManagerOwner\\n );\\n }\\n}\\n\",\"keccak256\":\"0xe627b754df9ee7265f1031cc946bb27d1de8dbb29a7e745453682420b5d9ee76\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610ab1806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063af52770114610030575b600080fd5b61004361003e3660046108d6565b610045565b005b6101267fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131f6020527f699d9daa71b280d05a152715774afa0a81a312594b2d731d6b0b2552b7d6f69f8054600160ff1991821681179092557ff97e938d8af42f52387bb74b8b526fda8f184cc2aa534340a8d75a88fbecc77580548216831790557f65d510a5d8f7ef134ec444f7f34ee808c8eeb5177cdfd16be0c40fe1ab43369580548216831790556307f5828d60e41b6000527f5622121b47b8cd0120c4efe45dd5483242f54a3d49bd7679be565d47694918c380549091169091179055565b61016d61013660e0830183610912565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506101be92505050565b610181813560208301356040840135610260565b6101ae608082013561019960c0840160a08501610963565b6101a960e0850160c08601610963565b610339565b6101bb8160600135610407565b50565b80517f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fc90600881111561022d5760405162461bcd60e51b8152602060048201526012602482015271757020746f20382076616c696461746f727360701b60448201526064015b60405180910390fd5b8251610242906001840190602086019061085c565b5060028201819055610253816104ae565b8260030181905550505050565b7fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c8381557fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189d805463ffffffff8481166401000000000267ffffffffffffffff19909216868216179190911773ffffffff00000000ffffffff0000000000000000191642909116600160401b0263ffffffff60801b191617905560408051848152602081018490527fd6f5a5cd17f05cf9045751ee10f662f62e569c9371ffec8380510aabe63012d391015b60405180910390a150505050565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc748390557f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7580546001600160a01b038481166001600160a01b031992831681179093557f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7380549185169190921681178255604080518781526020810194909452830152907f5b54873359173c3d639e39928ad34e113039ce7c799d500e57f8a2c703adb4779060600161032b565b7f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff6003821080159061043a575060408211155b6104865760405162461bcd60e51b815260206004820152601960248201527f4c6f67206f6620696e7075742073697a653a205b332c36345d000000000000006044820152606401610224565b6001821b60028201556040805160208101909152600081526104a990829061050f565b505050565b600060088211156104f65760405162461bcd60e51b8152602060048201526012602482015271757020746f20382076616c696461746f727360701b6044820152606401610224565b6000610505600180851b6109b8565b60f01b9392505050565b600061051c838330610523565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c91111561059d5760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d00000000000000006044820152606401610224565b6105a6816106c8565b156105b4576105b48561079b565b600085600301546000146105cb57856001016105cd565b855b905060006105da836107ba565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e0840182905261010080850182905285518086039091018152610120909401909452825192820192909220600180860189556000898152929092209094018490558654949550909391929161067f91906109b8565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d6040516106b3939291906109cf565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff1660028111156106f0576106f061098c565b600184015490915063ffffffff600160401b820481169116600083600281111561071c5761071c61098c565b148015610731575061072e8183610a3b565b42115b15610790576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f9161077d91610a53565b60405180910390a1506001949350505050565b506000949350505050565b6003810154156107ac5760006107af565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff1660028111156108265761082661098c565b9050600081600281111561083c5761083c61098c565b146108515761084c826001610a3b565b610853565b815b95945050505050565b8280548282559060005260206000209081019282156108b1579160200282015b828111156108b157825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061087c565b506108bd9291506108c1565b5090565b5b808211156108bd57600081556001016108c2565b6000602082840312156108e857600080fd5b813567ffffffffffffffff8111156108ff57600080fd5b8201610100818503121561051c57600080fd5b6000808335601e1984360301811261092957600080fd5b83018035915067ffffffffffffffff82111561094457600080fd5b6020019150600581901b360382131561095c57600080fd5b9250929050565b60006020828403121561097557600080fd5b81356001600160a01b038116811461051c57600080fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156109ca576109ca6109a2565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015610a11578581018301518582016080015282016109f5565b81811115610a23576000608083870101525b50601f01601f19169290920160800195945050505050565b60008219821115610a4e57610a4e6109a2565b500190565b6020810160038310610a7557634e487b7160e01b600052602160045260246000fd5b9190529056fea26469706673582212205c1aea48b8585467b96c762ebc1e8162451390f82e4d8071d25e6dfba85f22bb64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063af52770114610030575b600080fd5b61004361003e3660046108d6565b610045565b005b6101267fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131f6020527f699d9daa71b280d05a152715774afa0a81a312594b2d731d6b0b2552b7d6f69f8054600160ff1991821681179092557ff97e938d8af42f52387bb74b8b526fda8f184cc2aa534340a8d75a88fbecc77580548216831790557f65d510a5d8f7ef134ec444f7f34ee808c8eeb5177cdfd16be0c40fe1ab43369580548216831790556307f5828d60e41b6000527f5622121b47b8cd0120c4efe45dd5483242f54a3d49bd7679be565d47694918c380549091169091179055565b61016d61013660e0830183610912565b808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152506101be92505050565b610181813560208301356040840135610260565b6101ae608082013561019960c0840160a08501610963565b6101a960e0850160c08601610963565b610339565b6101bb8160600135610407565b50565b80517f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fc90600881111561022d5760405162461bcd60e51b8152602060048201526012602482015271757020746f20382076616c696461746f727360701b60448201526064015b60405180910390fd5b8251610242906001840190602086019061085c565b5060028201819055610253816104ae565b8260030181905550505050565b7fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c8381557fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189d805463ffffffff8481166401000000000267ffffffffffffffff19909216868216179190911773ffffffff00000000ffffffff0000000000000000191642909116600160401b0263ffffffff60801b191617905560408051848152602081018490527fd6f5a5cd17f05cf9045751ee10f662f62e569c9371ffec8380510aabe63012d391015b60405180910390a150505050565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc748390557f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7580546001600160a01b038481166001600160a01b031992831681179093557f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7380549185169190921681178255604080518781526020810194909452830152907f5b54873359173c3d639e39928ad34e113039ce7c799d500e57f8a2c703adb4779060600161032b565b7f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff6003821080159061043a575060408211155b6104865760405162461bcd60e51b815260206004820152601960248201527f4c6f67206f6620696e7075742073697a653a205b332c36345d000000000000006044820152606401610224565b6001821b60028201556040805160208101909152600081526104a990829061050f565b505050565b600060088211156104f65760405162461bcd60e51b8152602060048201526012602482015271757020746f20382076616c696461746f727360701b6044820152606401610224565b6000610505600180851b6109b8565b60f01b9392505050565b600061051c838330610523565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c91111561059d5760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d00000000000000006044820152606401610224565b6105a6816106c8565b156105b4576105b48561079b565b600085600301546000146105cb57856001016105cd565b855b905060006105da836107ba565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e0840182905261010080850182905285518086039091018152610120909401909452825192820192909220600180860189556000898152929092209094018490558654949550909391929161067f91906109b8565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d6040516106b3939291906109cf565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff1660028111156106f0576106f061098c565b600184015490915063ffffffff600160401b820481169116600083600281111561071c5761071c61098c565b148015610731575061072e8183610a3b565b42115b15610790576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f9161077d91610a53565b60405180910390a1506001949350505050565b506000949350505050565b6003810154156107ac5760006107af565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff1660028111156108265761082661098c565b9050600081600281111561083c5761083c61098c565b146108515761084c826001610a3b565b610853565b815b95945050505050565b8280548282559060005260206000209081019282156108b1579160200282015b828111156108b157825182546001600160a01b0319166001600160a01b0390911617825560209092019160019091019061087c565b506108bd9291506108c1565b5090565b5b808211156108bd57600081556001016108c2565b6000602082840312156108e857600080fd5b813567ffffffffffffffff8111156108ff57600080fd5b8201610100818503121561051c57600080fd5b6000808335601e1984360301811261092957600080fd5b83018035915067ffffffffffffffff82111561094457600080fd5b6020019150600581901b360382131561095c57600080fd5b9250929050565b60006020828403121561097557600080fd5b81356001600160a01b038116811461051c57600080fd5b634e487b7160e01b600052602160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000828210156109ca576109ca6109a2565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015610a11578581018301518582016080015282016109f5565b81811115610a23576000608083870101525b50601f01601f19169290920160800195945050505050565b60008219821115610a4e57610a4e6109a2565b500190565b6020810160038310610a7557634e487b7160e01b600052602160045260246000fd5b9190529056fea26469706673582212205c1aea48b8585467b96c762ebc1e8162451390f82e4d8071d25e6dfba85f22bb64736f6c634300080d0033", + "libraries": { + "LibClaimsMask": "0x9A676e781A523b5d0C0e43731313A708CB607508" + }, + "devdoc": { + "events": { + "FeeManagerInitialized(uint256,address,address)": { + "params": { + "feeManagerBank": "fee manager bank address", + "feeManagerOwner": "fee manager owner address", + "feePerClaim": "fee per claim to reward the validators" + } + }, + "RollupsInitialized(uint256,uint256)": { + "params": { + "challengePeriod": "duration of challenge period in seconds", + "inputDuration": "duration of input accumulation phase in seconds" + } + } + }, + "kind": "dev", + "methods": { + "init((bytes32,uint256,uint256,uint256,uint256,address,address,address[]))": { + "params": { + "_dConfig": "diamond configurations" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "FeeManagerInitialized(uint256,address,address)": { + "notice": "FeeManagerImpl contract initialized" + }, + "RollupsInitialized(uint256,uint256)": { + "notice": "rollups contract initialized" + } + }, + "kind": "user", + "methods": { + "init((bytes32,uint256,uint256,uint256,uint256,address,address,address[]))": { + "notice": "initialize the diamond" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/DiamondLoupeFacet.json b/echo-js/deployments/localhost/DiamondLoupeFacet.json new file mode 100644 index 00000000..9f06b2da --- /dev/null +++ b/echo-js/deployments/localhost/DiamondLoupeFacet.json @@ -0,0 +1,177 @@ +{ + "address": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_functionSelector", + "type": "bytes4" + } + ], + "name": "facetAddress", + "outputs": [ + { + "internalType": "address", + "name": "facetAddress_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facetAddresses", + "outputs": [ + { + "internalType": "address[]", + "name": "facetAddresses_", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_facet", + "type": "address" + } + ], + "name": "facetFunctionSelectors", + "outputs": [ + { + "internalType": "bytes4[]", + "name": "facetFunctionSelectors_", + "type": "bytes4[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "facets", + "outputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "internalType": "struct IDiamondLoupe.Facet[]", + "name": "facets_", + "type": "tuple[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "_interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x3c71f7831330670d9ba13bc3ac8fa0e1809abd4d535b07d16a34c505a62176ed", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0", + "transactionIndex": 0, + "gasUsed": "669250", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xbc8e3fd943c16680aa8c7c0d600b556b2101cc5eeaf1357b77900454236748de", + "transactionHash": "0x3c71f7831330670d9ba13bc3ac8fa0e1809abd4d535b07d16a34c505a62176ed", + "logs": [], + "blockNumber": 13, + "cumulativeGasUsed": "669250", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_functionSelector\",\"type\":\"bytes4\"}],\"name\":\"facetAddress\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"facetAddress_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facetAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"facetAddresses_\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_facet\",\"type\":\"address\"}],\"name\":\"facetFunctionSelectors\",\"outputs\":[{\"internalType\":\"bytes4[]\",\"name\":\"facetFunctionSelectors_\",\"type\":\"bytes4[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"facets\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"internalType\":\"struct IDiamondLoupe.Facet[]\",\"name\":\"facets_\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"_interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"facetAddress(bytes4)\":{\"details\":\"If facet is not found return address(0).\",\"params\":{\"_functionSelector\":\"The function selector.\"},\"returns\":{\"facetAddress_\":\"The facet address.\"}},\"facetAddresses()\":{\"returns\":{\"facetAddresses_\":\"facetAddresses_\"}},\"facetFunctionSelectors(address)\":{\"params\":{\"_facet\":\"The facet address.\"},\"returns\":{\"facetFunctionSelectors_\":\"The selectors associated with a facet address.\"}},\"facets()\":{\"returns\":{\"facets_\":\"Facet\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"facetAddress(bytes4)\":{\"notice\":\"Gets the facet that supports the given selector.\"},\"facetAddresses()\":{\"notice\":\"Get all the facet addresses used by a diamond.\"},\"facetFunctionSelectors(address)\":{\"notice\":\"Gets all the function selectors supported by a specific facet.\"},\"facets()\":{\"notice\":\"Gets all facets and their selectors.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/DiamondLoupeFacet.sol\":\"DiamondLoupeFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/facets/DiamondLoupeFacet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\nimport {LibDiamond} from \\\"../libraries/LibDiamond.sol\\\";\\nimport {IDiamondLoupe} from \\\"../interfaces/IDiamondLoupe.sol\\\";\\nimport {IERC165} from \\\"@openzeppelin/contracts/utils/introspection/IERC165.sol\\\";\\n\\ncontract DiamondLoupeFacet is IDiamondLoupe, IERC165 {\\n // Diamond Loupe Functions\\n ////////////////////////////////////////////////////////////////////\\n /// These functions are expected to be called frequently by tools.\\n //\\n // struct Facet {\\n // address facetAddress;\\n // bytes4[] functionSelectors;\\n // }\\n\\n /// @notice Gets all facets and their selectors.\\n /// @return facets_ Facet\\n function facets() external view override returns (Facet[] memory facets_) {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n facets_ = new Facet[](ds.selectorCount);\\n uint8[] memory numFacetSelectors = new uint8[](ds.selectorCount);\\n uint256 numFacets;\\n uint256 selectorIndex;\\n // loop through function selectors\\n for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) {\\n bytes32 slot = ds.selectorSlots[slotIndex];\\n for (\\n uint256 selectorSlotIndex;\\n selectorSlotIndex < 8;\\n selectorSlotIndex++\\n ) {\\n selectorIndex++;\\n if (selectorIndex > ds.selectorCount) {\\n break;\\n }\\n bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));\\n address facetAddress_ = address(bytes20(ds.facets[selector]));\\n bool continueLoop;\\n for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {\\n if (facets_[facetIndex].facetAddress == facetAddress_) {\\n facets_[facetIndex].functionSelectors[\\n numFacetSelectors[facetIndex]\\n ] = selector;\\n // probably will never have more than 256 functions from one facet contract\\n require(numFacetSelectors[facetIndex] < 255);\\n numFacetSelectors[facetIndex]++;\\n continueLoop = true;\\n break;\\n }\\n }\\n if (continueLoop) {\\n continue;\\n }\\n facets_[numFacets].facetAddress = facetAddress_;\\n facets_[numFacets].functionSelectors = new bytes4[](\\n ds.selectorCount\\n );\\n facets_[numFacets].functionSelectors[0] = selector;\\n numFacetSelectors[numFacets] = 1;\\n numFacets++;\\n }\\n }\\n for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {\\n uint256 numSelectors = numFacetSelectors[facetIndex];\\n bytes4[] memory selectors = facets_[facetIndex].functionSelectors;\\n // setting the number of selectors\\n assembly {\\n mstore(selectors, numSelectors)\\n }\\n }\\n // setting the number of facets\\n assembly {\\n mstore(facets_, numFacets)\\n }\\n }\\n\\n /// @notice Gets all the function selectors supported by a specific facet.\\n /// @param _facet The facet address.\\n /// @return facetFunctionSelectors_ The selectors associated with a facet address.\\n function facetFunctionSelectors(address _facet)\\n external\\n view\\n override\\n returns (bytes4[] memory facetFunctionSelectors_)\\n {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n uint256 numSelectors;\\n facetFunctionSelectors_ = new bytes4[](ds.selectorCount);\\n uint256 selectorIndex;\\n // loop through function selectors\\n for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) {\\n bytes32 slot = ds.selectorSlots[slotIndex];\\n for (\\n uint256 selectorSlotIndex;\\n selectorSlotIndex < 8;\\n selectorSlotIndex++\\n ) {\\n selectorIndex++;\\n if (selectorIndex > ds.selectorCount) {\\n break;\\n }\\n bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));\\n address facet = address(bytes20(ds.facets[selector]));\\n if (_facet == facet) {\\n facetFunctionSelectors_[numSelectors] = selector;\\n numSelectors++;\\n }\\n }\\n }\\n // Set the number of selectors in the array\\n assembly {\\n mstore(facetFunctionSelectors_, numSelectors)\\n }\\n }\\n\\n /// @notice Get all the facet addresses used by a diamond.\\n /// @return facetAddresses_\\n function facetAddresses()\\n external\\n view\\n override\\n returns (address[] memory facetAddresses_)\\n {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n facetAddresses_ = new address[](ds.selectorCount);\\n uint256 numFacets;\\n uint256 selectorIndex;\\n // loop through function selectors\\n for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) {\\n bytes32 slot = ds.selectorSlots[slotIndex];\\n for (\\n uint256 selectorSlotIndex;\\n selectorSlotIndex < 8;\\n selectorSlotIndex++\\n ) {\\n selectorIndex++;\\n if (selectorIndex > ds.selectorCount) {\\n break;\\n }\\n bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));\\n address facetAddress_ = address(bytes20(ds.facets[selector]));\\n bool continueLoop;\\n for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {\\n if (facetAddress_ == facetAddresses_[facetIndex]) {\\n continueLoop = true;\\n break;\\n }\\n }\\n if (continueLoop) {\\n continue;\\n }\\n facetAddresses_[numFacets] = facetAddress_;\\n numFacets++;\\n }\\n }\\n // Set the number of facet addresses in the array\\n assembly {\\n mstore(facetAddresses_, numFacets)\\n }\\n }\\n\\n /// @notice Gets the facet that supports the given selector.\\n /// @dev If facet is not found return address(0).\\n /// @param _functionSelector The function selector.\\n /// @return facetAddress_ The facet address.\\n function facetAddress(bytes4 _functionSelector)\\n external\\n view\\n override\\n returns (address facetAddress_)\\n {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n facetAddress_ = address(bytes20(ds.facets[_functionSelector]));\\n }\\n\\n // This implements ERC-165.\\n function supportsInterface(bytes4 _interfaceId)\\n external\\n view\\n override\\n returns (bool)\\n {\\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\\n return ds.supportedInterfaces[_interfaceId];\\n }\\n}\\n\",\"keccak256\":\"0x4d5563813ef6f3a67df8a4350e17e46cdd8c12686a5be976e1e5b7bd24aa0e59\",\"license\":\"MIT\"},\"contracts/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\\n}\\n\",\"keccak256\":\"0x6a3129be1f39b6fec871f2c94bf7debf2d6a4e665547a4d83e7f2def38359e44\",\"license\":\"MIT\"},\"contracts/interfaces/IDiamondLoupe.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\n// A loupe is a small magnifying glass used to look at diamonds.\\n// These functions look at diamonds\\ninterface IDiamondLoupe {\\n /// These functions are expected to be called frequently\\n /// by tools.\\n\\n struct Facet {\\n address facetAddress;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Gets all facet addresses and their four byte function selectors.\\n /// @return facets_ Facet\\n function facets() external view returns (Facet[] memory facets_);\\n\\n /// @notice Gets all the function selectors supported by a specific facet.\\n /// @param _facet The facet address.\\n /// @return facetFunctionSelectors_\\n function facetFunctionSelectors(address _facet)\\n external\\n view\\n returns (bytes4[] memory facetFunctionSelectors_);\\n\\n /// @notice Get all the facet addresses used by a diamond.\\n /// @return facetAddresses_\\n function facetAddresses()\\n external\\n view\\n returns (address[] memory facetAddresses_);\\n\\n /// @notice Gets the facet that supports the given selector.\\n /// @dev If facet is not found return address(0).\\n /// @param _functionSelector The function selector.\\n /// @return facetAddress_ The facet address.\\n function facetAddress(bytes4 _functionSelector)\\n external\\n view\\n returns (address facetAddress_);\\n}\\n\",\"keccak256\":\"0xd6c3796a7c45baea6e47fdd5f2cec95d7796991bc9a949604f99875590962a67\",\"license\":\"MIT\"},\"contracts/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // maps function selectors to the facets that execute the functions.\\n // and maps the selectors to their position in the selectorSlots array.\\n // func selector => address facet, selector position\\n mapping(bytes4 => bytes32) facets;\\n // array of slots of function selectors.\\n // each slot holds 8 function selectors.\\n mapping(uint256 => bytes32) selectorSlots;\\n // The number of function selectors in selectorSlots\\n uint16 selectorCount;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(\\n msg.sender == diamondStorage().contractOwner,\\n \\\"LibDiamond: Must be contract owner\\\"\\n );\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] diamondCut,\\n address init,\\n bytes callData\\n );\\n\\n bytes32 constant CLEAR_ADDRESS_MASK =\\n bytes32(uint256(0xffffffffffffffffffffffff));\\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\\n\\n // Internal function version of diamondCut\\n // This code is almost the same as the external diamondCut,\\n // except it is using 'Facet[] memory _diamondCut' instead of\\n // 'Facet[] calldata _diamondCut'.\\n // The code is duplicated to prevent copying calldata to memory which\\n // causes an error for a two dimensional array.\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n DiamondStorage storage ds = diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addReplaceRemoveFacetSelectors(\\n uint256 _selectorCount,\\n bytes32 _selectorSlot,\\n address _newFacetAddress,\\n IDiamondCut.FacetCutAction _action,\\n bytes4[] memory _selectors\\n ) internal returns (uint256, bytes32) {\\n DiamondStorage storage ds = diamondStorage();\\n require(\\n _selectors.length > 0,\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\n );\\n if (_action == IDiamondCut.FacetCutAction.Add) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Add facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) == address(0),\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\n );\\n // add facet for selector\\n ds.facets[selector] =\\n bytes20(_newFacetAddress) |\\n bytes32(_selectorCount);\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\\n // clear selector position in slot and add selector\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\\n (bytes32(selector) >> selectorInSlotPosition);\\n // if slot is full then write it to storage\\n if (selectorInSlotPosition == 224) {\\n // \\\"_selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"_selectorSlot / 8\\\"\\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\\n _selectorSlot = 0;\\n }\\n _selectorCount++;\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Replace facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n address oldFacetAddress = address(bytes20(oldFacet));\\n // only useful if immutable functions exist\\n require(\\n oldFacetAddress != address(this),\\n \\\"LibDiamondCut: Can't replace immutable function\\\"\\n );\\n require(\\n oldFacetAddress != _newFacetAddress,\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\n );\\n require(\\n oldFacetAddress != address(0),\\n \\\"LibDiamondCut: Can't replace function that doesn't exist\\\"\\n );\\n // replace old facet address\\n ds.facets[selector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(_newFacetAddress);\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\\n require(\\n _newFacetAddress == address(0),\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\n );\\n // \\\"_selectorCount >> 3\\\" is a gas efficient division by 8 \\\"_selectorCount / 8\\\"\\n uint256 selectorSlotCount = _selectorCount >> 3;\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotIndex = _selectorCount & 7;\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n if (_selectorSlot == 0) {\\n // get last selectorSlot\\n selectorSlotCount--;\\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\\n selectorInSlotIndex = 7;\\n } else {\\n selectorInSlotIndex--;\\n }\\n bytes4 lastSelector;\\n uint256 oldSelectorsSlotCount;\\n uint256 oldSelectorInSlotPosition;\\n // adding a block here prevents stack too deep error\\n {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) != address(0),\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\n );\\n // only useful if immutable functions exist\\n require(\\n address(bytes20(oldFacet)) != address(this),\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\n );\\n // replace selector with last selector in ds.facets\\n // gets the last selector\\n lastSelector = bytes4(\\n _selectorSlot << (selectorInSlotIndex << 5)\\n );\\n if (lastSelector != selector) {\\n // update last selector slot position info\\n ds.facets[lastSelector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(ds.facets[lastSelector]);\\n }\\n delete ds.facets[selector];\\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\\n // \\\"oldSelectorCount >> 3\\\" is a gas efficient division by 8 \\\"oldSelectorCount / 8\\\"\\n oldSelectorsSlotCount = oldSelectorCount >> 3;\\n // \\\"oldSelectorCount & 7\\\" is a gas efficient modulo by eight \\\"oldSelectorCount % 8\\\"\\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\\n }\\n if (oldSelectorsSlotCount != selectorSlotCount) {\\n bytes32 oldSelectorSlot = ds.selectorSlots[\\n oldSelectorsSlotCount\\n ];\\n // clears the selector we are deleting and puts the last selector in its place.\\n oldSelectorSlot =\\n (oldSelectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n // update storage with the modified slot\\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\\n } else {\\n // clears the selector we are deleting and puts the last selector in its place.\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n }\\n if (selectorInSlotIndex == 0) {\\n delete ds.selectorSlots[selectorSlotCount];\\n _selectorSlot = 0;\\n }\\n }\\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n return (_selectorCount, _selectorSlot);\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\n internal\\n {\\n if (_init == address(0)) {\\n require(\\n _calldata.length == 0,\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\n );\\n } else {\\n require(\\n _calldata.length > 0,\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\n );\\n if (_init != address(this)) {\\n enforceHasContractCode(\\n _init,\\n \\\"LibDiamondCut: _init address has no code\\\"\\n );\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(\\n address _contract,\\n string memory _errorMessage\\n ) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x740ea3845282f09bb822e66a189ed431ac799ab08184de7457ef53799b2e99d6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610b24806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c57806352ef6b2c146100bd5780637a0ed627146100d2578063adfca15e146100e7578063cdffacc614610107575b600080fd5b6100a861006a3660046108d8565b6001600160e01b03191660009081527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131f602052604090205460ff1690565b60405190151581526020015b60405180910390f35b6100c5610159565b6040516100b49190610909565b6100da61031d565b6040516100b4919061099b565b6100fa6100f5366004610a18565b610766565b6040516100b49190610a41565b6101416101153660046108d8565b6001600160e01b0319166000908152600080516020610acf833981519152602052604090205460601c90565b6040516001600160a01b0390911681526020016100b4565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54606090600080516020610acf8339815191529061ffff1667ffffffffffffffff8111156101aa576101aa610a54565b6040519080825280602002602001820160405280156101d3578160200160208202803683370190505b50915060008060005b600284015461ffff16821015610315576000818152600185016020526040812054905b6008811015610300578361021281610a80565b600288015490955061ffff168511905061030057600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156102a3578a818151811061026857610268610a99565b60200260200101516001600160a01b0316836001600160a01b03160361029157600191506102a3565b8061029b81610a80565b91505061024e565b5080156102b2575050506102ee565b818a89815181106102c5576102c5610a99565b6001600160a01b0390921660209283029190910190910152876102e781610a80565b9850505050505b806102f881610a80565b9150506101ff565b5050808061030d90610a80565b9150506101dc565b505082525090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54606090600080516020610acf8339815191529061ffff1667ffffffffffffffff81111561036e5761036e610a54565b6040519080825280602002602001820160405280156103b457816020015b60408051808201909152600081526060602082015281526020019060019003908161038c5790505b50600282015490925060009061ffff1667ffffffffffffffff8111156103dc576103dc610a54565b604051908082528060200260200182016040528015610405578160200160208202803683370190505b50905060008060005b600285015461ffff168210156106f4576000818152600186016020526040812054905b60088110156106df578361044481610a80565b600289015490955061ffff16851190506106df57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b8881101561059d57826001600160a01b03168c82815181106104a4576104a4610a99565b6020026020010151600001516001600160a01b03160361058b57838c82815181106104d1576104d1610a99565b6020026020010151602001518b83815181106104ef576104ef610a99565b602002602001015160ff168151811061050a5761050a610a99565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a828151811061054057610540610a99565b602002602001015160ff161061055557600080fd5b89818151811061056757610567610a99565b60200260200101805180919061057c90610aaf565b60ff169052506001915061059d565b8061059581610a80565b915050610480565b5080156105ac575050506106cd565b818b89815181106105bf576105bf610a99565b60209081029190910101516001600160a01b03909116905260028a015461ffff1667ffffffffffffffff8111156105f8576105f8610a54565b604051908082528060200260200182016040528015610621578160200160208202803683370190505b508b898151811061063457610634610a99565b602002602001015160200181905250828b898151811061065657610656610a99565b60200260200101516020015160008151811061067457610674610a99565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060018989815181106106aa576106aa610a99565b60ff90921660209283029190910190910152876106c681610a80565b9850505050505b806106d781610a80565b915050610431565b505080806106ec90610a80565b91505061040e565b5060005b8281101561075b57600084828151811061071457610714610a99565b602002602001015160ff169050600087838151811061073557610735610a99565b60200260200101516020015190508181525050808061075390610a80565b9150506106f8565b508185525050505090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54606090600080516020610acf8339815191529060009061ffff1667ffffffffffffffff8111156107ba576107ba610a54565b6040519080825280602002602001820160405280156107e3578160200160208202803683370190505b5092506000805b600284015461ffff168210156108ce576000818152600185016020526040812054905b60088110156108b9578361082081610a80565b600288015490955061ffff16851190506108b957600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a168190036108a4578189888151811061087d5761087d610a99565b6001600160e01b031990921660209283029190910190910152866108a081610a80565b9750505b505080806108b190610a80565b91505061080d565b505080806108c690610a80565b9150506107ea565b5050825250919050565b6000602082840312156108ea57600080fd5b81356001600160e01b03198116811461090257600080fd5b9392505050565b6020808252825182820181905260009190848201906040850190845b8181101561094a5783516001600160a01b031683529284019291840191600101610925565b50909695505050505050565b600081518084526020808501945080840160005b838110156109905781516001600160e01b0319168752958201959082019060010161096a565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015610a0a57888303603f19018552815180516001600160a01b031684528701518784018790526109f787850182610956565b95880195935050908601906001016109c2565b509098975050505050505050565b600060208284031215610a2a57600080fd5b81356001600160a01b038116811461090257600080fd5b6020815260006109026020830184610956565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610a9257610a92610a6a565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff8103610ac557610ac5610a6a565b6001019291505056fec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131ca264697066735822122086a06e4bb376ef3991d7ba70ce00fa4b43cfacb8059c9980f3c1c386a38ed77b64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c806301ffc9a71461005c57806352ef6b2c146100bd5780637a0ed627146100d2578063adfca15e146100e7578063cdffacc614610107575b600080fd5b6100a861006a3660046108d8565b6001600160e01b03191660009081527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131f602052604090205460ff1690565b60405190151581526020015b60405180910390f35b6100c5610159565b6040516100b49190610909565b6100da61031d565b6040516100b4919061099b565b6100fa6100f5366004610a18565b610766565b6040516100b49190610a41565b6101416101153660046108d8565b6001600160e01b0319166000908152600080516020610acf833981519152602052604090205460601c90565b6040516001600160a01b0390911681526020016100b4565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54606090600080516020610acf8339815191529061ffff1667ffffffffffffffff8111156101aa576101aa610a54565b6040519080825280602002602001820160405280156101d3578160200160208202803683370190505b50915060008060005b600284015461ffff16821015610315576000818152600185016020526040812054905b6008811015610300578361021281610a80565b600288015490955061ffff168511905061030057600581901b82901b6001600160e01b0319811660009081526020889052604081205460601c90805b888110156102a3578a818151811061026857610268610a99565b60200260200101516001600160a01b0316836001600160a01b03160361029157600191506102a3565b8061029b81610a80565b91505061024e565b5080156102b2575050506102ee565b818a89815181106102c5576102c5610a99565b6001600160a01b0390921660209283029190910190910152876102e781610a80565b9850505050505b806102f881610a80565b9150506101ff565b5050808061030d90610a80565b9150506101dc565b505082525090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54606090600080516020610acf8339815191529061ffff1667ffffffffffffffff81111561036e5761036e610a54565b6040519080825280602002602001820160405280156103b457816020015b60408051808201909152600081526060602082015281526020019060019003908161038c5790505b50600282015490925060009061ffff1667ffffffffffffffff8111156103dc576103dc610a54565b604051908082528060200260200182016040528015610405578160200160208202803683370190505b50905060008060005b600285015461ffff168210156106f4576000818152600186016020526040812054905b60088110156106df578361044481610a80565b600289015490955061ffff16851190506106df57600581901b82901b6001600160e01b0319811660009081526020899052604081205460601c90805b8881101561059d57826001600160a01b03168c82815181106104a4576104a4610a99565b6020026020010151600001516001600160a01b03160361058b57838c82815181106104d1576104d1610a99565b6020026020010151602001518b83815181106104ef576104ef610a99565b602002602001015160ff168151811061050a5761050a610a99565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060ff8a828151811061054057610540610a99565b602002602001015160ff161061055557600080fd5b89818151811061056757610567610a99565b60200260200101805180919061057c90610aaf565b60ff169052506001915061059d565b8061059581610a80565b915050610480565b5080156105ac575050506106cd565b818b89815181106105bf576105bf610a99565b60209081029190910101516001600160a01b03909116905260028a015461ffff1667ffffffffffffffff8111156105f8576105f8610a54565b604051908082528060200260200182016040528015610621578160200160208202803683370190505b508b898151811061063457610634610a99565b602002602001015160200181905250828b898151811061065657610656610a99565b60200260200101516020015160008151811061067457610674610a99565b60200260200101906001600160e01b03191690816001600160e01b0319168152505060018989815181106106aa576106aa610a99565b60ff90921660209283029190910190910152876106c681610a80565b9850505050505b806106d781610a80565b915050610431565b505080806106ec90610a80565b91505061040e565b5060005b8281101561075b57600084828151811061071457610714610a99565b602002602001015160ff169050600087838151811061073557610735610a99565b60200260200101516020015190508181525050808061075390610a80565b9150506106f8565b508185525050505090565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131e54606090600080516020610acf8339815191529060009061ffff1667ffffffffffffffff8111156107ba576107ba610a54565b6040519080825280602002602001820160405280156107e3578160200160208202803683370190505b5092506000805b600284015461ffff168210156108ce576000818152600185016020526040812054905b60088110156108b9578361082081610a80565b600288015490955061ffff16851190506108b957600581901b82901b6001600160e01b0319811660009081526020889052604090205460601c6001600160a01b038a168190036108a4578189888151811061087d5761087d610a99565b6001600160e01b031990921660209283029190910190910152866108a081610a80565b9750505b505080806108b190610a80565b91505061080d565b505080806108c690610a80565b9150506107ea565b5050825250919050565b6000602082840312156108ea57600080fd5b81356001600160e01b03198116811461090257600080fd5b9392505050565b6020808252825182820181905260009190848201906040850190845b8181101561094a5783516001600160a01b031683529284019291840191600101610925565b50909695505050505050565b600081518084526020808501945080840160005b838110156109905781516001600160e01b0319168752958201959082019060010161096a565b509495945050505050565b60006020808301818452808551808352604092508286019150828160051b87010184880160005b83811015610a0a57888303603f19018552815180516001600160a01b031684528701518784018790526109f787850182610956565b95880195935050908601906001016109c2565b509098975050505050505050565b600060208284031215610a2a57600080fd5b81356001600160a01b038116811461090257600080fd5b6020815260006109026020830184610956565b634e487b7160e01b600052604160045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600060018201610a9257610a92610a6a565b5060010190565b634e487b7160e01b600052603260045260246000fd5b600060ff821660ff8103610ac557610ac5610a6a565b6001019291505056fec8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131ca264697066735822122086a06e4bb376ef3991d7ba70ce00fa4b43cfacb8059c9980f3c1c386a38ed77b64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "facetAddress(bytes4)": { + "details": "If facet is not found return address(0).", + "params": { + "_functionSelector": "The function selector." + }, + "returns": { + "facetAddress_": "The facet address." + } + }, + "facetAddresses()": { + "returns": { + "facetAddresses_": "facetAddresses_" + } + }, + "facetFunctionSelectors(address)": { + "params": { + "_facet": "The facet address." + }, + "returns": { + "facetFunctionSelectors_": "The selectors associated with a facet address." + } + }, + "facets()": { + "returns": { + "facets_": "Facet" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "facetAddress(bytes4)": { + "notice": "Gets the facet that supports the given selector." + }, + "facetAddresses()": { + "notice": "Get all the facet addresses used by a diamond." + }, + "facetFunctionSelectors(address)": { + "notice": "Gets all the function selectors supported by a specific facet." + }, + "facets()": { + "notice": "Gets all facets and their selectors." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/ERC20PortalFacet.json b/echo-js/deployments/localhost/ERC20PortalFacet.json new file mode 100644 index 00000000..666905e6 --- /dev/null +++ b/echo-js/deployments/localhost/ERC20PortalFacet.json @@ -0,0 +1,121 @@ +{ + "address": "0x59b670e9fA9D0A427751Af201D676719a970857b", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "ERC20", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ERC20Deposited", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_ERC20", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_amount", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "erc20Deposit", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x1effcf7afd0dc630ee782e48cb2b730f02214c59da2db79b5558cf50249a88d0", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x59b670e9fA9D0A427751Af201D676719a970857b", + "transactionIndex": 0, + "gasUsed": "479906", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x2a8665409aefab35b129928bef7be8a23247709fb6947d8411b5b2219925812f", + "transactionHash": "0x1effcf7afd0dc630ee782e48cb2b730f02214c59da2db79b5558cf50249a88d0", + "logs": [], + "blockNumber": 22, + "cumulativeGasUsed": "479906", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"ERC20\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ERC20Deposited\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_ERC20\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_amount\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"erc20Deposit\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"erc20Deposit(address,uint256,bytes)\":{\"params\":{\"_ERC20\":\"address of the ERC20 token contract\",\"_amount\":\"amount of the ERC20 token to be deposited\",\"_data\":\"information to be interpreted by L2\"},\"returns\":{\"_0\":\"hash of input generated by deposit\"}}},\"version\":1},\"userdoc\":{\"events\":{\"ERC20Deposited(address,address,uint256,bytes)\":{\"notice\":\"emitted on ERC20 deposited\"}},\"kind\":\"user\",\"methods\":{\"erc20Deposit(address,uint256,bytes)\":{\"notice\":\"deposit an amount of a generic ERC20 in the portal and create tokens in L2\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ERC20PortalFacet.sol\":\"ERC20PortalFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/ERC20PortalFacet.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Generic ERC20 Portal facet\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nimport {IERC20Portal} from \\\"../interfaces/IERC20Portal.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\n\\ncontract ERC20PortalFacet is IERC20Portal {\\n using LibInput for LibInput.DiamondStorage;\\n\\n bytes32 constant INPUT_HEADER = keccak256(\\\"ERC20_Transfer\\\");\\n\\n /// @notice deposit an amount of a generic ERC20 in the portal and create tokens in L2\\n /// @param _ERC20 address of the ERC20 token contract\\n /// @param _amount amount of the ERC20 token to be deposited\\n /// @param _data information to be interpreted by L2\\n /// @return hash of input generated by deposit\\n function erc20Deposit(\\n address _ERC20,\\n uint256 _amount,\\n bytes calldata _data\\n ) public override returns (bytes32) {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n IERC20 token = IERC20(_ERC20);\\n\\n require(\\n token.transferFrom(msg.sender, address(this), _amount),\\n \\\"ERC20 transferFrom failed\\\"\\n );\\n\\n bytes memory input = abi.encode(\\n INPUT_HEADER,\\n msg.sender,\\n _ERC20,\\n _amount,\\n _data\\n );\\n\\n emit ERC20Deposited(_ERC20, msg.sender, _amount, _data);\\n return inputDS.addInternalInput(input);\\n }\\n}\\n\",\"keccak256\":\"0x30d5d1aad8854d02b7783c1b07812bc8a637d64c2dcf43638aeb7c62de47ed3a\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC20Portal.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Generic ERC20 Portal interface\\npragma solidity >=0.7.0;\\n\\ninterface IERC20Portal {\\n /// @notice deposit an amount of a generic ERC20 token in the portal and create tokens in L2\\n /// @param _ERC20 address of the ERC20 token contract\\n /// @param _amount amount of the ERC20 token to be deposited\\n /// @param _data information to be interpreted by L2\\n /// @return hash of input generated by deposit\\n function erc20Deposit(\\n address _ERC20,\\n uint256 _amount,\\n bytes calldata _data\\n ) external returns (bytes32);\\n\\n /// @notice emitted on ERC20 deposited\\n event ERC20Deposited(\\n address ERC20,\\n address sender,\\n uint256 amount,\\n bytes data\\n );\\n}\\n\",\"keccak256\":\"0xc252480d20774dc9d6bdb0f632e364f4232d3be447db5a45f86ae1c904adacc6\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506107b9806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063cb1061a614610030575b600080fd5b61004361003e36600461053b565b610055565b60405190815260200160405180910390f35b6000807f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff6040516323b872dd60e01b81523360048201523060248201526044810187905290915086906001600160a01b038216906323b872dd906064016020604051808303816000875af11580156100d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f591906105d0565b6101465760405162461bcd60e51b815260206004820152601960248201527f4552433230207472616e7366657246726f6d206661696c65640000000000000060448201526064015b60405180910390fd5b60007f59da2a984e165ae4487c99e5d1dca7e04c8a99301be6bc092932cb5d7f03437833898989896040516020016101839695949392919061061b565b60405160208183030381529060405290507f29e6a9ed1b00933e0de5679ea9bc6ad323969a70b69b627425b46ac0431c7b0188338989896040516101cb959493929190610655565b60405180910390a16101dd83826101e9565b98975050505050505050565b60006101f68383306101fd565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c9111156102775760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d0000000000000000604482015260640161013d565b610280816103a2565b1561028e5761028e8561047a565b600085600301546000146102a557856001016102a7565b855b905060006102b483610499565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e0840182905261010080850182905285518086039091018152610120909401909452825192820192909220600180860189556000898152929092209094018490558654949550909391929161035991906106aa565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d60405161038d939291906106c1565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff1660028111156103ca576103ca61072d565b600184015490915063ffffffff6801000000000000000082048116911660008360028111156103fb576103fb61072d565b148015610410575061040d8183610743565b42115b1561046f576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f9161045c9161075b565b60405180910390a1506001949350505050565b506000949350505050565b60038101541561048b57600061048e565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff1660028111156105055761050561072d565b9050600081600281111561051b5761051b61072d565b146105305761052b826001610743565b610532565b815b95945050505050565b6000806000806060858703121561055157600080fd5b84356001600160a01b038116811461056857600080fd5b935060208501359250604085013567ffffffffffffffff8082111561058c57600080fd5b818701915087601f8301126105a057600080fd5b8135818111156105af57600080fd5b8860208285010111156105c157600080fd5b95989497505060200194505050565b6000602082840312156105e257600080fd5b815180151581146101f657600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8681526001600160a01b038681166020830152851660408201526060810184905260a0608082018190526000906101dd90830184866105f2565b6001600160a01b038681168252851660208201526040810184905260806060820181905260009061068990830184866105f2565b979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156106bc576106bc610694565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015610703578581018301518582016080015282016106e7565b81811115610715576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b6000821982111561075657610756610694565b500190565b602081016003831061077d57634e487b7160e01b600052602160045260246000fd5b9190529056fea264697066735822122085f1f711a938addfee9fe400008e8e390be52bc8e586f1c69e748d85d44bc31064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063cb1061a614610030575b600080fd5b61004361003e36600461053b565b610055565b60405190815260200160405180910390f35b6000807f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff6040516323b872dd60e01b81523360048201523060248201526044810187905290915086906001600160a01b038216906323b872dd906064016020604051808303816000875af11580156100d1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906100f591906105d0565b6101465760405162461bcd60e51b815260206004820152601960248201527f4552433230207472616e7366657246726f6d206661696c65640000000000000060448201526064015b60405180910390fd5b60007f59da2a984e165ae4487c99e5d1dca7e04c8a99301be6bc092932cb5d7f03437833898989896040516020016101839695949392919061061b565b60405160208183030381529060405290507f29e6a9ed1b00933e0de5679ea9bc6ad323969a70b69b627425b46ac0431c7b0188338989896040516101cb959493929190610655565b60405180910390a16101dd83826101e9565b98975050505050505050565b60006101f68383306101fd565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c9111156102775760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d0000000000000000604482015260640161013d565b610280816103a2565b1561028e5761028e8561047a565b600085600301546000146102a557856001016102a7565b855b905060006102b483610499565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e0840182905261010080850182905285518086039091018152610120909401909452825192820192909220600180860189556000898152929092209094018490558654949550909391929161035991906106aa565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d60405161038d939291906106c1565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff1660028111156103ca576103ca61072d565b600184015490915063ffffffff6801000000000000000082048116911660008360028111156103fb576103fb61072d565b148015610410575061040d8183610743565b42115b1561046f576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f9161045c9161075b565b60405180910390a1506001949350505050565b506000949350505050565b60038101541561048b57600061048e565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff1660028111156105055761050561072d565b9050600081600281111561051b5761051b61072d565b146105305761052b826001610743565b610532565b815b95945050505050565b6000806000806060858703121561055157600080fd5b84356001600160a01b038116811461056857600080fd5b935060208501359250604085013567ffffffffffffffff8082111561058c57600080fd5b818701915087601f8301126105a057600080fd5b8135818111156105af57600080fd5b8860208285010111156105c157600080fd5b95989497505060200194505050565b6000602082840312156105e257600080fd5b815180151581146101f657600080fd5b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8681526001600160a01b038681166020830152851660408201526060810184905260a0608082018190526000906101dd90830184866105f2565b6001600160a01b038681168252851660208201526040810184905260806060820181905260009061068990830184866105f2565b979650505050505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156106bc576106bc610694565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b81811015610703578581018301518582016080015282016106e7565b81811115610715576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b6000821982111561075657610756610694565b500190565b602081016003831061077d57634e487b7160e01b600052602160045260246000fd5b9190529056fea264697066735822122085f1f711a938addfee9fe400008e8e390be52bc8e586f1c69e748d85d44bc31064736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "erc20Deposit(address,uint256,bytes)": { + "params": { + "_ERC20": "address of the ERC20 token contract", + "_amount": "amount of the ERC20 token to be deposited", + "_data": "information to be interpreted by L2" + }, + "returns": { + "_0": "hash of input generated by deposit" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "ERC20Deposited(address,address,uint256,bytes)": { + "notice": "emitted on ERC20 deposited" + } + }, + "kind": "user", + "methods": { + "erc20Deposit(address,uint256,bytes)": { + "notice": "deposit an amount of a generic ERC20 in the portal and create tokens in L2" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/ERC721PortalFacet.json b/echo-js/deployments/localhost/ERC721PortalFacet.json new file mode 100644 index 00000000..ab0cb0ea --- /dev/null +++ b/echo-js/deployments/localhost/ERC721PortalFacet.json @@ -0,0 +1,190 @@ +{ + "address": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "ERC721", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "operator", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "ERC721Received", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "ERC721", + "type": "address" + }, + { + "indexed": false, + "internalType": "address payable", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "tokenId", + "type": "uint256" + } + ], + "name": "ERC721Withdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "erc721Withdrawal", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_operator", + "type": "address" + }, + { + "internalType": "address", + "name": "_from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "_tokenId", + "type": "uint256" + }, + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "onERC721Received", + "outputs": [ + { + "internalType": "bytes4", + "name": "", + "type": "bytes4" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x37a6600202a16cb710e7bfde0a1796caa589c752db1187989d04ad27dbd4463e", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1", + "transactionIndex": 0, + "gasUsed": "555119", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x0d36fc220a283ade63173169ccc5b967a727200a01ee764f2d702f26038848a4", + "transactionHash": "0x37a6600202a16cb710e7bfde0a1796caa589c752db1187989d04ad27dbd4463e", + "logs": [], + "blockNumber": 23, + "cumulativeGasUsed": "555119", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"ERC721\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"operator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"ERC721Received\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"ERC721\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address payable\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"tokenId\",\"type\":\"uint256\"}],\"name\":\"ERC721Withdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"erc721Withdrawal\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_operator\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"onERC721Received\",\"outputs\":[{\"internalType\":\"bytes4\",\"name\":\"\",\"type\":\"bytes4\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"erc721Withdrawal(bytes)\":{\"details\":\"can only be called by the Rollups contract\",\"params\":{\"_data\":\"data with withdrawal information\"}},\"onERC721Received(address,address,uint256,bytes)\":{\"details\":\"The ERC721 smart contract calls this function on the recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return of other than the magic value MUST result in the transaction being reverted. Note: the contract address is always the message sender.\",\"params\":{\"_data\":\"Additional data to be interpreted by L2\",\"_from\":\"The address which previously owned the token\",\"_operator\":\"The address which called `safeTransferFrom` function\",\"_tokenId\":\"The NFT identifier which is being transferred\"},\"returns\":{\"_0\":\"this function selector unless throwing\"}}},\"version\":1},\"userdoc\":{\"events\":{\"ERC721Received(address,address,address,uint256,bytes)\":{\"notice\":\"emitted on a call to `onERC721Received`\"},\"ERC721Withdrawn(address,address,uint256)\":{\"notice\":\"emitted on ERC721 withdrawal\"}},\"kind\":\"user\",\"methods\":{\"erc721Withdrawal(bytes)\":{\"notice\":\"withdraw an ERC721 token from the portal\"},\"onERC721Received(address,address,uint256,bytes)\":{\"notice\":\"Handle the receipt of an NFT\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ERC721PortalFacet.sol\":\"ERC721PortalFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../../utils/introspection/IERC165.sol\\\";\\n\\n/**\\n * @dev Required interface of an ERC721 compliant contract.\\n */\\ninterface IERC721 is IERC165 {\\n /**\\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\\n */\\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\\n\\n /**\\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\\n */\\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\\n\\n /**\\n * @dev Returns the number of tokens in ``owner``'s account.\\n */\\n function balanceOf(address owner) external view returns (uint256 balance);\\n\\n /**\\n * @dev Returns the owner of the `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function ownerOf(uint256 tokenId) external view returns (address owner);\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId,\\n bytes calldata data\\n ) external;\\n\\n /**\\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must exist and be owned by `from`.\\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\\n *\\n * Emits a {Transfer} event.\\n */\\n function safeTransferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Transfers `tokenId` token from `from` to `to`.\\n *\\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `tokenId` token must be owned by `from`.\\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 tokenId\\n ) external;\\n\\n /**\\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\\n * The approval is cleared when the token is transferred.\\n *\\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\\n *\\n * Requirements:\\n *\\n * - The caller must own the token or be an approved operator.\\n * - `tokenId` must exist.\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address to, uint256 tokenId) external;\\n\\n /**\\n * @dev Approve or remove `operator` as an operator for the caller.\\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\\n *\\n * Requirements:\\n *\\n * - The `operator` cannot be the caller.\\n *\\n * Emits an {ApprovalForAll} event.\\n */\\n function setApprovalForAll(address operator, bool _approved) external;\\n\\n /**\\n * @dev Returns the account approved for `tokenId` token.\\n *\\n * Requirements:\\n *\\n * - `tokenId` must exist.\\n */\\n function getApproved(uint256 tokenId) external view returns (address operator);\\n\\n /**\\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\\n *\\n * See {setApprovalForAll}\\n */\\n function isApprovedForAll(address owner, address operator) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x0d4de01fe5360c38b4ad2b0822a12722958428f5138a7ff47c1720eb6fa52bba\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @title ERC721 token receiver interface\\n * @dev Interface for any contract that wants to support safeTransfers\\n * from ERC721 asset contracts.\\n */\\ninterface IERC721Receiver {\\n /**\\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\\n * by `operator` from `from`, this function is called.\\n *\\n * It must return its Solidity selector to confirm the token transfer.\\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\\n *\\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\\n */\\n function onERC721Received(\\n address operator,\\n address from,\\n uint256 tokenId,\\n bytes calldata data\\n ) external returns (bytes4);\\n}\\n\",\"keccak256\":\"0xa82b58eca1ee256be466e536706850163d2ec7821945abd6b4778cfb3bee37da\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/introspection/IERC165.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC165 standard, as defined in the\\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\\n *\\n * Implementers can declare support of contract interfaces, which can then be\\n * queried by others ({ERC165Checker}).\\n *\\n * For an implementation, see {ERC165}.\\n */\\ninterface IERC165 {\\n /**\\n * @dev Returns true if this contract implements the interface defined by\\n * `interfaceId`. See the corresponding\\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\\n * to learn more about how these ids are created.\\n *\\n * This function call must use less than 30 000 gas.\\n */\\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x447a5f3ddc18419d41ff92b3773fb86471b1db25773e07f877f548918a185bf1\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/ERC721PortalFacet.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Generic ERC721 Portal facet\\npragma solidity ^0.8.0;\\n\\nimport {IERC721} from \\\"@openzeppelin/contracts/token/ERC721/IERC721.sol\\\";\\n\\nimport {IERC721Portal} from \\\"../interfaces/IERC721Portal.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\n\\ncontract ERC721PortalFacet is IERC721Portal {\\n using LibInput for LibInput.DiamondStorage;\\n\\n bytes32 constant INPUT_HEADER = keccak256(\\\"ERC721_Transfer\\\");\\n\\n /// @notice Handle the receipt of an NFT\\n /// @dev The ERC721 smart contract calls this function on the recipient\\n /// after a `transfer`. This function MAY throw to revert and reject the\\n /// transfer. Return of other than the magic value MUST result in the\\n /// transaction being reverted.\\n /// Note: the contract address is always the message sender.\\n /// @param _operator The address which called `safeTransferFrom` function\\n /// @param _from The address which previously owned the token\\n /// @param _tokenId The NFT identifier which is being transferred\\n /// @param _data Additional data to be interpreted by L2\\n /// @return this function selector unless throwing\\n function onERC721Received(\\n address _operator,\\n address _from,\\n uint256 _tokenId,\\n bytes calldata _data\\n ) public override returns (bytes4) {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n address erc721Contract = msg.sender;\\n\\n bytes memory input = abi.encode(\\n INPUT_HEADER,\\n erc721Contract,\\n _operator,\\n _from,\\n _tokenId,\\n _data\\n );\\n\\n inputDS.addInternalInput(input);\\n\\n emit ERC721Received(erc721Contract, _operator, _from, _tokenId, _data);\\n\\n // return the magic value to approve the transfer\\n return this.onERC721Received.selector;\\n }\\n\\n /// @notice withdraw an ERC721 token from the portal\\n /// @param _data data with withdrawal information\\n /// @dev can only be called by the Rollups contract\\n function erc721Withdrawal(bytes calldata _data)\\n public\\n override\\n returns (bool)\\n {\\n // Delegate calls preserve msg.sender, msg.value and address(this)\\n require(msg.sender == address(this), \\\"only itself\\\");\\n\\n (address tokenAddr, address payable receiver, uint256 tokenId) = abi\\n .decode(_data, (address, address, uint256));\\n\\n IERC721 token = IERC721(tokenAddr);\\n\\n // transfer reverts on failure\\n token.safeTransferFrom(address(this), receiver, tokenId);\\n\\n emit ERC721Withdrawn(tokenAddr, receiver, tokenId);\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0x87ab790c157e34f53ca132c2b1056fea1728a1c67b62abc7fd83ed08c94a84ff\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IERC721Portal.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Generic ERC721 Portal interface\\npragma solidity >=0.7.0;\\n\\nimport {IERC721Receiver} from \\\"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\\\";\\n\\ninterface IERC721Portal is IERC721Receiver {\\n /// @notice withdraw an ERC721 token from the portal\\n /// @param _data data with withdrawal information\\n /// @dev can only be called by the Rollups contract\\n function erc721Withdrawal(bytes calldata _data) external returns (bool);\\n\\n /// @notice emitted on a call to `onERC721Received`\\n event ERC721Received(\\n address ERC721,\\n address operator,\\n address sender,\\n uint256 tokenId,\\n bytes data\\n );\\n\\n /// @notice emitted on ERC721 withdrawal\\n event ERC721Withdrawn(\\n address ERC721,\\n address payable receiver,\\n uint256 tokenId\\n );\\n}\\n\",\"keccak256\":\"0x44d396dc8754fbbafd5b7cadf77a1acf13d9dab26ce31effc1d7f32308726ca0\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610915806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c8063150b7a021461003b57806315e55ce51461006c575b600080fd5b61004e61004936600461063a565b61008f565b6040516001600160e01b031990911681526020015b60405180910390f35b61007f61007a3660046106ad565b610168565b6040519015158152602001610063565b6040516000907f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff90339083906100f5907f64d9de45e7db1c0a7cb7960ad25107a6379b6ab85b30444f3a8d724857c1ac789084908c908c908c908c908c90602001610718565b60408051601f1981840301815291905290506101118382610287565b507f33dcfebf3eaf42764314a95335af55bb1c008027c47c827e6e09119071639e1d828a8a8a8a8a60405161014b96959493929190610767565b60405180910390a150630a85bd0160e11b98975050505050505050565b60003330146101ac5760405162461bcd60e51b815260206004820152600b60248201526a37b7363c9034ba39b2b63360a91b60448201526064015b60405180910390fd5b600080806101bc858701876107af565b604051632142170760e11b81523060048201526001600160a01b03808416602483015260448201839052939650919450925084918216906342842e0e90606401600060405180830381600087803b15801561021657600080fd5b505af115801561022a573d6000803e3d6000fd5b5050604080516001600160a01b038089168252871660208201529081018590527feea167c0d54572a80626f5fd092a7c1f7b5d8e309533747e7e7d77b0558d6cf19250606001905060405180910390a15060019695505050505050565b600061029483833061029b565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c9111156103155760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d000000000000000060448201526064016101a3565b61031e81610440565b1561032c5761032c85610518565b600085600301546000146103435785600101610345565b855b9050600061035283610537565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e084018290526101008085018290528551808603909101815261012090940190945282519282019290922060018086018955600089815292909220909401849055865494955090939192916103f79190610806565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d60405161042b9392919061081d565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff16600281111561046857610468610889565b600184015490915063ffffffff68010000000000000000820481169116600083600281111561049957610499610889565b1480156104ae57506104ab818361089f565b42115b1561050d576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f916104fa916108b7565b60405180910390a1506001949350505050565b506000949350505050565b60038101541561052957600061052c565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff1660028111156105a3576105a3610889565b905060008160028111156105b9576105b9610889565b146105ce576105c982600161089f565b6105d0565b815b95945050505050565b6001600160a01b03811681146105ee57600080fd5b50565b60008083601f84011261060357600080fd5b50813567ffffffffffffffff81111561061b57600080fd5b60208301915083602082850101111561063357600080fd5b9250929050565b60008060008060006080868803121561065257600080fd5b853561065d816105d9565b9450602086013561066d816105d9565b935060408601359250606086013567ffffffffffffffff81111561069057600080fd5b61069c888289016105f1565b969995985093965092949392505050565b600080602083850312156106c057600080fd5b823567ffffffffffffffff8111156106d757600080fd5b6106e3858286016105f1565b90969095509350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8781526001600160a01b0387811660208301528681166040830152851660608201526080810184905260c060a0820181905260009061075a90830184866106ef565b9998505050505050505050565b6001600160a01b0387811682528681166020830152851660408201526060810184905260a0608082018190526000906107a390830184866106ef565b98975050505050505050565b6000806000606084860312156107c457600080fd5b83356107cf816105d9565b925060208401356107df816105d9565b929592945050506040919091013590565b634e487b7160e01b600052601160045260246000fd5b600082821015610818576108186107f0565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b8181101561085f57858101830151858201608001528201610843565b81811115610871576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b600082198211156108b2576108b26107f0565b500190565b60208101600383106108d957634e487b7160e01b600052602160045260246000fd5b9190529056fea264697066735822122063bd39ba5fcde318ac6f9113d8c4f5275c6487653824db8e78a5e0a317694cac64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c8063150b7a021461003b57806315e55ce51461006c575b600080fd5b61004e61004936600461063a565b61008f565b6040516001600160e01b031990911681526020015b60405180910390f35b61007f61007a3660046106ad565b610168565b6040519015158152602001610063565b6040516000907f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff90339083906100f5907f64d9de45e7db1c0a7cb7960ad25107a6379b6ab85b30444f3a8d724857c1ac789084908c908c908c908c908c90602001610718565b60408051601f1981840301815291905290506101118382610287565b507f33dcfebf3eaf42764314a95335af55bb1c008027c47c827e6e09119071639e1d828a8a8a8a8a60405161014b96959493929190610767565b60405180910390a150630a85bd0160e11b98975050505050505050565b60003330146101ac5760405162461bcd60e51b815260206004820152600b60248201526a37b7363c9034ba39b2b63360a91b60448201526064015b60405180910390fd5b600080806101bc858701876107af565b604051632142170760e11b81523060048201526001600160a01b03808416602483015260448201839052939650919450925084918216906342842e0e90606401600060405180830381600087803b15801561021657600080fd5b505af115801561022a573d6000803e3d6000fd5b5050604080516001600160a01b038089168252871660208201529081018590527feea167c0d54572a80626f5fd092a7c1f7b5d8e309533747e7e7d77b0558d6cf19250606001905060405180910390a15060019695505050505050565b600061029483833061029b565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c9111156103155760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d000000000000000060448201526064016101a3565b61031e81610440565b1561032c5761032c85610518565b600085600301546000146103435785600101610345565b855b9050600061035283610537565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e084018290526101008085018290528551808603909101815261012090940190945282519282019290922060018086018955600089815292909220909401849055865494955090939192916103f79190610806565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d60405161042b9392919061081d565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff16600281111561046857610468610889565b600184015490915063ffffffff68010000000000000000820481169116600083600281111561049957610499610889565b1480156104ae57506104ab818361089f565b42115b1561050d576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f916104fa916108b7565b60405180910390a1506001949350505050565b506000949350505050565b60038101541561052957600061052c565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff1660028111156105a3576105a3610889565b905060008160028111156105b9576105b9610889565b146105ce576105c982600161089f565b6105d0565b815b95945050505050565b6001600160a01b03811681146105ee57600080fd5b50565b60008083601f84011261060357600080fd5b50813567ffffffffffffffff81111561061b57600080fd5b60208301915083602082850101111561063357600080fd5b9250929050565b60008060008060006080868803121561065257600080fd5b853561065d816105d9565b9450602086013561066d816105d9565b935060408601359250606086013567ffffffffffffffff81111561069057600080fd5b61069c888289016105f1565b969995985093965092949392505050565b600080602083850312156106c057600080fd5b823567ffffffffffffffff8111156106d757600080fd5b6106e3858286016105f1565b90969095509350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b8781526001600160a01b0387811660208301528681166040830152851660608201526080810184905260c060a0820181905260009061075a90830184866106ef565b9998505050505050505050565b6001600160a01b0387811682528681166020830152851660408201526060810184905260a0608082018190526000906107a390830184866106ef565b98975050505050505050565b6000806000606084860312156107c457600080fd5b83356107cf816105d9565b925060208401356107df816105d9565b929592945050506040919091013590565b634e487b7160e01b600052601160045260246000fd5b600082821015610818576108186107f0565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b8181101561085f57858101830151858201608001528201610843565b81811115610871576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b600082198211156108b2576108b26107f0565b500190565b60208101600383106108d957634e487b7160e01b600052602160045260246000fd5b9190529056fea264697066735822122063bd39ba5fcde318ac6f9113d8c4f5275c6487653824db8e78a5e0a317694cac64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "erc721Withdrawal(bytes)": { + "details": "can only be called by the Rollups contract", + "params": { + "_data": "data with withdrawal information" + } + }, + "onERC721Received(address,address,uint256,bytes)": { + "details": "The ERC721 smart contract calls this function on the recipient after a `transfer`. This function MAY throw to revert and reject the transfer. Return of other than the magic value MUST result in the transaction being reverted. Note: the contract address is always the message sender.", + "params": { + "_data": "Additional data to be interpreted by L2", + "_from": "The address which previously owned the token", + "_operator": "The address which called `safeTransferFrom` function", + "_tokenId": "The NFT identifier which is being transferred" + }, + "returns": { + "_0": "this function selector unless throwing" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "ERC721Received(address,address,address,uint256,bytes)": { + "notice": "emitted on a call to `onERC721Received`" + }, + "ERC721Withdrawn(address,address,uint256)": { + "notice": "emitted on ERC721 withdrawal" + } + }, + "kind": "user", + "methods": { + "erc721Withdrawal(bytes)": { + "notice": "withdraw an ERC721 token from the portal" + }, + "onERC721Received(address,address,uint256,bytes)": { + "notice": "Handle the receipt of an NFT" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/EtherPortalFacet.json b/echo-js/deployments/localhost/EtherPortalFacet.json new file mode 100644 index 00000000..b3ee8ade --- /dev/null +++ b/echo-js/deployments/localhost/EtherPortalFacet.json @@ -0,0 +1,153 @@ +{ + "address": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "data", + "type": "bytes" + } + ], + "name": "EtherDeposited", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address payable", + "name": "receiver", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "EtherWithdrawn", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "etherDeposit", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + } + ], + "name": "etherWithdrawal", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x427ad7f8d928e9d19034cc848dc4c8f0f92f363607ab511903f7590c0c854657", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44", + "transactionIndex": 0, + "gasUsed": "506127", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xc08e7d786a345088cb0e24a89c9110a1abd3d939f29e2c3afc3b81b3d3c40623", + "transactionHash": "0x427ad7f8d928e9d19034cc848dc4c8f0f92f363607ab511903f7590c0c854657", + "logs": [], + "blockNumber": 24, + "cumulativeGasUsed": "506127", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"EtherDeposited\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address payable\",\"name\":\"receiver\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"EtherWithdrawn\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"etherDeposit\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"}],\"name\":\"etherWithdrawal\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"etherDeposit(bytes)\":{\"params\":{\"_data\":\"information to be interpreted by L2\"},\"returns\":{\"_0\":\"hash of input generated by deposit\"}},\"etherWithdrawal(bytes)\":{\"details\":\"can only be called by the Rollups contract\",\"params\":{\"_data\":\"data with withdrawal information\"}}},\"version\":1},\"userdoc\":{\"events\":{\"EtherDeposited(address,uint256,bytes)\":{\"notice\":\"emitted on Ether deposited\"},\"EtherWithdrawn(address,uint256)\":{\"notice\":\"emitted on Ether withdrawal\"}},\"kind\":\"user\",\"methods\":{\"etherDeposit(bytes)\":{\"notice\":\"deposit an amount of Ether in the portal and create Ether in L2\"},\"etherWithdrawal(bytes)\":{\"notice\":\"withdraw an amount of Ether from the portal\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/EtherPortalFacet.sol\":\"EtherPortalFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/EtherPortalFacet.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Ether Portal facet\\npragma solidity ^0.8.0;\\n\\nimport {IEtherPortal} from \\\"../interfaces/IEtherPortal.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\n\\ncontract EtherPortalFacet is IEtherPortal {\\n using LibInput for LibInput.DiamondStorage;\\n\\n bytes32 constant INPUT_HEADER = keccak256(\\\"Ether_Transfer\\\");\\n\\n /// @notice deposit an amount of Ether in the portal and create Ether in L2\\n /// @param _data information to be interpreted by L2\\n /// @return hash of input generated by deposit\\n function etherDeposit(bytes calldata _data)\\n public\\n payable\\n override\\n returns (bytes32)\\n {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n bytes memory input = abi.encode(\\n INPUT_HEADER,\\n msg.sender,\\n msg.value,\\n _data\\n );\\n\\n emit EtherDeposited(msg.sender, msg.value, _data);\\n return inputDS.addInternalInput(input);\\n }\\n\\n /// @notice withdraw an amount of Ether from the portal\\n /// @param _data data with withdrawal information\\n /// @dev can only be called by the Rollups contract\\n function etherWithdrawal(bytes calldata _data)\\n public\\n override\\n returns (bool)\\n {\\n // Delegate calls preserve msg.sender, msg.value and address(this)\\n require(msg.sender == address(this), \\\"only itself\\\");\\n\\n (address payable receiver, uint256 value) = abi.decode(\\n _data,\\n (address, uint256)\\n );\\n\\n // We used to call receiver.transfer(value) but it's no\\n // longer considered safe, as it assumes gas costs are\\n // immutable, while in fact they are not.\\n (bool success, ) = receiver.call{value: value}(\\\"\\\");\\n require(success, \\\"transfer failed\\\");\\n\\n emit EtherWithdrawn(receiver, value);\\n\\n return true;\\n }\\n}\\n\",\"keccak256\":\"0xff3ceab5676d1e626aed77ebcad60da7b3bdf8109badb672407ea500b48338dd\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IEtherPortal.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Ether Portal interface\\npragma solidity >=0.7.0;\\n\\ninterface IEtherPortal {\\n /// @notice deposit an amount of Ether in the portal and create Ether in L2\\n /// @param _data information to be interpreted by L2\\n /// @return hash of input generated by deposit\\n function etherDeposit(bytes calldata _data)\\n external\\n payable\\n returns (bytes32);\\n\\n /// @notice withdraw an amount of Ether from the portal\\n /// @param _data data with withdrawal information\\n /// @dev can only be called by the Rollups contract\\n function etherWithdrawal(bytes calldata _data) external returns (bool);\\n\\n /// @notice emitted on Ether deposited\\n event EtherDeposited(address sender, uint256 amount, bytes data);\\n\\n /// @notice emitted on Ether withdrawal\\n event EtherWithdrawn(address payable receiver, uint256 amount);\\n}\\n\",\"keccak256\":\"0xe4cf1f9c0036627a992efdbc1cb73a871e0c3208e07a5d1580b64af29e16f0f9\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610832806100206000396000f3fe6080604052600436106100295760003560e01c80632abfe7b31461002e57806374956b9414610054575b600080fd5b61004161003c3660046105cf565b610084565b6040519081526020015b60405180910390f35b34801561006057600080fd5b5061007461006f3660046105cf565b610146565b604051901515815260200161004b565b6000807f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff905060007ff258e0fc39d35abd7d8393dcfe7e1cf8c745ddca38ae41d451d0c55ac5f2c4ce333487876040516020016100e595949392919061066a565b60405160208183030381529060405290507fa9888e32d8ea552aaeb3018b9c85c77c66ecc61cf8d1989f9e3271a88205ee633334878760405161012b94939291906106a3565b60405180910390a161013d8282610280565b95945050505050565b600033301461018a5760405162461bcd60e51b815260206004820152600b60248201526a37b7363c9034ba39b2b63360a91b60448201526064015b60405180910390fd5b600080610199848601866106d5565b915091506000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146101ea576040519150601f19603f3d011682016040523d82523d6000602084013e6101ef565b606091505b50509050806102325760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610181565b604080516001600160a01b0385168152602081018490527f06097061aeda806b5e9cb4133d9899f332ff0913956567fc0f7ea15e3d19947c910160405180910390a150600195945050505050565b600061028d838330610294565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c91111561030e5760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d00000000000000006044820152606401610181565b61031781610439565b156103255761032585610511565b6000856003015460001461033c578560010161033e565b855b9050600061034b83610530565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e084018290526101008085018290528551808603909101815261012090940190945282519282019290922060018086018955600089815292909220909401849055865494955090939192916103f09190610723565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d6040516104249392919061073a565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff166002811115610461576104616107a6565b600184015490915063ffffffff680100000000000000008204811691166000836002811115610492576104926107a6565b1480156104a757506104a481836107bc565b42115b15610506576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f916104f3916107d4565b60405180910390a1506001949350505050565b506000949350505050565b600381015415610522576000610525565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff16600281111561059c5761059c6107a6565b905060008160028111156105b2576105b26107a6565b146105c7576105c28260016107bc565b61013d565b509392505050565b600080602083850312156105e257600080fd5b823567ffffffffffffffff808211156105fa57600080fd5b818501915085601f83011261060e57600080fd5b81358181111561061d57600080fd5b86602082850101111561062f57600080fd5b60209290920196919550909350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b85815260018060a01b0385166020820152836040820152608060608201526000610698608083018486610641565b979650505050505050565b60018060a01b03851681528360208201526060604082015260006106cb606083018486610641565b9695505050505050565b600080604083850312156106e857600080fd5b82356001600160a01b03811681146106ff57600080fd5b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107355761073561070d565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b8181101561077c57858101830151858201608001528201610760565b8181111561078e576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b600082198211156107cf576107cf61070d565b500190565b60208101600383106107f657634e487b7160e01b600052602160045260246000fd5b9190529056fea26469706673582212205f8b8b334540ae8474e8ed820a158d5c1603d75d34c78a0a7fdce1a205004e7864736f6c634300080d0033", + "deployedBytecode": "0x6080604052600436106100295760003560e01c80632abfe7b31461002e57806374956b9414610054575b600080fd5b61004161003c3660046105cf565b610084565b6040519081526020015b60405180910390f35b34801561006057600080fd5b5061007461006f3660046105cf565b610146565b604051901515815260200161004b565b6000807f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff905060007ff258e0fc39d35abd7d8393dcfe7e1cf8c745ddca38ae41d451d0c55ac5f2c4ce333487876040516020016100e595949392919061066a565b60405160208183030381529060405290507fa9888e32d8ea552aaeb3018b9c85c77c66ecc61cf8d1989f9e3271a88205ee633334878760405161012b94939291906106a3565b60405180910390a161013d8282610280565b95945050505050565b600033301461018a5760405162461bcd60e51b815260206004820152600b60248201526a37b7363c9034ba39b2b63360a91b60448201526064015b60405180910390fd5b600080610199848601866106d5565b915091506000826001600160a01b03168260405160006040518083038185875af1925050503d80600081146101ea576040519150601f19603f3d011682016040523d82523d6000602084013e6101ef565b606091505b50509050806102325760405162461bcd60e51b815260206004820152600f60248201526e1d1c985b9cd9995c8819985a5b1959608a1b6044820152606401610181565b604080516001600160a01b0385168152602081018490527f06097061aeda806b5e9cb4133d9899f332ff0913956567fc0f7ea15e3d19947c910160405180910390a150600195945050505050565b600061028d838330610294565b9392505050565b600283015482516000917fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c91111561030e5760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d00000000000000006044820152606401610181565b61031781610439565b156103255761032585610511565b6000856003015460001461033c578560010161033e565b855b9050600061034b83610530565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e084018290526101008085018290528551808603909101815261012090940190945282519282019290922060018086018955600089815292909220909401849055865494955090939192916103f09190610723565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d6040516104249392919061073a565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff166002811115610461576104616107a6565b600184015490915063ffffffff680100000000000000008204811691166000836002811115610492576104926107a6565b1480156104a757506104a481836107bc565b42115b15610506576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f916104f3916107d4565b60405180910390a1506001949350505050565b506000949350505050565b600381015415610522576000610525565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff16600281111561059c5761059c6107a6565b905060008160028111156105b2576105b26107a6565b146105c7576105c28260016107bc565b61013d565b509392505050565b600080602083850312156105e257600080fd5b823567ffffffffffffffff808211156105fa57600080fd5b818501915085601f83011261060e57600080fd5b81358181111561061d57600080fd5b86602082850101111561062f57600080fd5b60209290920196919550909350505050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b85815260018060a01b0385166020820152836040820152608060608201526000610698608083018486610641565b979650505050505050565b60018060a01b03851681528360208201526060604082015260006106cb606083018486610641565b9695505050505050565b600080604083850312156106e857600080fd5b82356001600160a01b03811681146106ff57600080fd5b946020939093013593505050565b634e487b7160e01b600052601160045260246000fd5b6000828210156107355761073561070d565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b8181101561077c57858101830151858201608001528201610760565b8181111561078e576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b600082198211156107cf576107cf61070d565b500190565b60208101600383106107f657634e487b7160e01b600052602160045260246000fd5b9190529056fea26469706673582212205f8b8b334540ae8474e8ed820a158d5c1603d75d34c78a0a7fdce1a205004e7864736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "etherDeposit(bytes)": { + "params": { + "_data": "information to be interpreted by L2" + }, + "returns": { + "_0": "hash of input generated by deposit" + } + }, + "etherWithdrawal(bytes)": { + "details": "can only be called by the Rollups contract", + "params": { + "_data": "data with withdrawal information" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "EtherDeposited(address,uint256,bytes)": { + "notice": "emitted on Ether deposited" + }, + "EtherWithdrawn(address,uint256)": { + "notice": "emitted on Ether withdrawal" + } + }, + "kind": "user", + "methods": { + "etherDeposit(bytes)": { + "notice": "deposit an amount of Ether in the portal and create Ether in L2" + }, + "etherWithdrawal(bytes)": { + "notice": "withdraw an amount of Ether from the portal" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/FeeManagerFacet.json b/echo-js/deployments/localhost/FeeManagerFacet.json new file mode 100644 index 00000000..dbaae0df --- /dev/null +++ b/echo-js/deployments/localhost/FeeManagerFacet.json @@ -0,0 +1,198 @@ +{ + "address": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "FeePerClaimReset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claims", + "type": "uint256" + } + ], + "name": "FeeRedeemed", + "type": "event" + }, + { + "inputs": [], + "name": "getFeeManagerBank", + "outputs": [ + { + "internalType": "contract IBank", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "getNumClaimsRedeemed", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "numClaimsRedeemable", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_validator", + "type": "address" + } + ], + "name": "redeemFee", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_value", + "type": "uint256" + } + ], + "name": "resetFeePerClaim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xaa9e28a7bf6c6fc245c381176ae8dfd6c0ab95e755f5977dbed23df6ed68d366", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f", + "transactionIndex": 0, + "gasUsed": "626660", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd6347f28406e977146397249e7371ed27291f716f2ec1a7ae18eb9a678ad10f1", + "transactionHash": "0xaa9e28a7bf6c6fc245c381176ae8dfd6c0ab95e755f5977dbed23df6ed68d366", + "logs": [], + "blockNumber": 25, + "cumulativeGasUsed": "626660", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"FeePerClaimReset\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claims\",\"type\":\"uint256\"}],\"name\":\"FeeRedeemed\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getFeeManagerBank\",\"outputs\":[{\"internalType\":\"contract IBank\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"getNumClaimsRedeemed\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"numClaimsRedeemable\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_validator\",\"type\":\"address\"}],\"name\":\"redeemFee\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"resetFeePerClaim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getNumClaimsRedeemed(address)\":{\"params\":{\"_validator\":\"address of the validator\"}},\"numClaimsRedeemable(address)\":{\"params\":{\"_validator\":\"address of the validator\"}},\"redeemFee(address)\":{\"params\":{\"_validator\":\"address of the validator that is redeeming\"}},\"resetFeePerClaim(uint256)\":{\"params\":{\"_value\":\"the new value of fee per claim\"}}},\"version\":1},\"userdoc\":{\"events\":{\"FeePerClaimReset(uint256)\":{\"notice\":\"emitted on resetting feePerClaim\"},\"FeeRedeemed(address,uint256)\":{\"notice\":\"emitted on ERC20 funds redeemed by validator\"}},\"kind\":\"user\",\"methods\":{\"getFeeManagerBank()\":{\"notice\":\"returns the bank used to manage fees\"},\"getNumClaimsRedeemed(address)\":{\"notice\":\"this function can be called to check the number of claims that has been redeemed for the validator\"},\"numClaimsRedeemable(address)\":{\"notice\":\"this function can be called to check the number of claims that's redeemable for the validator\"},\"redeemFee(address)\":{\"notice\":\"this function can be called to redeem fees for validators\"},\"resetFeePerClaim(uint256)\":{\"notice\":\"contract owner can reset the value of fee per claim\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/FeeManagerFacet.sol\":\"FeeManagerFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/FeeManagerFacet.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager facet\\npragma solidity >=0.8.8;\\n\\nimport {IBank} from \\\"../IBank.sol\\\";\\nimport {IFeeManager} from \\\"../interfaces/IFeeManager.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\ncontract FeeManagerFacet is IFeeManager {\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n /// @notice functions modified by noReentrancy are not subject to recursion\\n modifier noReentrancy() {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n require(!feeManagerDS.lock, \\\"reentrancy not allowed\\\");\\n feeManagerDS.lock = true;\\n _;\\n feeManagerDS.lock = false;\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(address _validator)\\n public\\n view\\n override\\n returns (uint256)\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n return feeManagerDS.numClaimsRedeemable(_validator);\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(address _validator)\\n public\\n view\\n override\\n returns (uint256)\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n return feeManagerDS.getNumClaimsRedeemed(_validator);\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(uint256 _value) public override {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n feeManagerDS.onlyOwner();\\n feeManagerDS.resetFeePerClaim(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(address _validator) public override noReentrancy {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n feeManagerDS.redeemFee(_validator);\\n }\\n\\n /// @notice returns the bank used to manage fees\\n function getFeeManagerBank() public view override returns (IBank) {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n return feeManagerDS.bank;\\n }\\n}\\n\",\"keccak256\":\"0xbc7705a8ec363654d6ade4275214a58eb02ac5374421be18f5a5826a11c3e50f\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager interface\\npragma solidity >=0.7.0;\\n\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\ninterface IFeeManager {\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(address _validator)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(address _validator)\\n external\\n view\\n returns (uint256);\\n\\n /// @notice contract owner can set/reset the value of fee per claim\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(uint256 _value) external;\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(address _validator) external;\\n\\n /// @notice returns the bank used to manage fees\\n function getFeeManagerBank() external view returns (IBank);\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0x7f55753293a46fb0d6a1fa822b27ea38157d1b6ebd3f20fa4273894a251aea4d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610a61806100206000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80636e964cea1461005c5780637a5bf67c1461009b578063a859b983146100b0578063de7a8d11146100d1578063e8f56171146100e4575b600080fd5b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc75546040516001600160a01b0390911681526020015b60405180910390f35b6100ae6100a93660046108ea565b6100f7565b005b6100c36100be366004610903565b61011d565b604051908152602001610092565b6100ae6100df366004610903565b61013f565b6100c36100f2366004610903565b610210565b600080516020610a0c83398151915261010f8161022b565b6101198183610287565b5050565b6000600080516020610a0c8339815191526101388184610418565b9392505050565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7554600080516020610a0c83398151915290600160a01b900460ff16156101c65760405162461bcd60e51b81526020600482015260166024820152751c99595b9d1c985b98de481b9bdd08185b1b1bddd95960521b60448201526064015b60405180910390fd5b60028101805460ff60a01b1916600160a01b17905560006101f2600080516020610a0c83398151915290565b90506101fe81846104ac565b50600201805460ff60a01b1916905550565b6000600080516020610a0c83398151915261013881846105fc565b80546001600160a01b031633146102845760405162461bcd60e51b815260206004820152601760248201527f63616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064016101bd565b50565b6000805160206109ec83398151915260005b81600201548110156103d85760008260010182815481106102bc576102bc61092c565b6000918252602090912001546001600160a01b0316905080156103c55760006102e586836105fc565b905080156103c35760038601546102fd9084836106b6565b600387015560018601546000906103149083610958565b600288015460405163bec3fa1760e01b81526001600160a01b0386811660048301526024820184905292935091169063bec3fa1790604401600060405180830381600087803b15801561036657600080fd5b505af115801561037a573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690527f0544e8b0e3ef3679366e27df87030668812cb3284d1acccfb1eb8a0e7b26ead3935001905060405180910390a1505b505b50806103d081610977565b915050610299565b50600183018290556040518281527fd454bae44ce74e91cf62780bdb9278052c00cfd79c13003d5761b400475b12f69060200160405180910390a1505050565b60006001600160a01b03821661046a5760405162461bcd60e51b81526020600482015260176024820152760616464726573732073686f756c64206e6f74206265203604c1b60448201526064016101bd565b6000805160206109ec83398151915260006104858285610709565b905060006104a08287600301546107e890919063ffffffff16565b93505050505b92915050565b60006104b883836105fc565b9050600081116105025760405162461bcd60e51b81526020600482015260156024820152741b9bdd1a1a5b99c81d1bc81c995919595b481e595d605a1b60448201526064016101bd565b6000805160206109ec833981519152600061051d8285610709565b60038601549091506105309082856106b6565b600386015560018501546000906105479085610958565b600287015460405163bec3fa1760e01b81526001600160a01b0388811660048301526024820184905292935091169063bec3fa1790604401600060405180830381600087803b15801561059957600080fd5b505af11580156105ad573d6000803e3d6000fd5b5050604080516001600160a01b0389168152602081018890527f0544e8b0e3ef3679366e27df87030668812cb3284d1acccfb1eb8a0e7b26ead3935001905060405180910390a1505050505050565b60006001600160a01b03821661064e5760405162461bcd60e51b81526020600482015260176024820152760616464726573732073686f756c64206e6f74206265203604c1b60448201526064016101bd565b6000805160206109ec83398151915260006106698285610709565b905060006106848284600301546107e890919063ffffffff16565b9050600061069f8388600301546107e890919063ffffffff16565b90506106ab8183610990565b979650505050505050565b6000600883106106d85760405162461bcd60e51b81526004016101bd906109a7565b60006106e485856107e8565b905060006106f284836109d3565b90506106ff868683610836565b9695505050505050565b60006001600160a01b03821661074d5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b60448201526064016101bd565b60005b60018401548110156107a9578360010181815481106107715761077161092c565b6000918252602090912001546001600160a01b03908116908416036107975790506104a6565b806107a181610977565b915050610750565b5060405162461bcd60e51b81526020600482015260136024820152721d985b1a59185d1bdc881b9bdd08199bdd5b99606a1b60448201526064016101bd565b60006008821061080a5760405162461bcd60e51b81526004016101bd906109a7565b600061081b60016340000000610990565b90508061082984601e610958565b85901c1691505092915050565b6000600883106108585760405162461bcd60e51b81526004016101bd906109a7565b61086760016340000000610990565b8211156108ac5760405162461bcd60e51b8152602060048201526013602482015272436c61696d734d61736b204f766572666c6f7760681b60448201526064016101bd565b60006108b984601e610958565b6108c860016340000000610990565b901b1990508481166108db85601e610958565b9390931b909217949350505050565b6000602082840312156108fc57600080fd5b5035919050565b60006020828403121561091557600080fd5b81356001600160a01b038116811461013857600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561097257610972610942565b500290565b60006001820161098957610989610942565b5060010190565b6000828210156109a2576109a2610942565b500390565b602080825260129082015271696e646578206f7574206f662072616e676560701b604082015260600190565b600082198211156109e6576109e6610942565b50019056fe8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fc844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc73a2646970667358221220bbef9ee9631eea87502ee3148d59871e6852c0024e2669ce3d9053cce53809ef64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80636e964cea1461005c5780637a5bf67c1461009b578063a859b983146100b0578063de7a8d11146100d1578063e8f56171146100e4575b600080fd5b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc75546040516001600160a01b0390911681526020015b60405180910390f35b6100ae6100a93660046108ea565b6100f7565b005b6100c36100be366004610903565b61011d565b604051908152602001610092565b6100ae6100df366004610903565b61013f565b6100c36100f2366004610903565b610210565b600080516020610a0c83398151915261010f8161022b565b6101198183610287565b5050565b6000600080516020610a0c8339815191526101388184610418565b9392505050565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7554600080516020610a0c83398151915290600160a01b900460ff16156101c65760405162461bcd60e51b81526020600482015260166024820152751c99595b9d1c985b98de481b9bdd08185b1b1bddd95960521b60448201526064015b60405180910390fd5b60028101805460ff60a01b1916600160a01b17905560006101f2600080516020610a0c83398151915290565b90506101fe81846104ac565b50600201805460ff60a01b1916905550565b6000600080516020610a0c83398151915261013881846105fc565b80546001600160a01b031633146102845760405162461bcd60e51b815260206004820152601760248201527f63616c6c6572206973206e6f7420746865206f776e657200000000000000000060448201526064016101bd565b50565b6000805160206109ec83398151915260005b81600201548110156103d85760008260010182815481106102bc576102bc61092c565b6000918252602090912001546001600160a01b0316905080156103c55760006102e586836105fc565b905080156103c35760038601546102fd9084836106b6565b600387015560018601546000906103149083610958565b600288015460405163bec3fa1760e01b81526001600160a01b0386811660048301526024820184905292935091169063bec3fa1790604401600060405180830381600087803b15801561036657600080fd5b505af115801561037a573d6000803e3d6000fd5b5050604080516001600160a01b0387168152602081018690527f0544e8b0e3ef3679366e27df87030668812cb3284d1acccfb1eb8a0e7b26ead3935001905060405180910390a1505b505b50806103d081610977565b915050610299565b50600183018290556040518281527fd454bae44ce74e91cf62780bdb9278052c00cfd79c13003d5761b400475b12f69060200160405180910390a1505050565b60006001600160a01b03821661046a5760405162461bcd60e51b81526020600482015260176024820152760616464726573732073686f756c64206e6f74206265203604c1b60448201526064016101bd565b6000805160206109ec83398151915260006104858285610709565b905060006104a08287600301546107e890919063ffffffff16565b93505050505b92915050565b60006104b883836105fc565b9050600081116105025760405162461bcd60e51b81526020600482015260156024820152741b9bdd1a1a5b99c81d1bc81c995919595b481e595d605a1b60448201526064016101bd565b6000805160206109ec833981519152600061051d8285610709565b60038601549091506105309082856106b6565b600386015560018501546000906105479085610958565b600287015460405163bec3fa1760e01b81526001600160a01b0388811660048301526024820184905292935091169063bec3fa1790604401600060405180830381600087803b15801561059957600080fd5b505af11580156105ad573d6000803e3d6000fd5b5050604080516001600160a01b0389168152602081018890527f0544e8b0e3ef3679366e27df87030668812cb3284d1acccfb1eb8a0e7b26ead3935001905060405180910390a1505050505050565b60006001600160a01b03821661064e5760405162461bcd60e51b81526020600482015260176024820152760616464726573732073686f756c64206e6f74206265203604c1b60448201526064016101bd565b6000805160206109ec83398151915260006106698285610709565b905060006106848284600301546107e890919063ffffffff16565b9050600061069f8388600301546107e890919063ffffffff16565b90506106ab8183610990565b979650505050505050565b6000600883106106d85760405162461bcd60e51b81526004016101bd906109a7565b60006106e485856107e8565b905060006106f284836109d3565b90506106ff868683610836565b9695505050505050565b60006001600160a01b03821661074d5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b60448201526064016101bd565b60005b60018401548110156107a9578360010181815481106107715761077161092c565b6000918252602090912001546001600160a01b03908116908416036107975790506104a6565b806107a181610977565b915050610750565b5060405162461bcd60e51b81526020600482015260136024820152721d985b1a59185d1bdc881b9bdd08199bdd5b99606a1b60448201526064016101bd565b60006008821061080a5760405162461bcd60e51b81526004016101bd906109a7565b600061081b60016340000000610990565b90508061082984601e610958565b85901c1691505092915050565b6000600883106108585760405162461bcd60e51b81526004016101bd906109a7565b61086760016340000000610990565b8211156108ac5760405162461bcd60e51b8152602060048201526013602482015272436c61696d734d61736b204f766572666c6f7760681b60448201526064016101bd565b60006108b984601e610958565b6108c860016340000000610990565b901b1990508481166108db85601e610958565b9390931b909217949350505050565b6000602082840312156108fc57600080fd5b5035919050565b60006020828403121561091557600080fd5b81356001600160a01b038116811461013857600080fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600081600019048311821515161561097257610972610942565b500290565b60006001820161098957610989610942565b5060010190565b6000828210156109a2576109a2610942565b500390565b602080825260129082015271696e646578206f7574206f662072616e676560701b604082015260600190565b600082198211156109e6576109e6610942565b50019056fe8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fc844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc73a2646970667358221220bbef9ee9631eea87502ee3148d59871e6852c0024e2669ce3d9053cce53809ef64736f6c634300080d0033", + "libraries": { + "LibClaimsMask": "0x9A676e781A523b5d0C0e43731313A708CB607508" + }, + "devdoc": { + "kind": "dev", + "methods": { + "getNumClaimsRedeemed(address)": { + "params": { + "_validator": "address of the validator" + } + }, + "numClaimsRedeemable(address)": { + "params": { + "_validator": "address of the validator" + } + }, + "redeemFee(address)": { + "params": { + "_validator": "address of the validator that is redeeming" + } + }, + "resetFeePerClaim(uint256)": { + "params": { + "_value": "the new value of fee per claim" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "FeePerClaimReset(uint256)": { + "notice": "emitted on resetting feePerClaim" + }, + "FeeRedeemed(address,uint256)": { + "notice": "emitted on ERC20 funds redeemed by validator" + } + }, + "kind": "user", + "methods": { + "getFeeManagerBank()": { + "notice": "returns the bank used to manage fees" + }, + "getNumClaimsRedeemed(address)": { + "notice": "this function can be called to check the number of claims that has been redeemed for the validator" + }, + "numClaimsRedeemable(address)": { + "notice": "this function can be called to check the number of claims that's redeemable for the validator" + }, + "redeemFee(address)": { + "notice": "this function can be called to redeem fees for validators" + }, + "resetFeePerClaim(uint256)": { + "notice": "contract owner can reset the value of fee per claim" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/InputFacet.json b/echo-js/deployments/localhost/InputFacet.json new file mode 100644 index 00000000..02446d89 --- /dev/null +++ b/echo-js/deployments/localhost/InputFacet.json @@ -0,0 +1,187 @@ +{ + "address": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "inputIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "input", + "type": "bytes" + } + ], + "name": "InputAdded", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_input", + "type": "bytes" + } + ], + "name": "addInput", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentInbox", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "getInput", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getNumberOfInputs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xaac585869d90c2be534b71ca8f187c2dd9bd6c464d90ba567dee8aae9a4d53c0", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319", + "transactionIndex": 0, + "gasUsed": "444643", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xe6382d2f82b6a44352951345dab24b34e27f7e266a1de143186a19bc078cf60c", + "transactionHash": "0xaac585869d90c2be534b71ca8f187c2dd9bd6c464d90ba567dee8aae9a4d53c0", + "logs": [], + "blockNumber": 26, + "cumulativeGasUsed": "444643", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"epochNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"inputIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"name\":\"InputAdded\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_input\",\"type\":\"bytes\"}],\"name\":\"addInput\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentInbox\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"getInput\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfInputs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"addInput(bytes)\":{\"details\":\"offchain code is responsible for making sure that input size is power of 2 and multiple of 8 since\",\"params\":{\"_input\":\"input to be understood by offchain machine\"}},\"getCurrentInbox()\":{\"returns\":{\"_0\":\"input inbox currently receiveing inputs\"}},\"getInput(uint256)\":{\"details\":\"currentInputBox being zero means that the inputs for the claimed epoch are on input box one\",\"params\":{\"_index\":\"index of input inside that inbox\"},\"returns\":{\"_0\":\"hash of input at index _index\"}},\"getNumberOfInputs()\":{\"details\":\"currentInputBox being zero means that the inputs for the claimed epoch are on input box one\",\"returns\":{\"_0\":\"number of inputs on that input box\"}}},\"version\":1},\"userdoc\":{\"events\":{\"InputAdded(uint256,uint256,address,uint256,bytes)\":{\"notice\":\"input added\"}},\"kind\":\"user\",\"methods\":{\"addInput(bytes)\":{\"notice\":\"add input to processed by next epoch\"},\"getCurrentInbox()\":{\"notice\":\"get inbox currently receiveing inputs\"},\"getInput(uint256)\":{\"notice\":\"get input inside inbox of currently proposed claim\"},\"getNumberOfInputs()\":{\"notice\":\"get number of inputs inside inbox of currently proposed claim\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/InputFacet.sol\":\"InputFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/InputFacet.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input facet\\npragma solidity ^0.8.0;\\n\\nimport {IInput} from \\\"../interfaces/IInput.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\n\\ncontract InputFacet is IInput {\\n using LibInput for LibInput.DiamondStorage;\\n\\n /// @notice add input to processed by next epoch\\n /// @param _input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n // the offchain machine has a 8 byte word\\n function addInput(bytes calldata _input) public override returns (bytes32) {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n return inputDS.addInput(_input);\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param _index index of input inside that inbox\\n /// @return hash of input at index _index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(uint256 _index) public view override returns (bytes32) {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n return inputDS.getInput(_index);\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs() public view override returns (uint256) {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n return inputDS.getNumberOfInputs();\\n }\\n\\n /// @notice get inbox currently receiveing inputs\\n /// @return input inbox currently receiveing inputs\\n function getCurrentInbox() public view override returns (uint256) {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n return inputDS.currentInputBox;\\n }\\n}\\n\",\"keccak256\":\"0xe7355e94250381c1d3f4ed399ff5db753a7909296b8b9bf7437e965bcd704793\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input interface\\npragma solidity >=0.7.0;\\n\\ninterface IInput {\\n /// @notice adds input to correct inbox\\n /// @param _input bytes array of input\\n /// @return merkle root hash of input\\n /// @dev msg.sender and timestamp are preppended log2 size\\n /// has to be calculated offchain taking that into account\\n function addInput(bytes calldata _input) external returns (bytes32);\\n\\n /// @notice returns input from correct input inbox\\n /// @param _index position of the input on inbox\\n /// @return root hash of input\\n function getInput(uint256 _index) external view returns (bytes32);\\n\\n /// @notice returns number of inputs on correct inbox\\n /// @return number of inputs of non active inbox\\n function getNumberOfInputs() external view returns (uint256);\\n\\n /// @notice returns active current inbox index\\n /// @return index of current active inbox\\n function getCurrentInbox() external view returns (uint256);\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0xecfc3bb2987598d5b5020c345cef7d570f757de69223d7cb16500c4d5fdd429d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610716806100206000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80631ab6dcab14610051578063a459600e14610086578063e795524414610099578063f32078e8146100a1575b600080fd5b7f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a688224991302545b60405190815260200160405180910390f35b610074610094366004610550565b6100b4565b6100746100e8565b6100746100af366004610569565b61011a565b60007f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff6100e1818461018a565b9392505050565b60007f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff610114816101e4565b91505090565b6000807f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff905061018284848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085939250506102059050565b949350505050565b600082600301546000146101bd578260000182815481106101ad576101ad6105db565b90600052602060002001546100e1565b8260010182815481106101d2576101d26105db565b90600052602060002001549392505050565b600081600301546000146101f95781546101ff565b60018201545b92915050565b60006100e18383336000807fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c905084600201548451111561028c5760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d0000000000000000604482015260640160405180910390fd5b610295816103b7565b156102a3576102a38561048f565b600085600301546000146102ba57856001016102bc565b855b905060006102c9836104ae565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e0840182905261010080850182905285518086039091018152610120909401909452825192820192909220600180860189556000898152929092209094018490558654949550909391929161036e9190610607565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d6040516103a29392919061061e565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff1660028111156103df576103df61068a565b600184015490915063ffffffff6801000000000000000082048116911660008360028111156104105761041061068a565b148015610425575061042281836106a0565b42115b15610484576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f91610471916106b8565b60405180910390a1506001949350505050565b506000949350505050565b6003810154156104a05760006104a3565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff16600281111561051a5761051a61068a565b905060008160028111156105305761053061068a565b14610545576105408260016106a0565b610547565b815b95945050505050565b60006020828403121561056257600080fd5b5035919050565b6000806020838503121561057c57600080fd5b823567ffffffffffffffff8082111561059457600080fd5b818501915085601f8301126105a857600080fd5b8135818111156105b757600080fd5b8660208285010111156105c957600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015610619576106196105f1565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b8181101561066057858101830151858201608001528201610644565b81811115610672576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b600082198211156106b3576106b36105f1565b500190565b60208101600383106106da57634e487b7160e01b600052602160045260246000fd5b9190529056fea26469706673582212208d2585ea14781006c7c2a1c4cd31794f4afd52d508e1dfb6b383bee26039dbca64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80631ab6dcab14610051578063a459600e14610086578063e795524414610099578063f32078e8146100a1575b600080fd5b7f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a688224991302545b60405190815260200160405180910390f35b610074610094366004610550565b6100b4565b6100746100e8565b6100746100af366004610569565b61011a565b60007f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff6100e1818461018a565b9392505050565b60007f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff610114816101e4565b91505090565b6000807f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff905061018284848080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525085939250506102059050565b949350505050565b600082600301546000146101bd578260000182815481106101ad576101ad6105db565b90600052602060002001546100e1565b8260010182815481106101d2576101d26105db565b90600052602060002001549392505050565b600081600301546000146101f95781546101ff565b60018201545b92915050565b60006100e18383336000807fd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189c905084600201548451111561028c5760405162461bcd60e51b815260206004820152601860248201527f696e707574206c656e3a205b302c647269766553697a655d0000000000000000604482015260640160405180910390fd5b610295816103b7565b156102a3576102a38561048f565b600085600301546000146102ba57856001016102bc565b855b905060006102c9836104ae565b8254604080516001600160a01b03891660208083019190915243828401524260608301526080820185905260a08083018590528351808403909101815260c0830184528051908201208b518c83012060e0840182905261010080850182905285518086039091018152610120909401909452825192820192909220600180860189556000898152929092209094018490558654949550909391929161036e9190610607565b847fa15a0da5519c084484141aaa73e525cee96062f5decc97e070f0c4da27738bc78a428d6040516103a29392919061061e565b60405180910390a39998505050505050505050565b60018101546000908190600160801b900463ffffffff1660028111156103df576103df61068a565b600184015490915063ffffffff6801000000000000000082048116911660008360028111156104105761041061068a565b148015610425575061042281836106a0565b42115b15610484576001858101805463ffffffff60801b1916600160801b1790556040517fed606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f91610471916106b8565b60405180910390a1506001949350505050565b506000949350505050565b6003810154156104a05760006104a3565b60015b60ff16600390910155565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff16600281111561051a5761051a61068a565b905060008160028111156105305761053061068a565b14610545576105408260016106a0565b610547565b815b95945050505050565b60006020828403121561056257600080fd5b5035919050565b6000806020838503121561057c57600080fd5b823567ffffffffffffffff8082111561059457600080fd5b818501915085601f8301126105a857600080fd5b8135818111156105b757600080fd5b8660208285010111156105c957600080fd5b60209290920196919550909350505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b600082821015610619576106196105f1565b500390565b60018060a01b038416815260006020848184015260606040840152835180606085015260005b8181101561066057858101830151858201608001528201610644565b81811115610672576000608083870101525b50601f01601f19169290920160800195945050505050565b634e487b7160e01b600052602160045260246000fd5b600082198211156106b3576106b36105f1565b500190565b60208101600383106106da57634e487b7160e01b600052602160045260246000fd5b9190529056fea26469706673582212208d2585ea14781006c7c2a1c4cd31794f4afd52d508e1dfb6b383bee26039dbca64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "addInput(bytes)": { + "details": "offchain code is responsible for making sure that input size is power of 2 and multiple of 8 since", + "params": { + "_input": "input to be understood by offchain machine" + } + }, + "getCurrentInbox()": { + "returns": { + "_0": "input inbox currently receiveing inputs" + } + }, + "getInput(uint256)": { + "details": "currentInputBox being zero means that the inputs for the claimed epoch are on input box one", + "params": { + "_index": "index of input inside that inbox" + }, + "returns": { + "_0": "hash of input at index _index" + } + }, + "getNumberOfInputs()": { + "details": "currentInputBox being zero means that the inputs for the claimed epoch are on input box one", + "returns": { + "_0": "number of inputs on that input box" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "InputAdded(uint256,uint256,address,uint256,bytes)": { + "notice": "input added" + } + }, + "kind": "user", + "methods": { + "addInput(bytes)": { + "notice": "add input to processed by next epoch" + }, + "getCurrentInbox()": { + "notice": "get inbox currently receiveing inputs" + }, + "getInput(uint256)": { + "notice": "get input inside inbox of currently proposed claim" + }, + "getNumberOfInputs()": { + "notice": "get number of inputs inside inbox of currently proposed claim" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibClaimsMask.json b/echo-js/deployments/localhost/LibClaimsMask.json new file mode 100644 index 00000000..40ebee78 --- /dev/null +++ b/echo-js/deployments/localhost/LibClaimsMask.json @@ -0,0 +1,40 @@ +{ + "address": "0x9A676e781A523b5d0C0e43731313A708CB607508", + "abi": [], + "transactionHash": "0x3fd601465ca5a7b7608ae66dd90e54f166d9e7e55dd73611661aa3157fe46dcc", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x9A676e781A523b5d0C0e43731313A708CB607508", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x8a12b1c673fdd7b953a49eb4be83652e7ded715d8b83fd0062e90ecce4e8a221", + "transactionHash": "0x3fd601465ca5a7b7608ae66dd90e54f166d9e7e55dd73611661aa3157fe46dcc", + "logs": [], + "blockNumber": 15, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibClaimsMask.sol\":\"LibClaimsMask\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220f207a18bf0f032f65f6fc0ed17c44444682051896bbf2631ca031feb8e936f1c64736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220f207a18bf0f032f65f6fc0ed17c44444682051896bbf2631ca031feb8e936f1c64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibDiamond.json b/echo-js/deployments/localhost/LibDiamond.json new file mode 100644 index 00000000..6fa10de5 --- /dev/null +++ b/echo-js/deployments/localhost/LibDiamond.json @@ -0,0 +1,102 @@ +{ + "address": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "components": [ + { + "internalType": "address", + "name": "facetAddress", + "type": "address" + }, + { + "internalType": "enum IDiamondCut.FacetCutAction", + "name": "action", + "type": "uint8" + }, + { + "internalType": "bytes4[]", + "name": "functionSelectors", + "type": "bytes4[]" + } + ], + "indexed": false, + "internalType": "struct IDiamondCut.FacetCut[]", + "name": "diamondCut", + "type": "tuple[]" + }, + { + "indexed": false, + "internalType": "address", + "name": "init", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "callData", + "type": "bytes" + } + ], + "name": "DiamondCut", + "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" + } + ], + "transactionHash": "0xedc13f0c1ce94653974570525a95f6949e55b0e0a065fe497930079b83dd02a7", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xba253c12cd7b9f0e977df7c65e37f871eef9a1d7ebffa611743ed03bede7819e", + "transactionHash": "0xedc13f0c1ce94653974570525a95f6949e55b0e0a065fe497930079b83dd02a7", + "logs": [], + "blockNumber": 11, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"facetAddress\",\"type\":\"address\"},{\"internalType\":\"enum IDiamondCut.FacetCutAction\",\"name\":\"action\",\"type\":\"uint8\"},{\"internalType\":\"bytes4[]\",\"name\":\"functionSelectors\",\"type\":\"bytes4[]\"}],\"indexed\":false,\"internalType\":\"struct IDiamondCut.FacetCut[]\",\"name\":\"diamondCut\",\"type\":\"tuple[]\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"init\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"callData\",\"type\":\"bytes\"}],\"name\":\"DiamondCut\",\"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\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibDiamond.sol\":\"LibDiamond\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\\n}\\n\",\"keccak256\":\"0x6a3129be1f39b6fec871f2c94bf7debf2d6a4e665547a4d83e7f2def38359e44\",\"license\":\"MIT\"},\"contracts/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // maps function selectors to the facets that execute the functions.\\n // and maps the selectors to their position in the selectorSlots array.\\n // func selector => address facet, selector position\\n mapping(bytes4 => bytes32) facets;\\n // array of slots of function selectors.\\n // each slot holds 8 function selectors.\\n mapping(uint256 => bytes32) selectorSlots;\\n // The number of function selectors in selectorSlots\\n uint16 selectorCount;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(\\n msg.sender == diamondStorage().contractOwner,\\n \\\"LibDiamond: Must be contract owner\\\"\\n );\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] diamondCut,\\n address init,\\n bytes callData\\n );\\n\\n bytes32 constant CLEAR_ADDRESS_MASK =\\n bytes32(uint256(0xffffffffffffffffffffffff));\\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\\n\\n // Internal function version of diamondCut\\n // This code is almost the same as the external diamondCut,\\n // except it is using 'Facet[] memory _diamondCut' instead of\\n // 'Facet[] calldata _diamondCut'.\\n // The code is duplicated to prevent copying calldata to memory which\\n // causes an error for a two dimensional array.\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n DiamondStorage storage ds = diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addReplaceRemoveFacetSelectors(\\n uint256 _selectorCount,\\n bytes32 _selectorSlot,\\n address _newFacetAddress,\\n IDiamondCut.FacetCutAction _action,\\n bytes4[] memory _selectors\\n ) internal returns (uint256, bytes32) {\\n DiamondStorage storage ds = diamondStorage();\\n require(\\n _selectors.length > 0,\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\n );\\n if (_action == IDiamondCut.FacetCutAction.Add) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Add facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) == address(0),\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\n );\\n // add facet for selector\\n ds.facets[selector] =\\n bytes20(_newFacetAddress) |\\n bytes32(_selectorCount);\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\\n // clear selector position in slot and add selector\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\\n (bytes32(selector) >> selectorInSlotPosition);\\n // if slot is full then write it to storage\\n if (selectorInSlotPosition == 224) {\\n // \\\"_selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"_selectorSlot / 8\\\"\\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\\n _selectorSlot = 0;\\n }\\n _selectorCount++;\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Replace facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n address oldFacetAddress = address(bytes20(oldFacet));\\n // only useful if immutable functions exist\\n require(\\n oldFacetAddress != address(this),\\n \\\"LibDiamondCut: Can't replace immutable function\\\"\\n );\\n require(\\n oldFacetAddress != _newFacetAddress,\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\n );\\n require(\\n oldFacetAddress != address(0),\\n \\\"LibDiamondCut: Can't replace function that doesn't exist\\\"\\n );\\n // replace old facet address\\n ds.facets[selector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(_newFacetAddress);\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\\n require(\\n _newFacetAddress == address(0),\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\n );\\n // \\\"_selectorCount >> 3\\\" is a gas efficient division by 8 \\\"_selectorCount / 8\\\"\\n uint256 selectorSlotCount = _selectorCount >> 3;\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotIndex = _selectorCount & 7;\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n if (_selectorSlot == 0) {\\n // get last selectorSlot\\n selectorSlotCount--;\\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\\n selectorInSlotIndex = 7;\\n } else {\\n selectorInSlotIndex--;\\n }\\n bytes4 lastSelector;\\n uint256 oldSelectorsSlotCount;\\n uint256 oldSelectorInSlotPosition;\\n // adding a block here prevents stack too deep error\\n {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) != address(0),\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\n );\\n // only useful if immutable functions exist\\n require(\\n address(bytes20(oldFacet)) != address(this),\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\n );\\n // replace selector with last selector in ds.facets\\n // gets the last selector\\n lastSelector = bytes4(\\n _selectorSlot << (selectorInSlotIndex << 5)\\n );\\n if (lastSelector != selector) {\\n // update last selector slot position info\\n ds.facets[lastSelector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(ds.facets[lastSelector]);\\n }\\n delete ds.facets[selector];\\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\\n // \\\"oldSelectorCount >> 3\\\" is a gas efficient division by 8 \\\"oldSelectorCount / 8\\\"\\n oldSelectorsSlotCount = oldSelectorCount >> 3;\\n // \\\"oldSelectorCount & 7\\\" is a gas efficient modulo by eight \\\"oldSelectorCount % 8\\\"\\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\\n }\\n if (oldSelectorsSlotCount != selectorSlotCount) {\\n bytes32 oldSelectorSlot = ds.selectorSlots[\\n oldSelectorsSlotCount\\n ];\\n // clears the selector we are deleting and puts the last selector in its place.\\n oldSelectorSlot =\\n (oldSelectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n // update storage with the modified slot\\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\\n } else {\\n // clears the selector we are deleting and puts the last selector in its place.\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n }\\n if (selectorInSlotIndex == 0) {\\n delete ds.selectorSlots[selectorSlotCount];\\n _selectorSlot = 0;\\n }\\n }\\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n return (_selectorCount, _selectorSlot);\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\n internal\\n {\\n if (_init == address(0)) {\\n require(\\n _calldata.length == 0,\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\n );\\n } else {\\n require(\\n _calldata.length > 0,\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\n );\\n if (_init != address(this)) {\\n enforceHasContractCode(\\n _init,\\n \\\"LibDiamondCut: _init address has no code\\\"\\n );\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(\\n address _contract,\\n string memory _errorMessage\\n ) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x740ea3845282f09bb822e66a189ed431ac799ab08184de7457ef53799b2e99d6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c5a84bf61634d1ec545a6f8b1feb7ca9ae19b6c1de1b62724654313e991082a264736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220c5a84bf61634d1ec545a6f8b1feb7ca9ae19b6c1de1b62724654313e991082a264736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibDisputeManager.json b/echo-js/deployments/localhost/LibDisputeManager.json new file mode 100644 index 00000000..9a9ceafa --- /dev/null +++ b/echo-js/deployments/localhost/LibDisputeManager.json @@ -0,0 +1,40 @@ +{ + "address": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed", + "abi": [], + "transactionHash": "0x30f53ee6f9124a2b30e32f3555a7836a13689728ac14d0926b82c9a3c5c751ac", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x68B1D87F95878fE05B998F19b66F4baba5De1aed", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x122ce6f3bd087572c4d9774136f86fac15d5bc067720eed872731b9022fa9e5a", + "transactionHash": "0x30f53ee6f9124a2b30e32f3555a7836a13689728ac14d0926b82c9a3c5c751ac", + "logs": [], + "blockNumber": 19, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibDisputeManager.sol\":\"LibDisputeManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204141febf12e97e090ace242057c841d7f58ca4cd6a3d58622ac11f58772c29d664736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212204141febf12e97e090ace242057c841d7f58ca4cd6a3d58622ac11f58772c29d664736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibFeeManager.json b/echo-js/deployments/localhost/LibFeeManager.json new file mode 100644 index 00000000..74f299b8 --- /dev/null +++ b/echo-js/deployments/localhost/LibFeeManager.json @@ -0,0 +1,81 @@ +{ + "address": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "FeePerClaimReset", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "validator", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "claims", + "type": "uint256" + } + ], + "name": "FeeRedeemed", + "type": "event" + } + ], + "transactionHash": "0x16ea571f922ff165f1c46d49d37ba29b9196b4de23254d09082bb352f82f0179", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x30ec8aff9b1b46e44b66c4e3f5d8aaf17e15d818ba849e307321903a8ef04f46", + "transactionHash": "0x16ea571f922ff165f1c46d49d37ba29b9196b4de23254d09082bb352f82f0179", + "logs": [], + "blockNumber": 20, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"FeePerClaimReset\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"validator\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"claims\",\"type\":\"uint256\"}],\"name\":\"FeeRedeemed\",\"type\":\"event\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"FeePerClaimReset(uint256)\":{\"notice\":\"emitted on resetting feePerClaim\"},\"FeeRedeemed(address,uint256)\":{\"notice\":\"emitted on ERC20 funds redeemed by validator\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibFeeManager.sol\":\"LibFeeManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122038dc250b0eee390254c1a470f46a497aebc692590f944731c1e94ef49b70814964736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122038dc250b0eee390254c1a470f46a497aebc692590f944731c1e94ef49b70814964736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "events": { + "FeePerClaimReset(uint256)": { + "notice": "emitted on resetting feePerClaim" + }, + "FeeRedeemed(address,uint256)": { + "notice": "emitted on ERC20 funds redeemed by validator" + } + }, + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibInput.json b/echo-js/deployments/localhost/LibInput.json new file mode 100644 index 00000000..600ae99a --- /dev/null +++ b/echo-js/deployments/localhost/LibInput.json @@ -0,0 +1,94 @@ +{ + "address": "0x0B306BF915C4d645ff596e518fAf3F9669b97016", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "inputIndex", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "input", + "type": "bytes" + } + ], + "name": "InputAdded", + "type": "event" + } + ], + "transactionHash": "0x8d7a0179a1a89c343cf01b74b4613b8c83fd6225436cf8ee04edec29ea420bf3", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x0B306BF915C4d645ff596e518fAf3F9669b97016", + "transactionIndex": 0, + "gasUsed": "72205", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x19b571eec547f7924d4f624ddc1a38010c914a6c368c57ec070418396d498a79", + "transactionHash": "0x8d7a0179a1a89c343cf01b74b4613b8c83fd6225436cf8ee04edec29ea420bf3", + "logs": [], + "blockNumber": 16, + "cumulativeGasUsed": "72205", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"epochNumber\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"inputIndex\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"timestamp\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"input\",\"type\":\"bytes\"}],\"name\":\"InputAdded\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"InputAdded(uint256,uint256,address,uint256,bytes)\":{\"params\":{\"epochNumber\":\"which epoch this input belongs to\",\"input\":\"input data\",\"inputIndex\":\"index of the input just added\",\"sender\":\"msg.sender\",\"timestamp\":\"block.timestamp\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"InputAdded(uint256,uint256,address,uint256,bytes)\":{\"notice\":\"input added\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibInput.sol\":\"LibInput\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122045af0a00851f115a4bb6fc3594433c2460d8f7c3ab9dc1838829ed264d67d1a064736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122045af0a00851f115a4bb6fc3594433c2460d8f7c3ab9dc1838829ed264d67d1a064736f6c634300080d0033", + "devdoc": { + "events": { + "InputAdded(uint256,uint256,address,uint256,bytes)": { + "params": { + "epochNumber": "which epoch this input belongs to", + "input": "input data", + "inputIndex": "index of the input just added", + "sender": "msg.sender", + "timestamp": "block.timestamp" + } + } + }, + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "events": { + "InputAdded(uint256,uint256,address,uint256,bytes)": { + "notice": "input added" + } + }, + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibOutput.json b/echo-js/deployments/localhost/LibOutput.json new file mode 100644 index 00000000..dd9f5181 --- /dev/null +++ b/echo-js/deployments/localhost/LibOutput.json @@ -0,0 +1,40 @@ +{ + "address": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1", + "abi": [], + "transactionHash": "0xa94802e992eb4780569bf38b9dde82c02bf6f4b88e64c4eb4991d2411f0e3bc6", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9b5958f1a848c6c85e9ef17545687fbe72e1bce4534c85a8711cd83c04e7d0e0", + "transactionHash": "0xa94802e992eb4780569bf38b9dde82c02bf6f4b88e64c4eb4991d2411f0e3bc6", + "logs": [], + "blockNumber": 17, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibOutput.sol\":\"LibOutput\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b9feb0adc702e3687bbb49b753bbb4f4a9adbe0e872b8403f87aa9130e9c38e764736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea2646970667358221220b9feb0adc702e3687bbb49b753bbb4f4a9adbe0e872b8403f87aa9130e9c38e764736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibRollups.json b/echo-js/deployments/localhost/LibRollups.json new file mode 100644 index 00000000..73de0c8f --- /dev/null +++ b/echo-js/deployments/localhost/LibRollups.json @@ -0,0 +1,129 @@ +{ + "address": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "epochHash", + "type": "bytes32" + } + ], + "name": "FinalizeEpoch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Phase", + "name": "newPhase", + "type": "uint8" + } + ], + "name": "PhaseChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "winner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "loser", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "winningClaim", + "type": "bytes32" + } + ], + "name": "ResolveDispute", + "type": "event" + } + ], + "transactionHash": "0x2866a1def92cee6438340f6409b0550dc0197ea8906397bc7d36ac1065bba3f7", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x3f0f5cac6bca9a7a848613ff02b840c81ac7e864716c31fcacec70f274b85818", + "transactionHash": "0x2866a1def92cee6438340f6409b0550dc0197ea8906397bc7d36ac1065bba3f7", + "logs": [], + "blockNumber": 21, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"epochNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"epochHash\",\"type\":\"bytes32\"}],\"name\":\"FinalizeEpoch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enum Phase\",\"name\":\"newPhase\",\"type\":\"uint8\"}],\"name\":\"PhaseChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"loser\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"winningClaim\",\"type\":\"bytes32\"}],\"name\":\"ResolveDispute\",\"type\":\"event\"}],\"devdoc\":{\"events\":{\"FinalizeEpoch(uint256,bytes32)\":{\"params\":{\"epochHash\":\"claim being submitted by this epoch\",\"epochNumber\":\"number of the epoch being finalized\"}},\"PhaseChange(uint8)\":{\"params\":{\"newPhase\":\"new phase\"}},\"ResolveDispute(address,address,bytes32)\":{\"params\":{\"loser\":\"loser of dispute\",\"winner\":\"winner of dispute\",\"winningClaim\":\"initial claim of winning validator\"}}},\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"FinalizeEpoch(uint256,bytes32)\":{\"notice\":\"epoch finalized\"},\"PhaseChange(uint8)\":{\"notice\":\"phase change\"},\"ResolveDispute(address,address,bytes32)\":{\"notice\":\"dispute resolved\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibRollups.sol\":\"LibRollups\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205a485fcaa0fe53c20da938a3897cb43d793987fb9c8138b345986de57832228164736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea26469706673582212205a485fcaa0fe53c20da938a3897cb43d793987fb9c8138b345986de57832228164736f6c634300080d0033", + "devdoc": { + "events": { + "FinalizeEpoch(uint256,bytes32)": { + "params": { + "epochHash": "claim being submitted by this epoch", + "epochNumber": "number of the epoch being finalized" + } + }, + "PhaseChange(uint8)": { + "params": { + "newPhase": "new phase" + } + }, + "ResolveDispute(address,address,bytes32)": { + "params": { + "loser": "loser of dispute", + "winner": "winner of dispute", + "winningClaim": "initial claim of winning validator" + } + } + }, + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "events": { + "FinalizeEpoch(uint256,bytes32)": { + "notice": "epoch finalized" + }, + "PhaseChange(uint8)": { + "notice": "phase change" + }, + "ResolveDispute(address,address,bytes32)": { + "notice": "dispute resolved" + } + }, + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/LibValidatorManager.json b/echo-js/deployments/localhost/LibValidatorManager.json new file mode 100644 index 00000000..a425b159 --- /dev/null +++ b/echo-js/deployments/localhost/LibValidatorManager.json @@ -0,0 +1,118 @@ +{ + "address": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Result", + "name": "result", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32[2]", + "name": "claims", + "type": "bytes32[2]" + }, + { + "indexed": false, + "internalType": "address payable[2]", + "name": "validators", + "type": "address[2]" + } + ], + "name": "ClaimReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Result", + "name": "result", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32[2]", + "name": "claims", + "type": "bytes32[2]" + }, + { + "indexed": false, + "internalType": "address payable[2]", + "name": "validators", + "type": "address[2]" + } + ], + "name": "DisputeEnded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "claim", + "type": "bytes32" + } + ], + "name": "NewEpoch", + "type": "event" + } + ], + "transactionHash": "0x9a65d7dbf5d2d338b74b449d91e1c88f591655c2b1e13a15ddc4cd5858dfcb5e", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x9A9f2CCfdE556A7E9Ff0848998Aa4a0CFD8863AE", + "transactionIndex": 0, + "gasUsed": "72217", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xab8e4bd56bb5867ae8be06b3d8c023f8b8743393e945bc9cb9537a09b3d7eb7b", + "transactionHash": "0x9a65d7dbf5d2d338b74b449d91e1c88f591655c2b1e13a15ddc4cd5858dfcb5e", + "logs": [], + "blockNumber": 18, + "cumulativeGasUsed": "72217", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enum Result\",\"name\":\"result\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32[2]\",\"name\":\"claims\",\"type\":\"bytes32[2]\"},{\"indexed\":false,\"internalType\":\"address payable[2]\",\"name\":\"validators\",\"type\":\"address[2]\"}],\"name\":\"ClaimReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enum Result\",\"name\":\"result\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32[2]\",\"name\":\"claims\",\"type\":\"bytes32[2]\"},{\"indexed\":false,\"internalType\":\"address payable[2]\",\"name\":\"validators\",\"type\":\"address[2]\"}],\"name\":\"DisputeEnded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"claim\",\"type\":\"bytes32\"}],\"name\":\"NewEpoch\",\"type\":\"event\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{},\"version\":1},\"userdoc\":{\"events\":{\"ClaimReceived(uint8,bytes32[2],address[2])\":{\"notice\":\"emitted on Claim received\"},\"DisputeEnded(uint8,bytes32[2],address[2])\":{\"notice\":\"emitted on Dispute end\"},\"NewEpoch(bytes32)\":{\"notice\":\"emitted on new Epoch\"}},\"kind\":\"user\",\"methods\":{},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/libraries/LibValidatorManager.sol\":\"LibValidatorManager\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x60566037600b82828239805160001a607314602a57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122080f3bd59d03023cff2312fd721be2a546ac4e0495a947d7ae9acb2f25034dc9764736f6c634300080d0033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600080fdfea264697066735822122080f3bd59d03023cff2312fd721be2a546ac4e0495a947d7ae9acb2f25034dc9764736f6c634300080d0033", + "libraries": { + "LibClaimsMask": "0x9A676e781A523b5d0C0e43731313A708CB607508" + }, + "devdoc": { + "kind": "dev", + "methods": {}, + "version": 1 + }, + "userdoc": { + "events": { + "ClaimReceived(uint8,bytes32[2],address[2])": { + "notice": "emitted on Claim received" + }, + "DisputeEnded(uint8,bytes32[2],address[2])": { + "notice": "emitted on Dispute end" + }, + "NewEpoch(bytes32)": { + "notice": "emitted on new Epoch" + } + }, + "kind": "user", + "methods": {}, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/Merkle.json b/echo-js/deployments/localhost/Merkle.json new file mode 100644 index 00000000..591c524d --- /dev/null +++ b/echo-js/deployments/localhost/Merkle.json @@ -0,0 +1,222 @@ +{ + "address": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", + "abi": [ + { + "inputs": [ + { + "internalType": "bytes32[]", + "name": "hashes", + "type": "bytes32[]" + } + ], + "name": "calculateRootFromPowerOfTwo", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "getEmptyTreeHashAtIndex", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_wordIndex", + "type": "uint256" + } + ], + "name": "getHashOfWordAtIndex", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_data", + "type": "bytes" + }, + { + "internalType": "uint256", + "name": "_log2Size", + "type": "uint256" + } + ], + "name": "getMerkleRootFromBytes", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_position", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_logSizeOfReplacement", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_logSizeOfFullDrive", + "type": "uint256" + }, + { + "internalType": "bytes32", + "name": "_replacement", + "type": "bytes32" + }, + { + "internalType": "bytes32[]", + "name": "siblings", + "type": "bytes32[]" + } + ], + "name": "getRootAfterReplacementInDrive", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0xe4cbd6e1b8cbef8003127d5f041b21c21a84068f49c260190b1fc21964eb35cd", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9", + "transactionIndex": 0, + "gasUsed": "1317703", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x858f9877a596e31258b46b9e21015991edca5f8dcd71a2eab59a569db6543798", + "transactionHash": "0xe4cbd6e1b8cbef8003127d5f041b21c21a84068f49c260190b1fc21964eb35cd", + "logs": [], + "blockNumber": 4, + "cumulativeGasUsed": "1317703", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bytes32[]\",\"name\":\"hashes\",\"type\":\"bytes32[]\"}],\"name\":\"calculateRootFromPowerOfTwo\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"getEmptyTreeHashAtIndex\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_wordIndex\",\"type\":\"uint256\"}],\"name\":\"getHashOfWordAtIndex\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_data\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_log2Size\",\"type\":\"uint256\"}],\"name\":\"getMerkleRootFromBytes\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_position\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_logSizeOfReplacement\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_logSizeOfFullDrive\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"_replacement\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32[]\",\"name\":\"siblings\",\"type\":\"bytes32[]\"}],\"name\":\"getRootAfterReplacementInDrive\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"calculateRootFromPowerOfTwo(bytes32[])\":{\"params\":{\"hashes\":\"The array containing power of 2 elements\"},\"returns\":{\"_0\":\"byte32 the root hash being calculated\"}},\"getEmptyTreeHashAtIndex(uint256)\":{\"details\":\"first index is keccak(0), second index is keccak(keccak(0), keccak(0))\",\"params\":{\"_index\":\"of hash wanted\"}},\"getHashOfWordAtIndex(bytes,uint256)\":{\"details\":\"if word is incomplete (< 8 bytes) it gets padded with zeroes\",\"params\":{\"_data\":\"array of bytes\",\"_wordIndex\":\"index of word inside the bytes to get the hash of\"}},\"getMerkleRootFromBytes(bytes,uint256)\":{\"details\":\"_data is padded with zeroes until is multiple of 8root is completed with zero tree until log2size is completehashes are taken word by word (8 bytes by 8 bytes)\",\"params\":{\"_data\":\"array of bytes to be merklelized\",\"_log2Size\":\"log2 of total size of the drive\"}},\"getRootAfterReplacementInDrive(uint256,uint256,uint256,bytes32,bytes32[])\":{\"params\":{\"_logSizeOfFullDrive\":\"log2 of size the full drive, which can be the entire machine\",\"_logSizeOfReplacement\":\"log2 of size the replacement\",\"_position\":\"position of _drive\",\"_replacement\":\"hash of the replacement\",\"siblings\":\"of replacement that merkle root can be calculated\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"calculateRootFromPowerOfTwo(bytes32[])\":{\"notice\":\"Calculate the root of Merkle tree from an array of power of 2 elements\"},\"getEmptyTreeHashAtIndex(uint256)\":{\"notice\":\"Gets precomputed hash of zero in empty tree hashes\"},\"getHashOfWordAtIndex(bytes,uint256)\":{\"notice\":\"Get the hash of a word in an array of bytes\"},\"getMerkleRootFromBytes(bytes,uint256)\":{\"notice\":\"get merkle root of generic array of bytes\"},\"getRootAfterReplacementInDrive(uint256,uint256,uint256,bytes32,bytes32[])\":{\"notice\":\"Gets merkle root hash of drive with a replacement\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Merkle.sol\":\"Merkle\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/CartesiMath.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title CartesiMath\\n/// @author Felipe Argento\\npragma solidity ^0.8.0;\\n\\nlibrary CartesiMath {\\n // mapping values are packed as bytes3 each\\n // see test/TestCartesiMath.ts for decimal values\\n bytes constant log2tableTimes1M =\\n hex\\\"0000000F4240182F421E8480236E082771822AD63A2DC6C0305E8532B04834C96736B3C23876D73A187A3B9D4A3D09003E5EA63FA0C540D17741F28843057D440BA745062945F60246DC1047B917488DC7495ABA4A207C4ADF8A4B98544C4B404CF8AA4DA0E64E44434EE3054F7D6D5013B750A61A5134C851BFF05247BD52CC58534DE753CC8D54486954C19C55384255AC75561E50568DE956FB575766B057D00758376F589CFA5900BA5962BC59C3135A21CA5A7EF15ADA945B34BF5B8D805BE4DF5C3AEA5C8FA95CE3265D356C5D86835DD6735E25455E73005EBFAD5F0B525F55F75F9FA25FE85A60302460770860BD0A61023061467F6189FD61CCAE620E98624FBF62902762CFD5630ECD634D12638AA963C7966403DC643F7F647A8264B4E864EEB56527EC6560906598A365D029660724663D9766738566A8F066DDDA6712476746386779AF67ACAF67DF3A6811526842FA68743268A4FC68D55C6905536934E169640A6992CF69C13169EF326A1CD46A4A186A76FF6AA38C6ACFC0\\\";\\n\\n /// @notice Approximates log2 * 1M\\n /// @param _num number to take log2 * 1M of\\n /// @return approximate log2 times 1M\\n function log2ApproxTimes1M(uint256 _num) public pure returns (uint256) {\\n require(_num > 0, \\\"Number cannot be zero\\\");\\n uint256 leading = 0;\\n\\n if (_num == 1) return 0;\\n\\n while (_num > 128) {\\n _num = _num >> 1;\\n leading += 1;\\n }\\n return (leading * uint256(1000000)) + (getLog2TableTimes1M(_num));\\n }\\n\\n /// @notice navigates log2tableTimes1M\\n /// @param _num number to take log2 of\\n /// @return result after table look-up\\n function getLog2TableTimes1M(uint256 _num) public pure returns (uint256) {\\n bytes3 result = 0;\\n for (uint8 i = 0; i < 3; i++) {\\n bytes3 tempResult = log2tableTimes1M[(_num - 1) * 3 + i];\\n result = result | (tempResult >> (i * 8));\\n }\\n\\n return uint256(uint24(result));\\n }\\n\\n /// @notice get floor of log2 of number\\n /// @param _num number to take floor(log2) of\\n /// @return floor(log2) of _num\\n function getLog2Floor(uint256 _num) public pure returns (uint8) {\\n require(_num != 0, \\\"log of zero is undefined\\\");\\n\\n return uint8(255 - clz(_num));\\n }\\n\\n /// @notice checks if a number is Power of 2\\n /// @param _num number to check\\n /// @return true if number is power of 2, false if not\\n function isPowerOf2(uint256 _num) public pure returns (bool) {\\n if (_num == 0) return false;\\n\\n return _num & (_num - 1) == 0;\\n }\\n\\n /// @notice count trailing zeros\\n /// @param _num number you want the ctz of\\n /// @dev this a binary search implementation\\n function ctz(uint256 _num) public pure returns (uint256) {\\n if (_num == 0) return 256;\\n\\n uint256 n = 0;\\n if (_num & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { n = n + 128; _num = _num >> 128; }\\n if (_num & 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF == 0) { n = n + 64; _num = _num >> 64; }\\n if (_num & 0x00000000000000000000000000000000000000000000000000000000FFFFFFFF == 0) { n = n + 32; _num = _num >> 32; }\\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000FFFF == 0) { n = n + 16; _num = _num >> 16; }\\n if (_num & 0x00000000000000000000000000000000000000000000000000000000000000FF == 0) { n = n + 8; _num = _num >> 8; }\\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000000F == 0) { n = n + 4; _num = _num >> 4; }\\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000003 == 0) { n = n + 2; _num = _num >> 2; }\\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000001 == 0) { n = n + 1; }\\n\\n return n;\\n }\\n\\n /// @notice count leading zeros\\n /// @param _num number you want the clz of\\n /// @dev this a binary search implementation\\n function clz(uint256 _num) public pure returns (uint256) {\\n if (_num == 0) return 256;\\n\\n uint256 n = 0;\\n if (_num & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 == 0) { n = n + 128; _num = _num << 128; }\\n if (_num & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 == 0) { n = n + 64; _num = _num << 64; }\\n if (_num & 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 == 0) { n = n + 32; _num = _num << 32; }\\n if (_num & 0xFFFF000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 16; _num = _num << 16; }\\n if (_num & 0xFF00000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 8; _num = _num << 8; }\\n if (_num & 0xF000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 4; _num = _num << 4; }\\n if (_num & 0xC000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 2; _num = _num << 2; }\\n if (_num & 0x8000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 1; }\\n\\n return n;\\n }\\n}\\n\",\"keccak256\":\"0x28b74012e966438edff701decdc5ffd207b3f0244af65fbd7d397050986e58d4\",\"license\":\"Apache-2.0\"},\"contracts/Merkle.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Library for Merkle proofs\\npragma solidity ^0.8.0;\\n\\nimport \\\"./CartesiMath.sol\\\";\\n\\nlibrary Merkle {\\n using CartesiMath for uint256;\\n\\n uint128 constant L_WORD_SIZE = 3; // word = 8 bytes, log = 3\\n // number of hashes in EMPTY_TREE_HASHES\\n uint128 constant EMPTY_TREE_SIZE = 1952; // 61*32=1952. 32 bytes per 61 indexes (64 words)\\n\\n // merkle root hashes of trees of zero concatenated\\n // 32 bytes for each root, first one is keccak(0), second one is\\n // keccak(keccack(0), keccak(0)) and so on\\n\\n bytes constant EMPTY_TREE_HASHES =\\n hex\\\"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce4d9470a821fbe90117ec357e30bad9305732fb19ddf54a07dd3e29f440619254ae39ce8537aca75e2eff3e38c98011dfe934e700a0967732fc07b430dd656a233fc9a15f5b4869c872f81087bb6104b7d63e6f9ab47f2c43f3535eae7172aa7f17d2dd614cddaa4d879276b11e0672c9560033d3e8453a1d045339d34ba601b9c37b8b13ca95166fb7af16988a70fcc90f38bf9126fd833da710a47fb37a55e68e7a427fa943d9966b389f4f257173676090c6e95f43e2cb6d65f8758111e30930b0b9deb73e155c59740bacf14a6ff04b64bb8e201a506409c3fe381ca4ea90cd5deac729d0fdaccc441d09d7325f41586ba13c801b7eccae0f95d8f3933efed8b96e5b7f6f459e9cb6a2f41bf276c7b85c10cd4662c04cbbb365434726c0a0c9695393027fb106a8153109ac516288a88b28a93817899460d6310b71cf1e6163e8806fa0d4b197a259e8c3ac28864268159d0ac85f8581ca28fa7d2c0c03eb91e3eee5ca7a3da2b3053c9770db73599fb149f620e3facef95e947c0ee860b72122e31e4bbd2b7c783d79cc30f60c6238651da7f0726f767d22747264fdb046f7549f26cc70ed5e18baeb6c81bb0625cb95bb4019aeecd40774ee87ae29ec517a71f6ee264c5d761379b3d7d617ca83677374b49d10aec50505ac087408ca892b573c267a712a52e1d06421fe276a03efb1889f337201110fdc32a81f8e152499af665835aabfdc6740c7e2c3791a31c3cdc9f5ab962f681b12fc092816a62f27d86025599a41233848702f0cfc0437b445682df51147a632a0a083d2d38b5e13e466a8935afff58bb533b3ef5d27fba63ee6b0fd9e67ff20af9d50deee3f8bf065ec220c1fd4ba57e341261d55997f85d66d32152526736872693d2b437a233e2337b715f6ac9a6a272622fdc2d67fcfe1da3459f8dab4ed7e40a657a54c36766c5e8ac9a88b35b05c34747e6507f6b044ab66180dc76ac1a696de03189593fedc0d0dbbd855c8ead673544899b0960e4a5a7ca43b4ef90afe607de7698caefdc242788f654b57a4fb32a71b335ef6ff9a4cc118b282b53bdd6d6192b7a82c3c5126b9c7e33c8e5a5ac9738b8bd31247fb7402054f97b573e8abb9faad219f4fd085aceaa7f542d787ee4196d365f3cc566e7bbcfbfd451230c48d804c017d21e2d8fa914e2559bb72bf0ab78c8ab92f00ef0d0d576eccdd486b64138a4172674857e543d1d5b639058dd908186597e366ad5f3d9c7ceaff44d04d1550b8d33abc751df07437834ba5acb32328a396994aebb3c40f759c2d6d7a3cb5377e55d5d218ef5a296dda8ddc355f3f50c3d0b660a51dfa4d98a6a5a33564556cf83c1373a814641d6a1dcef97b883fee61bb84fe60a3409340217e629cc7e4dcc93b85d8820921ff5826148b60e6939acd7838e1d7f20562bff8ee4b5ec4a05ad997a57b9796fdcb2eda87883c2640b072b140b946bfdf6575cacc066fdae04f6951e63624cbd316a677cad529bbe4e97b9144e4bc06c4afd1de55dd3e1175f90423847a230d34dfb71ed56f2965a7f6c72e6aa33c24c303fd67745d632656c5ef90bec80f4f5d1daa251988826cef375c81c36bf457e09687056f924677cb0bccf98dff81e014ce25f2d132497923e267363963cdf4302c5049d63131dc03fd95f65d8b6aa5934f817252c028c90f56d413b9d5d10d89790707dae2fabb249f649929927c21dd71e3f656826de5451c5da375aadecbd59d5ebf3a31fae65ac1b316a1611f1b276b26530f58d7247df459ce1f86db1d734f6f811932f042cee45d0e455306d01081bc3384f82c5fb2aacaa19d89cdfa46cc916eac61121475ba2e6191b4feecbe1789717021a158ace5d06744b40f551076b67cd63af60007f8c99876e1424883a45ec49d497ddaf808a5521ca74a999ab0b3c7aa9c80f85e93977ec61ce68b20307a1a81f71ca645b568fcd319ccbb5f651e87b707d37c39e15f945ea69e2f7c7d2ccc85b7e654c07e96f0636ae4044fe0e38590b431795ad0f8647bdd613713ada493cc17efd313206380e6a685b8198475bbd021c6e9d94daab2214947127506073e44d5408ba166c512a0b86805d07f5a44d3c41706be2bc15e712e55805248b92e8677d90f6d284d1d6ffaff2c430657042a0e82624fa3717b06cc0a6fd12230ea586dae83019fb9e06034ed2803c98d554b93c9a52348cafff75c40174a91f9ae6b8647854a156029f0b88b83316663ce574a4978277bb6bb27a31085634b6ec78864b6d8201c7e93903d75815067e378289a3d072ae172dafa6a452470f8d645bebfad9779594fc0784bb764a22e3a8181d93db7bf97893c414217a618ccb14caa9e92e8c61673afc9583662e812adba1f87a9c68202d60e909efab43c42c0cb00695fc7f1ffe67c75ca894c3c51e1e5e731360199e600f6ced9a87b2a6a87e70bf251bb5075ab222138288164b2eda727515ea7de12e2496d4fe42ea8d1a120c03cf9c50622c2afe4acb0dad98fd62d07ab4e828a94495f6d1ab973982c7ccbe6c1fae02788e4422ae22282fa49cbdb04ba54a7a238c6fc41187451383460762c06d1c8a72b9cd718866ad4b689e10c9a8c38fe5ef045bd785b01e980fc82c7e3532ce81876b778dd9f1ceeba4478e86411fb6fdd790683916ca832592485093644e8760cd7b4c01dba1ccc82b661bf13f0e3f34acd6b88\\\";\\n\\n /// @notice Gets merkle root hash of drive with a replacement\\n /// @param _position position of _drive\\n /// @param _logSizeOfReplacement log2 of size the replacement\\n /// @param _logSizeOfFullDrive log2 of size the full drive, which can be the entire machine\\n /// @param _replacement hash of the replacement\\n /// @param siblings of replacement that merkle root can be calculated\\n function getRootAfterReplacementInDrive(\\n uint256 _position,\\n uint256 _logSizeOfReplacement,\\n uint256 _logSizeOfFullDrive,\\n bytes32 _replacement,\\n bytes32[] calldata siblings\\n ) public pure returns (bytes32) {\\n require(\\n _logSizeOfFullDrive >= _logSizeOfReplacement &&\\n _logSizeOfReplacement >= 3 &&\\n _logSizeOfFullDrive <= 64,\\n \\\"3 <= logSizeOfReplacement <= logSizeOfFullDrive <= 64\\\"\\n );\\n\\n uint256 size = 1 << _logSizeOfReplacement;\\n\\n require(((size - 1) & _position) == 0, \\\"Position is not aligned\\\");\\n require(\\n siblings.length == _logSizeOfFullDrive - _logSizeOfReplacement,\\n \\\"Proof length does not match\\\"\\n );\\n\\n for (uint256 i; i < siblings.length; i++) {\\n if ((_position & (size << i)) == 0) {\\n _replacement = keccak256(\\n abi.encodePacked(_replacement, siblings[i])\\n );\\n } else {\\n _replacement = keccak256(\\n abi.encodePacked(siblings[i], _replacement)\\n );\\n }\\n }\\n\\n return _replacement;\\n }\\n\\n /// @notice Gets precomputed hash of zero in empty tree hashes\\n /// @param _index of hash wanted\\n /// @dev first index is keccak(0), second index is keccak(keccak(0), keccak(0))\\n function getEmptyTreeHashAtIndex(uint256 _index)\\n public\\n pure\\n returns (bytes32)\\n {\\n uint256 start = _index * 32;\\n require(EMPTY_TREE_SIZE >= start + 32, \\\"index out of bounds\\\");\\n bytes32 hashedZeros;\\n bytes memory zeroTree = EMPTY_TREE_HASHES;\\n\\n // first word is length, then skip index words\\n assembly {\\n hashedZeros := mload(add(add(zeroTree, 0x20), start))\\n }\\n return hashedZeros;\\n }\\n\\n /// @notice get merkle root of generic array of bytes\\n /// @param _data array of bytes to be merklelized\\n /// @param _log2Size log2 of total size of the drive\\n /// @dev _data is padded with zeroes until is multiple of 8\\n /// @dev root is completed with zero tree until log2size is complete\\n /// @dev hashes are taken word by word (8 bytes by 8 bytes)\\n function getMerkleRootFromBytes(bytes calldata _data, uint256 _log2Size)\\n public\\n pure\\n returns (bytes32)\\n {\\n require(_log2Size >= 3 && _log2Size <= 64, \\\"range of log2Size: [3,64]\\\");\\n\\n // if _data is empty return pristine drive of size log2size\\n if (_data.length == 0) return getEmptyTreeHashAtIndex(_log2Size - 3);\\n\\n // total size of the drive in words\\n uint256 size = 1 << (_log2Size - 3);\\n require(\\n size << L_WORD_SIZE >= _data.length,\\n \\\"data is bigger than drive\\\"\\n );\\n // the stack depth is log2(_data.length / 8) + 2\\n uint256 stack_depth = 2 +\\n ((_data.length) >> L_WORD_SIZE).getLog2Floor();\\n bytes32[] memory stack = new bytes32[](stack_depth);\\n\\n uint256 numOfHashes; // total number of hashes on stack (counting levels)\\n uint256 stackLength; // total length of stack\\n uint256 numOfJoins; // number of hashes of the same level on stack\\n uint256 topStackLevel; // hash level of the top of the stack\\n\\n while (numOfHashes < size) {\\n if ((numOfHashes << L_WORD_SIZE) < _data.length) {\\n // we still have words to hash\\n stack[stackLength] = getHashOfWordAtIndex(_data, numOfHashes);\\n numOfHashes++;\\n\\n numOfJoins = numOfHashes;\\n } else {\\n // since padding happens in hashOfWordAtIndex function\\n // we only need to complete the stack with pre-computed\\n // hash(0), hash(hash(0),hash(0)) and so on\\n topStackLevel = numOfHashes.ctz();\\n\\n stack[stackLength] = getEmptyTreeHashAtIndex(topStackLevel);\\n\\n //Empty Tree Hash summarizes many hashes\\n numOfHashes = numOfHashes + (1 << topStackLevel);\\n numOfJoins = numOfHashes >> topStackLevel;\\n }\\n\\n stackLength++;\\n\\n // while there are joins, hash top of stack together\\n while (numOfJoins & 1 == 0) {\\n bytes32 h2 = stack[stackLength - 1];\\n bytes32 h1 = stack[stackLength - 2];\\n\\n stack[stackLength - 2] = keccak256(abi.encodePacked(h1, h2));\\n stackLength = stackLength - 1; // remove hashes from stack\\n\\n numOfJoins = numOfJoins >> 1;\\n }\\n }\\n require(stackLength == 1, \\\"stack error\\\");\\n\\n return stack[0];\\n }\\n\\n /// @notice Get the hash of a word in an array of bytes\\n /// @param _data array of bytes\\n /// @param _wordIndex index of word inside the bytes to get the hash of\\n /// @dev if word is incomplete (< 8 bytes) it gets padded with zeroes\\n function getHashOfWordAtIndex(bytes calldata _data, uint256 _wordIndex)\\n public\\n pure\\n returns (bytes32)\\n {\\n uint256 start = _wordIndex << L_WORD_SIZE;\\n uint256 end = start + (1 << L_WORD_SIZE);\\n\\n // TODO: in .lua this just returns zero, but this might be more consistent\\n require(start <= _data.length, \\\"word out of bounds\\\");\\n\\n if (end <= _data.length) {\\n return keccak256(abi.encodePacked(_data[start:end]));\\n }\\n\\n // word is incomplete\\n // fill paddedSlice with incomplete words - the rest is going to be bytes(0)\\n bytes memory paddedSlice = new bytes(8);\\n uint256 remaining = _data.length - start;\\n\\n for (uint256 i; i < remaining; i++) {\\n paddedSlice[i] = _data[start + i];\\n }\\n\\n return keccak256(paddedSlice);\\n }\\n\\n /// @notice Calculate the root of Merkle tree from an array of power of 2 elements\\n /// @param hashes The array containing power of 2 elements\\n /// @return byte32 the root hash being calculated\\n function calculateRootFromPowerOfTwo(bytes32[] memory hashes)\\n public\\n pure\\n returns (bytes32)\\n {\\n // revert when the input is not of power of 2\\n require((hashes.length).isPowerOf2(), \\\"array len not power of 2\\\");\\n\\n if (hashes.length == 1) {\\n return hashes[0];\\n } else {\\n bytes32[] memory newHashes = new bytes32[](hashes.length >> 1);\\n\\n for (uint256 i; i < hashes.length; i += 2) {\\n newHashes[i >> 1] = keccak256(\\n abi.encodePacked(hashes[i], hashes[i + 1])\\n );\\n }\\n\\n return calculateRootFromPowerOfTwo(newHashes);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe9896db44cc4dab335a3e776c629186824823d316d902b2efecb4b0a3e3dfdb7\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x6116df61003a600b82828239805160001a60731461002d57634e487b7160e01b600052600060045260246000fd5b30600052607381538281f3fe73000000000000000000000000000000000000000030146080604052600436106100615760003560e01c806334bd712d14610066578063451a10551461008b57806379de46011461009e57806382b0eab8146100b1578063c84583a1146100c4575b600080fd5b610079610074366004610cbd565b6100d7565b60405190815260200160405180910390f35b610079610099366004610d30565b610245565b6100796100ac366004610d60565b6102d6565b6100796100bf366004610bdd565b610505565b6100796100d2366004610cbd565b610756565b6000600382901b816100ea600883610e4f565b9050848211156101365760405162461bcd60e51b8152602060048201526012602482015271776f7264206f7574206f6620626f756e647360701b60448201526064015b60405180910390fd5b8481116101795761014981838789610e27565b60405160200161015a929190610e17565b604051602081830303815290604052805190602001209250505061023e565b60408051600880825281830190925260009160208201818036833701905050905060006101a68488610eab565b905060005b8181101561022f5788886101bf8388610e4f565b8181106101dc57634e487b7160e01b600052603260045260246000fd5b9050013560f81c60f81b83828151811061020657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053508061022781610ec2565b9150506101ab565b50508051602090910120925050505b9392505050565b600080610253836020610e8c565b9050610260816020610e4f565b6107a010156102a75760405162461bcd60e51b8152602060048201526013602482015272696e646578206f7574206f6620626f756e647360681b604482015260640161012d565b600080604051806107c001604052806107a08152602001610f0a6107a091399290920160200151949350505050565b60008585101580156102e9575060038610155b80156102f6575060408511155b6103605760405162461bcd60e51b815260206004820152603560248201527f33203c3d206c6f6753697a654f665265706c6163656d656e74203c3d206c6f6760448201527414da5e9953d9919d5b1b111c9a5d99480f0f480d8d605a1b606482015260840161012d565b600180871b9088906103729083610eab565b16156103c05760405162461bcd60e51b815260206004820152601760248201527f506f736974696f6e206973206e6f7420616c69676e6564000000000000000000604482015260640161012d565b6103ca8787610eab565b83146104185760405162461bcd60e51b815260206004820152601b60248201527f50726f6f66206c656e67746820646f6573206e6f74206d617463680000000000604482015260640161012d565b60005b838110156104f85781811b891661048b578585858381811061044d57634e487b7160e01b600052603260045260246000fd5b9050602002013560405160200161046e929190918252602082015260400190565b6040516020818303038152906040528051906020012095506104e6565b8484828181106104ab57634e487b7160e01b600052603260045260246000fd5b90506020020135866040516020016104cd929190918252602082015260400190565b6040516020818303038152906040528051906020012095505b806104f081610ec2565b91505061041b565b5093979650505050505050565b805160405163d82ae4b160e01b8152600091739fE46736679d2D9a65F0992F2272dE9f3c7fa6e09163d82ae4b1916105439160040190815260200190565b60206040518083038186803b15801561055b57600080fd5b505af415801561056f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105939190610c9d565b6105df5760405162461bcd60e51b815260206004820152601860248201527f6172726179206c656e206e6f7420706f776572206f6620320000000000000000604482015260640161012d565b815160011415610619578160008151811061060a57634e487b7160e01b600052603260045260246000fd5b60200260200101519050919050565b600060018351901c67ffffffffffffffff81111561064757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610670578160200160208202803683370190505b50905060005b835181101561074c5783818151811061069f57634e487b7160e01b600052603260045260246000fd5b6020026020010151848260016106b59190610e4f565b815181106106d357634e487b7160e01b600052603260045260246000fd5b60200260200101516040516020016106f5929190918252602082015260400190565b6040516020818303038152906040528051906020012082600183901c8151811061072f57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152610745600282610e4f565b9050610676565b5061023e81610505565b60006003821015801561076a575060408211155b6107b65760405162461bcd60e51b815260206004820152601960248201527f72616e6765206f66206c6f673253697a653a205b332c36345d00000000000000604482015260640161012d565b826107d0576107c9610099600384610eab565b905061023e565b60006107dd600384610eab565b6001901b9050600381901b8411156108375760405162461bcd60e51b815260206004820152601960248201527f6461746120697320626967676572207468616e20647269766500000000000000604482015260640161012d565b6040516306c8e54b60e01b8152600385901c6004820152600090739fE46736679d2D9a65F0992F2272dE9f3c7fa6e0906306c8e54b9060240160206040518083038186803b15801561088857600080fd5b505af415801561089c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c09190610df6565b6108cb906002610e67565b60ff16905060008167ffffffffffffffff8111156108f957634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610922578160200160208202803683370190505b5090506000806000805b86841015610b6657600384901b8a111561098b5761094b8b8b866100d7565b85848151811061096b57634e487b7160e01b600052603260045260246000fd5b60209081029190910101528361098081610ec2565b945050839150610a59565b60405163052dcf5f60e31b815260048101859052739fE46736679d2D9a65F0992F2272dE9f3c7fa6e09063296e7af89060240160206040518083038186803b1580156109d657600080fd5b505af41580156109ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0e9190610d48565b9050610a1981610245565b858481518110610a3957634e487b7160e01b600052603260045260246000fd5b6020908102919091010152610a516001821b85610e4f565b935083811c91505b82610a6381610ec2565b9350505b60018216610b6157600085610a7d600186610eab565b81518110610a9b57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600086600286610ab59190610eab565b81518110610ad357634e487b7160e01b600052603260045260246000fd5b602002602001015190508082604051602001610af9929190918252602082015260400190565b6040516020818303038152906040528051906020012087600287610b1d9190610eab565b81518110610b3b57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152610b51600186610eab565b9450600184901c93505050610a67565b61092c565b82600114610ba45760405162461bcd60e51b815260206004820152600b60248201526a39ba30b1b59032b93937b960a91b604482015260640161012d565b84600081518110610bc557634e487b7160e01b600052603260045260246000fd5b60200260200101519750505050505050509392505050565b60006020808385031215610bef578182fd5b823567ffffffffffffffff80821115610c06578384fd5b818501915085601f830112610c19578384fd5b813581811115610c2b57610c2b610ef3565b8060051b604051601f19603f83011681018181108582111715610c5057610c50610ef3565b604052828152858101935084860182860187018a1015610c6e578788fd5b8795505b83861015610c90578035855260019590950194938601938601610c72565b5098975050505050505050565b600060208284031215610cae578081fd5b8151801515811461023e578182fd5b600080600060408486031215610cd1578182fd5b833567ffffffffffffffff80821115610ce8578384fd5b818601915086601f830112610cfb578384fd5b813581811115610d09578485fd5b876020828501011115610d1a578485fd5b6020928301989097509590910135949350505050565b600060208284031215610d41578081fd5b5035919050565b600060208284031215610d59578081fd5b5051919050565b60008060008060008060a08789031215610d78578182fd5b86359550602087013594506040870135935060608701359250608087013567ffffffffffffffff80821115610dab578384fd5b818901915089601f830112610dbe578384fd5b813581811115610dcc578485fd5b8a60208260051b8501011115610de0578485fd5b6020830194508093505050509295509295509295565b600060208284031215610e07578081fd5b815160ff8116811461023e578182fd5b8183823760009101908152919050565b60008085851115610e36578182fd5b83861115610e42578182fd5b5050820193919092039150565b60008219821115610e6257610e62610edd565b500190565b600060ff821660ff84168060ff03821115610e8457610e84610edd565b019392505050565b6000816000190483118215151615610ea657610ea6610edd565b500290565b600082821015610ebd57610ebd610edd565b500390565b6000600019821415610ed657610ed6610edd565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfe011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce4d9470a821fbe90117ec357e30bad9305732fb19ddf54a07dd3e29f440619254ae39ce8537aca75e2eff3e38c98011dfe934e700a0967732fc07b430dd656a233fc9a15f5b4869c872f81087bb6104b7d63e6f9ab47f2c43f3535eae7172aa7f17d2dd614cddaa4d879276b11e0672c9560033d3e8453a1d045339d34ba601b9c37b8b13ca95166fb7af16988a70fcc90f38bf9126fd833da710a47fb37a55e68e7a427fa943d9966b389f4f257173676090c6e95f43e2cb6d65f8758111e30930b0b9deb73e155c59740bacf14a6ff04b64bb8e201a506409c3fe381ca4ea90cd5deac729d0fdaccc441d09d7325f41586ba13c801b7eccae0f95d8f3933efed8b96e5b7f6f459e9cb6a2f41bf276c7b85c10cd4662c04cbbb365434726c0a0c9695393027fb106a8153109ac516288a88b28a93817899460d6310b71cf1e6163e8806fa0d4b197a259e8c3ac28864268159d0ac85f8581ca28fa7d2c0c03eb91e3eee5ca7a3da2b3053c9770db73599fb149f620e3facef95e947c0ee860b72122e31e4bbd2b7c783d79cc30f60c6238651da7f0726f767d22747264fdb046f7549f26cc70ed5e18baeb6c81bb0625cb95bb4019aeecd40774ee87ae29ec517a71f6ee264c5d761379b3d7d617ca83677374b49d10aec50505ac087408ca892b573c267a712a52e1d06421fe276a03efb1889f337201110fdc32a81f8e152499af665835aabfdc6740c7e2c3791a31c3cdc9f5ab962f681b12fc092816a62f27d86025599a41233848702f0cfc0437b445682df51147a632a0a083d2d38b5e13e466a8935afff58bb533b3ef5d27fba63ee6b0fd9e67ff20af9d50deee3f8bf065ec220c1fd4ba57e341261d55997f85d66d32152526736872693d2b437a233e2337b715f6ac9a6a272622fdc2d67fcfe1da3459f8dab4ed7e40a657a54c36766c5e8ac9a88b35b05c34747e6507f6b044ab66180dc76ac1a696de03189593fedc0d0dbbd855c8ead673544899b0960e4a5a7ca43b4ef90afe607de7698caefdc242788f654b57a4fb32a71b335ef6ff9a4cc118b282b53bdd6d6192b7a82c3c5126b9c7e33c8e5a5ac9738b8bd31247fb7402054f97b573e8abb9faad219f4fd085aceaa7f542d787ee4196d365f3cc566e7bbcfbfd451230c48d804c017d21e2d8fa914e2559bb72bf0ab78c8ab92f00ef0d0d576eccdd486b64138a4172674857e543d1d5b639058dd908186597e366ad5f3d9c7ceaff44d04d1550b8d33abc751df07437834ba5acb32328a396994aebb3c40f759c2d6d7a3cb5377e55d5d218ef5a296dda8ddc355f3f50c3d0b660a51dfa4d98a6a5a33564556cf83c1373a814641d6a1dcef97b883fee61bb84fe60a3409340217e629cc7e4dcc93b85d8820921ff5826148b60e6939acd7838e1d7f20562bff8ee4b5ec4a05ad997a57b9796fdcb2eda87883c2640b072b140b946bfdf6575cacc066fdae04f6951e63624cbd316a677cad529bbe4e97b9144e4bc06c4afd1de55dd3e1175f90423847a230d34dfb71ed56f2965a7f6c72e6aa33c24c303fd67745d632656c5ef90bec80f4f5d1daa251988826cef375c81c36bf457e09687056f924677cb0bccf98dff81e014ce25f2d132497923e267363963cdf4302c5049d63131dc03fd95f65d8b6aa5934f817252c028c90f56d413b9d5d10d89790707dae2fabb249f649929927c21dd71e3f656826de5451c5da375aadecbd59d5ebf3a31fae65ac1b316a1611f1b276b26530f58d7247df459ce1f86db1d734f6f811932f042cee45d0e455306d01081bc3384f82c5fb2aacaa19d89cdfa46cc916eac61121475ba2e6191b4feecbe1789717021a158ace5d06744b40f551076b67cd63af60007f8c99876e1424883a45ec49d497ddaf808a5521ca74a999ab0b3c7aa9c80f85e93977ec61ce68b20307a1a81f71ca645b568fcd319ccbb5f651e87b707d37c39e15f945ea69e2f7c7d2ccc85b7e654c07e96f0636ae4044fe0e38590b431795ad0f8647bdd613713ada493cc17efd313206380e6a685b8198475bbd021c6e9d94daab2214947127506073e44d5408ba166c512a0b86805d07f5a44d3c41706be2bc15e712e55805248b92e8677d90f6d284d1d6ffaff2c430657042a0e82624fa3717b06cc0a6fd12230ea586dae83019fb9e06034ed2803c98d554b93c9a52348cafff75c40174a91f9ae6b8647854a156029f0b88b83316663ce574a4978277bb6bb27a31085634b6ec78864b6d8201c7e93903d75815067e378289a3d072ae172dafa6a452470f8d645bebfad9779594fc0784bb764a22e3a8181d93db7bf97893c414217a618ccb14caa9e92e8c61673afc9583662e812adba1f87a9c68202d60e909efab43c42c0cb00695fc7f1ffe67c75ca894c3c51e1e5e731360199e600f6ced9a87b2a6a87e70bf251bb5075ab222138288164b2eda727515ea7de12e2496d4fe42ea8d1a120c03cf9c50622c2afe4acb0dad98fd62d07ab4e828a94495f6d1ab973982c7ccbe6c1fae02788e4422ae22282fa49cbdb04ba54a7a238c6fc41187451383460762c06d1c8a72b9cd718866ad4b689e10c9a8c38fe5ef045bd785b01e980fc82c7e3532ce81876b778dd9f1ceeba4478e86411fb6fdd790683916ca832592485093644e8760cd7b4c01dba1ccc82b661bf13f0e3f34acd6b88a2646970667358221220be79c972192069d105a5fc9aae66c9ff55a7f4076d708aa33a4f2ecaec2873e364736f6c63430008040033", + "deployedBytecode": "0x73000000000000000000000000000000000000000030146080604052600436106100615760003560e01c806334bd712d14610066578063451a10551461008b57806379de46011461009e57806382b0eab8146100b1578063c84583a1146100c4575b600080fd5b610079610074366004610cbd565b6100d7565b60405190815260200160405180910390f35b610079610099366004610d30565b610245565b6100796100ac366004610d60565b6102d6565b6100796100bf366004610bdd565b610505565b6100796100d2366004610cbd565b610756565b6000600382901b816100ea600883610e4f565b9050848211156101365760405162461bcd60e51b8152602060048201526012602482015271776f7264206f7574206f6620626f756e647360701b60448201526064015b60405180910390fd5b8481116101795761014981838789610e27565b60405160200161015a929190610e17565b604051602081830303815290604052805190602001209250505061023e565b60408051600880825281830190925260009160208201818036833701905050905060006101a68488610eab565b905060005b8181101561022f5788886101bf8388610e4f565b8181106101dc57634e487b7160e01b600052603260045260246000fd5b9050013560f81c60f81b83828151811061020657634e487b7160e01b600052603260045260246000fd5b60200101906001600160f81b031916908160001a9053508061022781610ec2565b9150506101ab565b50508051602090910120925050505b9392505050565b600080610253836020610e8c565b9050610260816020610e4f565b6107a010156102a75760405162461bcd60e51b8152602060048201526013602482015272696e646578206f7574206f6620626f756e647360681b604482015260640161012d565b600080604051806107c001604052806107a08152602001610f0a6107a091399290920160200151949350505050565b60008585101580156102e9575060038610155b80156102f6575060408511155b6103605760405162461bcd60e51b815260206004820152603560248201527f33203c3d206c6f6753697a654f665265706c6163656d656e74203c3d206c6f6760448201527414da5e9953d9919d5b1b111c9a5d99480f0f480d8d605a1b606482015260840161012d565b600180871b9088906103729083610eab565b16156103c05760405162461bcd60e51b815260206004820152601760248201527f506f736974696f6e206973206e6f7420616c69676e6564000000000000000000604482015260640161012d565b6103ca8787610eab565b83146104185760405162461bcd60e51b815260206004820152601b60248201527f50726f6f66206c656e67746820646f6573206e6f74206d617463680000000000604482015260640161012d565b60005b838110156104f85781811b891661048b578585858381811061044d57634e487b7160e01b600052603260045260246000fd5b9050602002013560405160200161046e929190918252602082015260400190565b6040516020818303038152906040528051906020012095506104e6565b8484828181106104ab57634e487b7160e01b600052603260045260246000fd5b90506020020135866040516020016104cd929190918252602082015260400190565b6040516020818303038152906040528051906020012095505b806104f081610ec2565b91505061041b565b5093979650505050505050565b805160405163d82ae4b160e01b815260009173__$8b7ebe2a69e01741840a6648963dfd5409$__9163d82ae4b1916105439160040190815260200190565b60206040518083038186803b15801561055b57600080fd5b505af415801561056f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105939190610c9d565b6105df5760405162461bcd60e51b815260206004820152601860248201527f6172726179206c656e206e6f7420706f776572206f6620320000000000000000604482015260640161012d565b815160011415610619578160008151811061060a57634e487b7160e01b600052603260045260246000fd5b60200260200101519050919050565b600060018351901c67ffffffffffffffff81111561064757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610670578160200160208202803683370190505b50905060005b835181101561074c5783818151811061069f57634e487b7160e01b600052603260045260246000fd5b6020026020010151848260016106b59190610e4f565b815181106106d357634e487b7160e01b600052603260045260246000fd5b60200260200101516040516020016106f5929190918252602082015260400190565b6040516020818303038152906040528051906020012082600183901c8151811061072f57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152610745600282610e4f565b9050610676565b5061023e81610505565b60006003821015801561076a575060408211155b6107b65760405162461bcd60e51b815260206004820152601960248201527f72616e6765206f66206c6f673253697a653a205b332c36345d00000000000000604482015260640161012d565b826107d0576107c9610099600384610eab565b905061023e565b60006107dd600384610eab565b6001901b9050600381901b8411156108375760405162461bcd60e51b815260206004820152601960248201527f6461746120697320626967676572207468616e20647269766500000000000000604482015260640161012d565b6040516306c8e54b60e01b8152600385901c600482015260009073__$8b7ebe2a69e01741840a6648963dfd5409$__906306c8e54b9060240160206040518083038186803b15801561088857600080fd5b505af415801561089c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108c09190610df6565b6108cb906002610e67565b60ff16905060008167ffffffffffffffff8111156108f957634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015610922578160200160208202803683370190505b5090506000806000805b86841015610b6657600384901b8a111561098b5761094b8b8b866100d7565b85848151811061096b57634e487b7160e01b600052603260045260246000fd5b60209081029190910101528361098081610ec2565b945050839150610a59565b60405163052dcf5f60e31b81526004810185905273__$8b7ebe2a69e01741840a6648963dfd5409$__9063296e7af89060240160206040518083038186803b1580156109d657600080fd5b505af41580156109ea573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a0e9190610d48565b9050610a1981610245565b858481518110610a3957634e487b7160e01b600052603260045260246000fd5b6020908102919091010152610a516001821b85610e4f565b935083811c91505b82610a6381610ec2565b9350505b60018216610b6157600085610a7d600186610eab565b81518110610a9b57634e487b7160e01b600052603260045260246000fd5b60200260200101519050600086600286610ab59190610eab565b81518110610ad357634e487b7160e01b600052603260045260246000fd5b602002602001015190508082604051602001610af9929190918252602082015260400190565b6040516020818303038152906040528051906020012087600287610b1d9190610eab565b81518110610b3b57634e487b7160e01b600052603260045260246000fd5b6020908102919091010152610b51600186610eab565b9450600184901c93505050610a67565b61092c565b82600114610ba45760405162461bcd60e51b815260206004820152600b60248201526a39ba30b1b59032b93937b960a91b604482015260640161012d565b84600081518110610bc557634e487b7160e01b600052603260045260246000fd5b60200260200101519750505050505050509392505050565b60006020808385031215610bef578182fd5b823567ffffffffffffffff80821115610c06578384fd5b818501915085601f830112610c19578384fd5b813581811115610c2b57610c2b610ef3565b8060051b604051601f19603f83011681018181108582111715610c5057610c50610ef3565b604052828152858101935084860182860187018a1015610c6e578788fd5b8795505b83861015610c90578035855260019590950194938601938601610c72565b5098975050505050505050565b600060208284031215610cae578081fd5b8151801515811461023e578182fd5b600080600060408486031215610cd1578182fd5b833567ffffffffffffffff80821115610ce8578384fd5b818601915086601f830112610cfb578384fd5b813581811115610d09578485fd5b876020828501011115610d1a578485fd5b6020928301989097509590910135949350505050565b600060208284031215610d41578081fd5b5035919050565b600060208284031215610d59578081fd5b5051919050565b60008060008060008060a08789031215610d78578182fd5b86359550602087013594506040870135935060608701359250608087013567ffffffffffffffff80821115610dab578384fd5b818901915089601f830112610dbe578384fd5b813581811115610dcc578485fd5b8a60208260051b8501011115610de0578485fd5b6020830194508093505050509295509295509295565b600060208284031215610e07578081fd5b815160ff8116811461023e578182fd5b8183823760009101908152919050565b60008085851115610e36578182fd5b83861115610e42578182fd5b5050820193919092039150565b60008219821115610e6257610e62610edd565b500190565b600060ff821660ff84168060ff03821115610e8457610e84610edd565b019392505050565b6000816000190483118215151615610ea657610ea6610edd565b500290565b600082821015610ebd57610ebd610edd565b500390565b6000600019821415610ed657610ed6610edd565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fdfe011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce4d9470a821fbe90117ec357e30bad9305732fb19ddf54a07dd3e29f440619254ae39ce8537aca75e2eff3e38c98011dfe934e700a0967732fc07b430dd656a233fc9a15f5b4869c872f81087bb6104b7d63e6f9ab47f2c43f3535eae7172aa7f17d2dd614cddaa4d879276b11e0672c9560033d3e8453a1d045339d34ba601b9c37b8b13ca95166fb7af16988a70fcc90f38bf9126fd833da710a47fb37a55e68e7a427fa943d9966b389f4f257173676090c6e95f43e2cb6d65f8758111e30930b0b9deb73e155c59740bacf14a6ff04b64bb8e201a506409c3fe381ca4ea90cd5deac729d0fdaccc441d09d7325f41586ba13c801b7eccae0f95d8f3933efed8b96e5b7f6f459e9cb6a2f41bf276c7b85c10cd4662c04cbbb365434726c0a0c9695393027fb106a8153109ac516288a88b28a93817899460d6310b71cf1e6163e8806fa0d4b197a259e8c3ac28864268159d0ac85f8581ca28fa7d2c0c03eb91e3eee5ca7a3da2b3053c9770db73599fb149f620e3facef95e947c0ee860b72122e31e4bbd2b7c783d79cc30f60c6238651da7f0726f767d22747264fdb046f7549f26cc70ed5e18baeb6c81bb0625cb95bb4019aeecd40774ee87ae29ec517a71f6ee264c5d761379b3d7d617ca83677374b49d10aec50505ac087408ca892b573c267a712a52e1d06421fe276a03efb1889f337201110fdc32a81f8e152499af665835aabfdc6740c7e2c3791a31c3cdc9f5ab962f681b12fc092816a62f27d86025599a41233848702f0cfc0437b445682df51147a632a0a083d2d38b5e13e466a8935afff58bb533b3ef5d27fba63ee6b0fd9e67ff20af9d50deee3f8bf065ec220c1fd4ba57e341261d55997f85d66d32152526736872693d2b437a233e2337b715f6ac9a6a272622fdc2d67fcfe1da3459f8dab4ed7e40a657a54c36766c5e8ac9a88b35b05c34747e6507f6b044ab66180dc76ac1a696de03189593fedc0d0dbbd855c8ead673544899b0960e4a5a7ca43b4ef90afe607de7698caefdc242788f654b57a4fb32a71b335ef6ff9a4cc118b282b53bdd6d6192b7a82c3c5126b9c7e33c8e5a5ac9738b8bd31247fb7402054f97b573e8abb9faad219f4fd085aceaa7f542d787ee4196d365f3cc566e7bbcfbfd451230c48d804c017d21e2d8fa914e2559bb72bf0ab78c8ab92f00ef0d0d576eccdd486b64138a4172674857e543d1d5b639058dd908186597e366ad5f3d9c7ceaff44d04d1550b8d33abc751df07437834ba5acb32328a396994aebb3c40f759c2d6d7a3cb5377e55d5d218ef5a296dda8ddc355f3f50c3d0b660a51dfa4d98a6a5a33564556cf83c1373a814641d6a1dcef97b883fee61bb84fe60a3409340217e629cc7e4dcc93b85d8820921ff5826148b60e6939acd7838e1d7f20562bff8ee4b5ec4a05ad997a57b9796fdcb2eda87883c2640b072b140b946bfdf6575cacc066fdae04f6951e63624cbd316a677cad529bbe4e97b9144e4bc06c4afd1de55dd3e1175f90423847a230d34dfb71ed56f2965a7f6c72e6aa33c24c303fd67745d632656c5ef90bec80f4f5d1daa251988826cef375c81c36bf457e09687056f924677cb0bccf98dff81e014ce25f2d132497923e267363963cdf4302c5049d63131dc03fd95f65d8b6aa5934f817252c028c90f56d413b9d5d10d89790707dae2fabb249f649929927c21dd71e3f656826de5451c5da375aadecbd59d5ebf3a31fae65ac1b316a1611f1b276b26530f58d7247df459ce1f86db1d734f6f811932f042cee45d0e455306d01081bc3384f82c5fb2aacaa19d89cdfa46cc916eac61121475ba2e6191b4feecbe1789717021a158ace5d06744b40f551076b67cd63af60007f8c99876e1424883a45ec49d497ddaf808a5521ca74a999ab0b3c7aa9c80f85e93977ec61ce68b20307a1a81f71ca645b568fcd319ccbb5f651e87b707d37c39e15f945ea69e2f7c7d2ccc85b7e654c07e96f0636ae4044fe0e38590b431795ad0f8647bdd613713ada493cc17efd313206380e6a685b8198475bbd021c6e9d94daab2214947127506073e44d5408ba166c512a0b86805d07f5a44d3c41706be2bc15e712e55805248b92e8677d90f6d284d1d6ffaff2c430657042a0e82624fa3717b06cc0a6fd12230ea586dae83019fb9e06034ed2803c98d554b93c9a52348cafff75c40174a91f9ae6b8647854a156029f0b88b83316663ce574a4978277bb6bb27a31085634b6ec78864b6d8201c7e93903d75815067e378289a3d072ae172dafa6a452470f8d645bebfad9779594fc0784bb764a22e3a8181d93db7bf97893c414217a618ccb14caa9e92e8c61673afc9583662e812adba1f87a9c68202d60e909efab43c42c0cb00695fc7f1ffe67c75ca894c3c51e1e5e731360199e600f6ced9a87b2a6a87e70bf251bb5075ab222138288164b2eda727515ea7de12e2496d4fe42ea8d1a120c03cf9c50622c2afe4acb0dad98fd62d07ab4e828a94495f6d1ab973982c7ccbe6c1fae02788e4422ae22282fa49cbdb04ba54a7a238c6fc41187451383460762c06d1c8a72b9cd718866ad4b689e10c9a8c38fe5ef045bd785b01e980fc82c7e3532ce81876b778dd9f1ceeba4478e86411fb6fdd790683916ca832592485093644e8760cd7b4c01dba1ccc82b661bf13f0e3f34acd6b88a2646970667358221220be79c972192069d105a5fc9aae66c9ff55a7f4076d708aa33a4f2ecaec2873e364736f6c63430008040033", + "libraries": { + "CartesiMath": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" + }, + "devdoc": { + "kind": "dev", + "methods": { + "calculateRootFromPowerOfTwo(bytes32[])": { + "params": { + "hashes": "The array containing power of 2 elements" + }, + "returns": { + "_0": "byte32 the root hash being calculated" + } + }, + "getEmptyTreeHashAtIndex(uint256)": { + "details": "first index is keccak(0), second index is keccak(keccak(0), keccak(0))", + "params": { + "_index": "of hash wanted" + } + }, + "getHashOfWordAtIndex(bytes,uint256)": { + "details": "if word is incomplete (< 8 bytes) it gets padded with zeroes", + "params": { + "_data": "array of bytes", + "_wordIndex": "index of word inside the bytes to get the hash of" + } + }, + "getMerkleRootFromBytes(bytes,uint256)": { + "details": "_data is padded with zeroes until is multiple of 8root is completed with zero tree until log2size is completehashes are taken word by word (8 bytes by 8 bytes)", + "params": { + "_data": "array of bytes to be merklelized", + "_log2Size": "log2 of total size of the drive" + } + }, + "getRootAfterReplacementInDrive(uint256,uint256,uint256,bytes32,bytes32[])": { + "params": { + "_logSizeOfFullDrive": "log2 of size the full drive, which can be the entire machine", + "_logSizeOfReplacement": "log2 of size the replacement", + "_position": "position of _drive", + "_replacement": "hash of the replacement", + "siblings": "of replacement that merkle root can be calculated" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "calculateRootFromPowerOfTwo(bytes32[])": { + "notice": "Calculate the root of Merkle tree from an array of power of 2 elements" + }, + "getEmptyTreeHashAtIndex(uint256)": { + "notice": "Gets precomputed hash of zero in empty tree hashes" + }, + "getHashOfWordAtIndex(bytes,uint256)": { + "notice": "Get the hash of a word in an array of bytes" + }, + "getMerkleRootFromBytes(bytes,uint256)": { + "notice": "get merkle root of generic array of bytes" + }, + "getRootAfterReplacementInDrive(uint256,uint256,uint256,bytes32,bytes32[])": { + "notice": "Gets merkle root hash of drive with a replacement" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/MineTimelock.json b/echo-js/deployments/localhost/MineTimelock.json new file mode 100644 index 00000000..c30297b1 --- /dev/null +++ b/echo-js/deployments/localhost/MineTimelock.json @@ -0,0 +1,241 @@ +{ + "address": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6", + "abi": [ + { + "constant": true, + "inputs": [], + "name": "beneficiary", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "release", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "isOwner", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "releaseTime", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "beneficiary", + "type": "address" + } + ], + "name": "changeBeneficiary", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "token", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "token", + "type": "address" + }, + { + "name": "beneficiary", + "type": "address" + }, + { + "name": "releaseTime", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "name": "newBeneficiary", + "type": "address" + } + ], + "name": "BeneficiaryUpdated", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + } + ], + "transactionHash": "0xfa8bd2544aee2d5b77458d17bf2a4bce47f51afe1a04f3e9d7e1b9690b094cc8", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6", + "transactionIndex": 0, + "gasUsed": "907201", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000020000000000000100000800000000000000000000000000000000400000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000040000000000000000000000000000000008000000000000000200000000000000000000000002000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7778853881fc64c60f4d7c4030b10c4f9bd8ad9264ad125afc58757c79524bcb", + "transactionHash": "0xfa8bd2544aee2d5b77458d17bf2a4bce47f51afe1a04f3e9d7e1b9690b094cc8", + "logs": [ + { + "transactionIndex": 0, + "blockNumber": 9, + "transactionHash": "0xfa8bd2544aee2d5b77458d17bf2a4bce47f51afe1a04f3e9d7e1b9690b094cc8", + "address": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266" + ], + "data": "0x", + "logIndex": 0, + "blockHash": "0x7778853881fc64c60f4d7c4030b10c4f9bd8ad9264ad125afc58757c79524bcb" + } + ], + "blockNumber": 9, + "cumulativeGasUsed": "907201", + "status": 1, + "byzantium": true + }, + "args": [ + "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853", + "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", + 1761850573 + ], + "numDeployments": 1, + "bytecode": "0x608060405234801561001057600080fd5b50604051606080610fea8339810180604052606081101561003057600080fd5b8101908080519060200190929190805190602001909291908051906020019092919050505060006100656101ee60201b60201c565b9050806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a350428111151561015d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180610fb86032913960400191505060405180910390fd5b82600160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550806003819055505050506101f6565b600033905090565b610db3806102056000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c80638f32d59b116100665780638f32d59b14610140578063b91d400114610162578063dc07065714610180578063f2fde38b146101c4578063fc0c546a1461020857610093565b806338af3eed14610098578063715018a6146100e257806386d1a69f146100ec5780638da5cb5b146100f6575b600080fd5b6100a0610252565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100ea61027c565b005b6100f46103b7565b005b6100fe6105bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101486105e8565b604051808215151515815260200191505060405180910390f35b61016a610646565b6040518082815260200191505060405180910390f35b6101c26004803603602081101561019657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610650565b005b610206600480360360208110156101da57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610773565b005b6102106107fb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6102846105e8565b15156102f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6003544210151515610414576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180610ce36032913960400191505060405180910390fd5b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156104b557600080fd5b505afa1580156104c9573d6000803e3d6000fd5b505050506040513d60208110156104df57600080fd5b8101908080519060200190929190505050905060008111151561054d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610d656023913960400191505060405180910390fd5b6105bc600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108259092919063ffffffff16565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661062a6108f6565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600354905090565b6106586105e8565b15156106cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507feee59a71c694e68368a1cb0d135c448051bbfb12289e6c2223b0ceb100c2321d81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b61077b6105e8565b15156107ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6107f8816108fe565b50565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6108f1838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb905060e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610a44565b505050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515610986576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610d156026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610a638273ffffffffffffffffffffffffffffffffffffffff16610c97565b1515610ad7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e74726163740081525060200191505060405180910390fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083101515610b285780518252602082019150602081019050602083039250610b03565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610b8a576040519150601f19603f3d011682016040523d82523d6000602084013e610b8f565b606091505b5091509150811515610c09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656481525060200191505060405180910390fd5b600081511115610c9157808060200190516020811015610c2857600080fd5b81019080805190602001909291905050501515610c90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610d3b602a913960400191505060405180910390fd5b5b50505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f9150808214158015610cd957506000801b8214155b9250505091905056fe546f6b656e54696d656c6f636b3a2063757272656e742074696d65206973206265666f72652072656c656173652074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564546f6b656e54696d656c6f636b3a206e6f20746f6b656e7320746f2072656c65617365a165627a7a72305820e80c736d9cc7a31ddb7c6011d3a1955fc95354b7254499eb9f0d549446ba12b20029546f6b656e54696d656c6f636b3a2072656c656173652074696d65206973206265666f72652063757272656e742074696d65", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c80638f32d59b116100665780638f32d59b14610140578063b91d400114610162578063dc07065714610180578063f2fde38b146101c4578063fc0c546a1461020857610093565b806338af3eed14610098578063715018a6146100e257806386d1a69f146100ec5780638da5cb5b146100f6575b600080fd5b6100a0610252565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6100ea61027c565b005b6100f46103b7565b005b6100fe6105bf565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6101486105e8565b604051808215151515815260200191505060405180910390f35b61016a610646565b6040518082815260200191505060405180910390f35b6101c26004803603602081101561019657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610650565b005b610206600480360360208110156101da57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610773565b005b6102106107fb565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b6000600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6102846105e8565b15156102f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a360008060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b6003544210151515610414576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180610ce36032913960400191505060405180910390fd5b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b8152600401808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060206040518083038186803b1580156104b557600080fd5b505afa1580156104c9573d6000803e3d6000fd5b505050506040513d60208110156104df57600080fd5b8101908080519060200190929190505050905060008111151561054d576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526023815260200180610d656023913960400191505060405180910390fd5b6105bc600260009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1682600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166108259092919063ffffffff16565b50565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1661062a6108f6565b73ffffffffffffffffffffffffffffffffffffffff1614905090565b6000600354905090565b6106586105e8565b15156106cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055507feee59a71c694e68368a1cb0d135c448051bbfb12289e6c2223b0ceb100c2321d81604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390a150565b61077b6105e8565b15156107ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6107f8816108fe565b50565b6000600160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b6108f1838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb905060e01b8484604051602401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050610a44565b505050565b600033905090565b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614151515610986576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180610d156026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff166000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b610a638273ffffffffffffffffffffffffffffffffffffffff16610c97565b1515610ad7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f5361666545524332303a2063616c6c20746f206e6f6e2d636f6e74726163740081525060200191505060405180910390fd5b600060608373ffffffffffffffffffffffffffffffffffffffff16836040518082805190602001908083835b602083101515610b285780518252602082019150602081019050602083039250610b03565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114610b8a576040519150601f19603f3d011682016040523d82523d6000602084013e610b8f565b606091505b5091509150811515610c09576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c656481525060200191505060405180910390fd5b600081511115610c9157808060200190516020811015610c2857600080fd5b81019080805190602001909291905050501515610c90576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180610d3b602a913960400191505060405180910390fd5b5b50505050565b60008060007fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47060001b9050833f9150808214158015610cd957506000801b8214155b9250505091905056fe546f6b656e54696d656c6f636b3a2063757272656e742074696d65206973206265666f72652072656c656173652074696d654f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573735361666545524332303a204552433230206f7065726174696f6e20646964206e6f742073756363656564546f6b656e54696d656c6f636b3a206e6f20746f6b656e7320746f2072656c65617365a165627a7a72305820e80c736d9cc7a31ddb7c6011d3a1955fc95354b7254499eb9f0d549446ba12b20029", + "devdoc": { + "details": "A token holder contract that will allow a beneficiary to extract the tokens after a given release time. * Useful for simple vesting schedules like \"advisors get all of their tokens after 1 year\". * For a more complete vesting schedule, see {TokenVesting}.", + "methods": { + "beneficiary()": { + "return": "the beneficiary of the tokens." + }, + "isOwner()": { + "details": "Returns true if the caller is the current owner." + }, + "owner()": { + "details": "Returns the address of the current owner." + }, + "releaseTime()": { + "return": "the time when the tokens are released." + }, + "renounceOwnership()": { + "details": "Leaves the contract without owner. It will not be possible to call `onlyOwner` functions anymore. Can only be called by the current owner. * NOTE: Renouncing ownership will leave the contract without an owner, thereby removing any functionality that is only available to the owner." + }, + "token()": { + "return": "the token being held." + }, + "transferOwnership(address)": { + "details": "Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner." + } + } + }, + "userdoc": { + "methods": { + "release()": { + "notice": "Transfers tokens held by timelock to beneficiary." + } + } + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/OutputFacet.json b/echo-js/deployments/localhost/OutputFacet.json new file mode 100644 index 00000000..ab913989 --- /dev/null +++ b/echo-js/deployments/localhost/OutputFacet.json @@ -0,0 +1,448 @@ +{ + "address": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "voucherPosition", + "type": "uint256" + } + ], + "name": "VoucherExecuted", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_destination", + "type": "address" + }, + { + "internalType": "bytes", + "name": "_payload", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "epochIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inputIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "outputIndex", + "type": "uint256" + }, + { + "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": "keccakInHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ], + "internalType": "struct OutputValidityProof", + "name": "_v", + "type": "tuple" + } + ], + "name": "executeVoucher", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_voucher", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_input", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_epoch", + "type": "uint256" + } + ], + "name": "getBitMaskPosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getEpochNoticeLog2Size", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getEpochVoucherLog2Size", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "_log2Size", + "type": "uint256" + } + ], + "name": "getIntraDrivePosition", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getNoticeMetadataLog2Size", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [], + "name": "getNumberOfFinalizedEpochs", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getVoucherMetadataLog2Size", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_encodedNotice", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_epochHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "epochIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inputIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "outputIndex", + "type": "uint256" + }, + { + "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": "keccakInHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ], + "internalType": "struct OutputValidityProof", + "name": "_v", + "type": "tuple" + } + ], + "name": "isValidNoticeProof", + "outputs": [], + "stateMutability": "pure", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "_encodedVoucher", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "_epochHash", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "uint256", + "name": "epochIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "inputIndex", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "outputIndex", + "type": "uint256" + }, + { + "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": "keccakInHashesSiblings", + "type": "bytes32[]" + }, + { + "internalType": "bytes32[]", + "name": "outputHashesInEpochSiblings", + "type": "bytes32[]" + } + ], + "internalType": "struct OutputValidityProof", + "name": "_v", + "type": "tuple" + } + ], + "name": "isValidVoucherProof", + "outputs": [], + "stateMutability": "pure", + "type": "function" + } + ], + "transactionHash": "0x9980a2ee195a304e55ff3e3dfd2ed12cb091da7e8407e0a8b88e5f475b2e03dd", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F", + "transactionIndex": 0, + "gasUsed": "742886", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x38d1f26e745def924024fb46857f0a0e6dfbc20ce571ce7455308c916a3b8a74", + "transactionHash": "0x9980a2ee195a304e55ff3e3dfd2ed12cb091da7e8407e0a8b88e5f475b2e03dd", + "logs": [], + "blockNumber": 27, + "cumulativeGasUsed": "742886", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"voucherPosition\",\"type\":\"uint256\"}],\"name\":\"VoucherExecuted\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_destination\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"_payload\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"epochIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inputIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputIndex\",\"type\":\"uint256\"},{\"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\":\"keccakInHashesSiblings\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashesInEpochSiblings\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct OutputValidityProof\",\"name\":\"_v\",\"type\":\"tuple\"}],\"name\":\"executeVoucher\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_voucher\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_input\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_epoch\",\"type\":\"uint256\"}],\"name\":\"getBitMaskPosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEpochNoticeLog2Size\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEpochVoucherLog2Size\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_log2Size\",\"type\":\"uint256\"}],\"name\":\"getIntraDrivePosition\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNoticeMetadataLog2Size\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getNumberOfFinalizedEpochs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getVoucherMetadataLog2Size\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_encodedNotice\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"_epochHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"epochIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inputIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputIndex\",\"type\":\"uint256\"},{\"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\":\"keccakInHashesSiblings\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashesInEpochSiblings\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct OutputValidityProof\",\"name\":\"_v\",\"type\":\"tuple\"}],\"name\":\"isValidNoticeProof\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"_encodedVoucher\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"_epochHash\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"epochIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"inputIndex\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"outputIndex\",\"type\":\"uint256\"},{\"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\":\"keccakInHashesSiblings\",\"type\":\"bytes32[]\"},{\"internalType\":\"bytes32[]\",\"name\":\"outputHashesInEpochSiblings\",\"type\":\"bytes32[]\"}],\"internalType\":\"struct OutputValidityProof\",\"name\":\"_v\",\"type\":\"tuple\"}],\"name\":\"isValidVoucherProof\",\"outputs\":[],\"stateMutability\":\"pure\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"executeVoucher(address,bytes,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))\":{\"details\":\"vouchers can only be executed once\",\"params\":{\"_destination\":\"address that will execute the payload\",\"_payload\":\"payload to be executed by destination\",\"_v\":\"validity proof for this encoded voucher\"},\"returns\":{\"_0\":\"true if voucher was executed successfully\"}},\"getBitMaskPosition(uint256,uint256,uint256)\":{\"params\":{\"_epoch\":\"which epoch the voucher belongs to\",\"_input\":\"which input, inside the epoch, the voucher belongs to\",\"_voucher\":\"of voucher inside the input\"},\"returns\":{\"_0\":\"position of that voucher on bitmask\"}},\"getIntraDrivePosition(uint256,uint256)\":{\"params\":{\"_index\":\"index of intra memory range\",\"_log2Size\":\"of intra memory range\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"executeVoucher(address,bytes,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))\":{\"notice\":\"executes voucher\"},\"getBitMaskPosition(uint256,uint256,uint256)\":{\"notice\":\"get voucher position on bitmask\"},\"getEpochNoticeLog2Size()\":{\"notice\":\"get log2 size of epoch notice memory range\"},\"getEpochVoucherLog2Size()\":{\"notice\":\"get log2 size of epoch voucher memory range\"},\"getNoticeMetadataLog2Size()\":{\"notice\":\"get log2 size of notice metadata memory range\"},\"getNumberOfFinalizedEpochs()\":{\"notice\":\"get number of finalized epochs\"},\"getVoucherMetadataLog2Size()\":{\"notice\":\"get log2 size of voucher metadata memory range\"},\"isValidNoticeProof(bytes,bytes32,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))\":{\"notice\":\"isValidNoticeProof reverts if the proof is invalid\"},\"isValidVoucherProof(bytes,bytes32,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))\":{\"notice\":\"isValidVoucherProof reverts if the proof is invalid\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/OutputFacet.sol\":\"OutputFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@cartesi/util/contracts/Bitmask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\npragma solidity ^0.8.0;\\n\\n/// @title Bit Mask Library\\n/// @author Stephen Chen\\n/// @notice Implements bit mask with dynamic array\\nlibrary Bitmask {\\n /// @notice Set a bit in the bit mask\\n function setBit(\\n mapping(uint256 => uint256) storage bitmask,\\n uint256 _bit,\\n bool _value\\n ) public {\\n // calculate the number of bits has been store in bitmask now\\n uint256 positionOfMask = uint256(_bit / 256);\\n uint256 positionOfBit = _bit % 256;\\n\\n if (_value) {\\n bitmask[positionOfMask] =\\n bitmask[positionOfMask] |\\n (1 << positionOfBit);\\n } else {\\n bitmask[positionOfMask] =\\n bitmask[positionOfMask] &\\n ~(1 << positionOfBit);\\n }\\n }\\n\\n /// @notice Get a bit in the bit mask\\n function getBit(mapping(uint256 => uint256) storage bitmask, uint256 _bit)\\n public\\n view\\n returns (bool)\\n {\\n // calculate the number of bits has been store in bitmask now\\n uint256 positionOfMask = uint256(_bit / 256);\\n uint256 positionOfBit = _bit % 256;\\n\\n return ((bitmask[positionOfMask] & (1 << positionOfBit)) != 0);\\n }\\n}\\n\",\"keccak256\":\"0xe35cf68672f5844589c0e56f36aa3813ca4ffb882a55a46d15adac7e3cc889bd\",\"license\":\"Apache-2.0\"},\"@cartesi/util/contracts/CartesiMath.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title CartesiMath\\n/// @author Felipe Argento\\npragma solidity ^0.8.0;\\n\\nlibrary CartesiMath {\\n // mapping values are packed as bytes3 each\\n // see test/TestCartesiMath.ts for decimal values\\n bytes constant log2tableTimes1M =\\n hex\\\"0000000F4240182F421E8480236E082771822AD63A2DC6C0305E8532B04834C96736B3C23876D73A187A3B9D4A3D09003E5EA63FA0C540D17741F28843057D440BA745062945F60246DC1047B917488DC7495ABA4A207C4ADF8A4B98544C4B404CF8AA4DA0E64E44434EE3054F7D6D5013B750A61A5134C851BFF05247BD52CC58534DE753CC8D54486954C19C55384255AC75561E50568DE956FB575766B057D00758376F589CFA5900BA5962BC59C3135A21CA5A7EF15ADA945B34BF5B8D805BE4DF5C3AEA5C8FA95CE3265D356C5D86835DD6735E25455E73005EBFAD5F0B525F55F75F9FA25FE85A60302460770860BD0A61023061467F6189FD61CCAE620E98624FBF62902762CFD5630ECD634D12638AA963C7966403DC643F7F647A8264B4E864EEB56527EC6560906598A365D029660724663D9766738566A8F066DDDA6712476746386779AF67ACAF67DF3A6811526842FA68743268A4FC68D55C6905536934E169640A6992CF69C13169EF326A1CD46A4A186A76FF6AA38C6ACFC0\\\";\\n\\n /// @notice Approximates log2 * 1M\\n /// @param _num number to take log2 * 1M of\\n /// @return approximate log2 times 1M\\n function log2ApproxTimes1M(uint256 _num) public pure returns (uint256) {\\n require(_num > 0, \\\"Number cannot be zero\\\");\\n uint256 leading = 0;\\n\\n if (_num == 1) return 0;\\n\\n while (_num > 128) {\\n _num = _num >> 1;\\n leading += 1;\\n }\\n return (leading * uint256(1000000)) + (getLog2TableTimes1M(_num));\\n }\\n\\n /// @notice navigates log2tableTimes1M\\n /// @param _num number to take log2 of\\n /// @return result after table look-up\\n function getLog2TableTimes1M(uint256 _num) public pure returns (uint256) {\\n bytes3 result = 0;\\n for (uint8 i = 0; i < 3; i++) {\\n bytes3 tempResult = log2tableTimes1M[(_num - 1) * 3 + i];\\n result = result | (tempResult >> (i * 8));\\n }\\n\\n return uint256(uint24(result));\\n }\\n\\n /// @notice get floor of log2 of number\\n /// @param _num number to take floor(log2) of\\n /// @return floor(log2) of _num\\n function getLog2Floor(uint256 _num) public pure returns (uint8) {\\n require(_num != 0, \\\"log of zero is undefined\\\");\\n\\n return uint8(255 - clz(_num));\\n }\\n\\n /// @notice checks if a number is Power of 2\\n /// @param _num number to check\\n /// @return true if number is power of 2, false if not\\n function isPowerOf2(uint256 _num) public pure returns (bool) {\\n if (_num == 0) return false;\\n\\n return _num & (_num - 1) == 0;\\n }\\n\\n /// @notice count trailing zeros\\n /// @param _num number you want the ctz of\\n /// @dev this a binary search implementation\\n function ctz(uint256 _num) public pure returns (uint256) {\\n if (_num == 0) return 256;\\n\\n uint256 n = 0;\\n if (_num & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { n = n + 128; _num = _num >> 128; }\\n if (_num & 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF == 0) { n = n + 64; _num = _num >> 64; }\\n if (_num & 0x00000000000000000000000000000000000000000000000000000000FFFFFFFF == 0) { n = n + 32; _num = _num >> 32; }\\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000FFFF == 0) { n = n + 16; _num = _num >> 16; }\\n if (_num & 0x00000000000000000000000000000000000000000000000000000000000000FF == 0) { n = n + 8; _num = _num >> 8; }\\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000000F == 0) { n = n + 4; _num = _num >> 4; }\\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000003 == 0) { n = n + 2; _num = _num >> 2; }\\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000001 == 0) { n = n + 1; }\\n\\n return n;\\n }\\n\\n /// @notice count leading zeros\\n /// @param _num number you want the clz of\\n /// @dev this a binary search implementation\\n function clz(uint256 _num) public pure returns (uint256) {\\n if (_num == 0) return 256;\\n\\n uint256 n = 0;\\n if (_num & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 == 0) { n = n + 128; _num = _num << 128; }\\n if (_num & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 == 0) { n = n + 64; _num = _num << 64; }\\n if (_num & 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 == 0) { n = n + 32; _num = _num << 32; }\\n if (_num & 0xFFFF000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 16; _num = _num << 16; }\\n if (_num & 0xFF00000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 8; _num = _num << 8; }\\n if (_num & 0xF000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 4; _num = _num << 4; }\\n if (_num & 0xC000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 2; _num = _num << 2; }\\n if (_num & 0x8000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 1; }\\n\\n return n;\\n }\\n}\\n\",\"keccak256\":\"0x28b74012e966438edff701decdc5ffd207b3f0244af65fbd7d397050986e58d4\",\"license\":\"Apache-2.0\"},\"@cartesi/util/contracts/Merkle.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Library for Merkle proofs\\npragma solidity ^0.8.0;\\n\\nimport \\\"./CartesiMath.sol\\\";\\n\\nlibrary Merkle {\\n using CartesiMath for uint256;\\n\\n uint128 constant L_WORD_SIZE = 3; // word = 8 bytes, log = 3\\n // number of hashes in EMPTY_TREE_HASHES\\n uint128 constant EMPTY_TREE_SIZE = 1952; // 61*32=1952. 32 bytes per 61 indexes (64 words)\\n\\n // merkle root hashes of trees of zero concatenated\\n // 32 bytes for each root, first one is keccak(0), second one is\\n // keccak(keccack(0), keccak(0)) and so on\\n\\n bytes constant EMPTY_TREE_HASHES =\\n hex\\\"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce4d9470a821fbe90117ec357e30bad9305732fb19ddf54a07dd3e29f440619254ae39ce8537aca75e2eff3e38c98011dfe934e700a0967732fc07b430dd656a233fc9a15f5b4869c872f81087bb6104b7d63e6f9ab47f2c43f3535eae7172aa7f17d2dd614cddaa4d879276b11e0672c9560033d3e8453a1d045339d34ba601b9c37b8b13ca95166fb7af16988a70fcc90f38bf9126fd833da710a47fb37a55e68e7a427fa943d9966b389f4f257173676090c6e95f43e2cb6d65f8758111e30930b0b9deb73e155c59740bacf14a6ff04b64bb8e201a506409c3fe381ca4ea90cd5deac729d0fdaccc441d09d7325f41586ba13c801b7eccae0f95d8f3933efed8b96e5b7f6f459e9cb6a2f41bf276c7b85c10cd4662c04cbbb365434726c0a0c9695393027fb106a8153109ac516288a88b28a93817899460d6310b71cf1e6163e8806fa0d4b197a259e8c3ac28864268159d0ac85f8581ca28fa7d2c0c03eb91e3eee5ca7a3da2b3053c9770db73599fb149f620e3facef95e947c0ee860b72122e31e4bbd2b7c783d79cc30f60c6238651da7f0726f767d22747264fdb046f7549f26cc70ed5e18baeb6c81bb0625cb95bb4019aeecd40774ee87ae29ec517a71f6ee264c5d761379b3d7d617ca83677374b49d10aec50505ac087408ca892b573c267a712a52e1d06421fe276a03efb1889f337201110fdc32a81f8e152499af665835aabfdc6740c7e2c3791a31c3cdc9f5ab962f681b12fc092816a62f27d86025599a41233848702f0cfc0437b445682df51147a632a0a083d2d38b5e13e466a8935afff58bb533b3ef5d27fba63ee6b0fd9e67ff20af9d50deee3f8bf065ec220c1fd4ba57e341261d55997f85d66d32152526736872693d2b437a233e2337b715f6ac9a6a272622fdc2d67fcfe1da3459f8dab4ed7e40a657a54c36766c5e8ac9a88b35b05c34747e6507f6b044ab66180dc76ac1a696de03189593fedc0d0dbbd855c8ead673544899b0960e4a5a7ca43b4ef90afe607de7698caefdc242788f654b57a4fb32a71b335ef6ff9a4cc118b282b53bdd6d6192b7a82c3c5126b9c7e33c8e5a5ac9738b8bd31247fb7402054f97b573e8abb9faad219f4fd085aceaa7f542d787ee4196d365f3cc566e7bbcfbfd451230c48d804c017d21e2d8fa914e2559bb72bf0ab78c8ab92f00ef0d0d576eccdd486b64138a4172674857e543d1d5b639058dd908186597e366ad5f3d9c7ceaff44d04d1550b8d33abc751df07437834ba5acb32328a396994aebb3c40f759c2d6d7a3cb5377e55d5d218ef5a296dda8ddc355f3f50c3d0b660a51dfa4d98a6a5a33564556cf83c1373a814641d6a1dcef97b883fee61bb84fe60a3409340217e629cc7e4dcc93b85d8820921ff5826148b60e6939acd7838e1d7f20562bff8ee4b5ec4a05ad997a57b9796fdcb2eda87883c2640b072b140b946bfdf6575cacc066fdae04f6951e63624cbd316a677cad529bbe4e97b9144e4bc06c4afd1de55dd3e1175f90423847a230d34dfb71ed56f2965a7f6c72e6aa33c24c303fd67745d632656c5ef90bec80f4f5d1daa251988826cef375c81c36bf457e09687056f924677cb0bccf98dff81e014ce25f2d132497923e267363963cdf4302c5049d63131dc03fd95f65d8b6aa5934f817252c028c90f56d413b9d5d10d89790707dae2fabb249f649929927c21dd71e3f656826de5451c5da375aadecbd59d5ebf3a31fae65ac1b316a1611f1b276b26530f58d7247df459ce1f86db1d734f6f811932f042cee45d0e455306d01081bc3384f82c5fb2aacaa19d89cdfa46cc916eac61121475ba2e6191b4feecbe1789717021a158ace5d06744b40f551076b67cd63af60007f8c99876e1424883a45ec49d497ddaf808a5521ca74a999ab0b3c7aa9c80f85e93977ec61ce68b20307a1a81f71ca645b568fcd319ccbb5f651e87b707d37c39e15f945ea69e2f7c7d2ccc85b7e654c07e96f0636ae4044fe0e38590b431795ad0f8647bdd613713ada493cc17efd313206380e6a685b8198475bbd021c6e9d94daab2214947127506073e44d5408ba166c512a0b86805d07f5a44d3c41706be2bc15e712e55805248b92e8677d90f6d284d1d6ffaff2c430657042a0e82624fa3717b06cc0a6fd12230ea586dae83019fb9e06034ed2803c98d554b93c9a52348cafff75c40174a91f9ae6b8647854a156029f0b88b83316663ce574a4978277bb6bb27a31085634b6ec78864b6d8201c7e93903d75815067e378289a3d072ae172dafa6a452470f8d645bebfad9779594fc0784bb764a22e3a8181d93db7bf97893c414217a618ccb14caa9e92e8c61673afc9583662e812adba1f87a9c68202d60e909efab43c42c0cb00695fc7f1ffe67c75ca894c3c51e1e5e731360199e600f6ced9a87b2a6a87e70bf251bb5075ab222138288164b2eda727515ea7de12e2496d4fe42ea8d1a120c03cf9c50622c2afe4acb0dad98fd62d07ab4e828a94495f6d1ab973982c7ccbe6c1fae02788e4422ae22282fa49cbdb04ba54a7a238c6fc41187451383460762c06d1c8a72b9cd718866ad4b689e10c9a8c38fe5ef045bd785b01e980fc82c7e3532ce81876b778dd9f1ceeba4478e86411fb6fdd790683916ca832592485093644e8760cd7b4c01dba1ccc82b661bf13f0e3f34acd6b88\\\";\\n\\n /// @notice Gets merkle root hash of drive with a replacement\\n /// @param _position position of _drive\\n /// @param _logSizeOfReplacement log2 of size the replacement\\n /// @param _logSizeOfFullDrive log2 of size the full drive, which can be the entire machine\\n /// @param _replacement hash of the replacement\\n /// @param siblings of replacement that merkle root can be calculated\\n function getRootAfterReplacementInDrive(\\n uint256 _position,\\n uint256 _logSizeOfReplacement,\\n uint256 _logSizeOfFullDrive,\\n bytes32 _replacement,\\n bytes32[] calldata siblings\\n ) public pure returns (bytes32) {\\n require(\\n _logSizeOfFullDrive >= _logSizeOfReplacement &&\\n _logSizeOfReplacement >= 3 &&\\n _logSizeOfFullDrive <= 64,\\n \\\"3 <= logSizeOfReplacement <= logSizeOfFullDrive <= 64\\\"\\n );\\n\\n uint256 size = 1 << _logSizeOfReplacement;\\n\\n require(((size - 1) & _position) == 0, \\\"Position is not aligned\\\");\\n require(\\n siblings.length == _logSizeOfFullDrive - _logSizeOfReplacement,\\n \\\"Proof length does not match\\\"\\n );\\n\\n for (uint256 i; i < siblings.length; i++) {\\n if ((_position & (size << i)) == 0) {\\n _replacement = keccak256(\\n abi.encodePacked(_replacement, siblings[i])\\n );\\n } else {\\n _replacement = keccak256(\\n abi.encodePacked(siblings[i], _replacement)\\n );\\n }\\n }\\n\\n return _replacement;\\n }\\n\\n /// @notice Gets precomputed hash of zero in empty tree hashes\\n /// @param _index of hash wanted\\n /// @dev first index is keccak(0), second index is keccak(keccak(0), keccak(0))\\n function getEmptyTreeHashAtIndex(uint256 _index)\\n public\\n pure\\n returns (bytes32)\\n {\\n uint256 start = _index * 32;\\n require(EMPTY_TREE_SIZE >= start + 32, \\\"index out of bounds\\\");\\n bytes32 hashedZeros;\\n bytes memory zeroTree = EMPTY_TREE_HASHES;\\n\\n // first word is length, then skip index words\\n assembly {\\n hashedZeros := mload(add(add(zeroTree, 0x20), start))\\n }\\n return hashedZeros;\\n }\\n\\n /// @notice get merkle root of generic array of bytes\\n /// @param _data array of bytes to be merklelized\\n /// @param _log2Size log2 of total size of the drive\\n /// @dev _data is padded with zeroes until is multiple of 8\\n /// @dev root is completed with zero tree until log2size is complete\\n /// @dev hashes are taken word by word (8 bytes by 8 bytes)\\n function getMerkleRootFromBytes(bytes calldata _data, uint256 _log2Size)\\n public\\n pure\\n returns (bytes32)\\n {\\n require(_log2Size >= 3 && _log2Size <= 64, \\\"range of log2Size: [3,64]\\\");\\n\\n // if _data is empty return pristine drive of size log2size\\n if (_data.length == 0) return getEmptyTreeHashAtIndex(_log2Size - 3);\\n\\n // total size of the drive in words\\n uint256 size = 1 << (_log2Size - 3);\\n require(\\n size << L_WORD_SIZE >= _data.length,\\n \\\"data is bigger than drive\\\"\\n );\\n // the stack depth is log2(_data.length / 8) + 2\\n uint256 stack_depth = 2 +\\n ((_data.length) >> L_WORD_SIZE).getLog2Floor();\\n bytes32[] memory stack = new bytes32[](stack_depth);\\n\\n uint256 numOfHashes; // total number of hashes on stack (counting levels)\\n uint256 stackLength; // total length of stack\\n uint256 numOfJoins; // number of hashes of the same level on stack\\n uint256 topStackLevel; // hash level of the top of the stack\\n\\n while (numOfHashes < size) {\\n if ((numOfHashes << L_WORD_SIZE) < _data.length) {\\n // we still have words to hash\\n stack[stackLength] = getHashOfWordAtIndex(_data, numOfHashes);\\n numOfHashes++;\\n\\n numOfJoins = numOfHashes;\\n } else {\\n // since padding happens in hashOfWordAtIndex function\\n // we only need to complete the stack with pre-computed\\n // hash(0), hash(hash(0),hash(0)) and so on\\n topStackLevel = numOfHashes.ctz();\\n\\n stack[stackLength] = getEmptyTreeHashAtIndex(topStackLevel);\\n\\n //Empty Tree Hash summarizes many hashes\\n numOfHashes = numOfHashes + (1 << topStackLevel);\\n numOfJoins = numOfHashes >> topStackLevel;\\n }\\n\\n stackLength++;\\n\\n // while there are joins, hash top of stack together\\n while (numOfJoins & 1 == 0) {\\n bytes32 h2 = stack[stackLength - 1];\\n bytes32 h1 = stack[stackLength - 2];\\n\\n stack[stackLength - 2] = keccak256(abi.encodePacked(h1, h2));\\n stackLength = stackLength - 1; // remove hashes from stack\\n\\n numOfJoins = numOfJoins >> 1;\\n }\\n }\\n require(stackLength == 1, \\\"stack error\\\");\\n\\n return stack[0];\\n }\\n\\n /// @notice Get the hash of a word in an array of bytes\\n /// @param _data array of bytes\\n /// @param _wordIndex index of word inside the bytes to get the hash of\\n /// @dev if word is incomplete (< 8 bytes) it gets padded with zeroes\\n function getHashOfWordAtIndex(bytes calldata _data, uint256 _wordIndex)\\n public\\n pure\\n returns (bytes32)\\n {\\n uint256 start = _wordIndex << L_WORD_SIZE;\\n uint256 end = start + (1 << L_WORD_SIZE);\\n\\n // TODO: in .lua this just returns zero, but this might be more consistent\\n require(start <= _data.length, \\\"word out of bounds\\\");\\n\\n if (end <= _data.length) {\\n return keccak256(abi.encodePacked(_data[start:end]));\\n }\\n\\n // word is incomplete\\n // fill paddedSlice with incomplete words - the rest is going to be bytes(0)\\n bytes memory paddedSlice = new bytes(8);\\n uint256 remaining = _data.length - start;\\n\\n for (uint256 i; i < remaining; i++) {\\n paddedSlice[i] = _data[start + i];\\n }\\n\\n return keccak256(paddedSlice);\\n }\\n\\n /// @notice Calculate the root of Merkle tree from an array of power of 2 elements\\n /// @param hashes The array containing power of 2 elements\\n /// @return byte32 the root hash being calculated\\n function calculateRootFromPowerOfTwo(bytes32[] memory hashes)\\n public\\n pure\\n returns (bytes32)\\n {\\n // revert when the input is not of power of 2\\n require((hashes.length).isPowerOf2(), \\\"array len not power of 2\\\");\\n\\n if (hashes.length == 1) {\\n return hashes[0];\\n } else {\\n bytes32[] memory newHashes = new bytes32[](hashes.length >> 1);\\n\\n for (uint256 i; i < hashes.length; i += 2) {\\n newHashes[i >> 1] = keccak256(\\n abi.encodePacked(hashes[i], hashes[i + 1])\\n );\\n }\\n\\n return calculateRootFromPowerOfTwo(newHashes);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xe9896db44cc4dab335a3e776c629186824823d316d902b2efecb4b0a3e3dfdb7\",\"license\":\"Apache-2.0\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/OutputFacet.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output facet\\npragma solidity ^0.8.0;\\n\\nimport {Bitmask} from \\\"@cartesi/util/contracts/Bitmask.sol\\\";\\nimport {Merkle} from \\\"@cartesi/util/contracts/Merkle.sol\\\";\\n\\nimport {IOutput, OutputValidityProof} from \\\"../interfaces/IOutput.sol\\\";\\n\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\ncontract OutputFacet is IOutput {\\n using LibOutput for LibOutput.DiamondStorage;\\n\\n // Here we only need 248 bits as keys in the mapping, but we use 256 bits for gas optimization\\n using Bitmask for mapping(uint256 => uint256);\\n\\n uint256 constant KECCAK_LOG2_SIZE = 5; // keccak log2 size\\n\\n // max size of voucher metadata memory range 32 * (2^16) bytes\\n uint256 constant VOUCHER_METADATA_LOG2_SIZE = 21;\\n // max size of epoch voucher memory range 32 * (2^32) bytes\\n uint256 constant EPOCH_VOUCHER_LOG2_SIZE = 37;\\n\\n // max size of notice metadata memory range 32 * (2^16) bytes\\n uint256 constant NOTICE_METADATA_LOG2_SIZE = 21;\\n // max size of epoch notice memory range 32 * (2^32) bytes\\n uint256 constant EPOCH_NOTICE_LOG2_SIZE = 37;\\n\\n /// @notice functions modified by noReentrancy are not subject to recursion\\n modifier noReentrancy() {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n require(!outputDS.lock, \\\"reentrancy not allowed\\\");\\n outputDS.lock = true;\\n _;\\n outputDS.lock = false;\\n }\\n\\n /// @notice executes voucher\\n /// @param _destination address that will execute the payload\\n /// @param _payload payload to be executed by destination\\n /// @param _v validity proof for this encoded voucher\\n /// @return true if voucher was executed successfully\\n /// @dev vouchers can only be executed once\\n function executeVoucher(\\n address _destination,\\n bytes calldata _payload,\\n OutputValidityProof calldata _v\\n ) public override noReentrancy returns (bool) {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n\\n // avoid a malicious DApp developer from draining the Fee Manager's bank account\\n require(_destination != address(feeManagerDS.bank), \\\"bad destination\\\");\\n\\n bytes memory encodedVoucher = abi.encode(_destination, _payload);\\n\\n // check if validity proof matches the voucher provided\\n isValidVoucherProof(\\n encodedVoucher,\\n outputDS.epochHashes[_v.epochIndex],\\n _v\\n );\\n\\n uint256 voucherPosition = getBitMaskPosition(\\n _v.outputIndex,\\n _v.inputIndex,\\n _v.epochIndex\\n );\\n\\n // check if voucher has been executed\\n require(\\n !outputDS.voucherBitmask.getBit(voucherPosition),\\n \\\"re-execution not allowed\\\"\\n );\\n\\n // execute voucher\\n (bool succ, ) = _destination.call(_payload);\\n\\n // if properly executed, mark it as executed and emit event\\n if (succ) {\\n outputDS.voucherBitmask.setBit(voucherPosition, true);\\n emit VoucherExecuted(voucherPosition);\\n }\\n\\n return succ;\\n }\\n\\n /// @notice isValidProof reverts if the proof is invalid\\n /// @dev _outputsEpochRootHash must be _v.vouchersEpochRootHash or\\n /// or _v.noticesEpochRootHash\\n function isValidProof(\\n bytes memory _encodedOutput,\\n bytes32 _epochHash,\\n bytes32 _outputsEpochRootHash,\\n uint256 _outputEpochLog2Size,\\n uint256 _outputHashesLog2Size,\\n OutputValidityProof calldata _v\\n ) internal pure {\\n // prove that outputs hash is represented in a finalized epoch\\n require(\\n keccak256(\\n abi.encodePacked(\\n _v.vouchersEpochRootHash,\\n _v.noticesEpochRootHash,\\n _v.machineStateHash\\n )\\n ) == _epochHash,\\n \\\"epochHash incorrect\\\"\\n );\\n\\n // prove that output metadata memory range is contained in epoch's output memory range\\n require(\\n Merkle.getRootAfterReplacementInDrive(\\n getIntraDrivePosition(_v.inputIndex, KECCAK_LOG2_SIZE),\\n KECCAK_LOG2_SIZE,\\n _outputEpochLog2Size,\\n keccak256(abi.encodePacked(_v.outputHashesRootHash)),\\n _v.outputHashesInEpochSiblings\\n ) == _outputsEpochRootHash,\\n \\\"outputsEpochRootHash incorrect\\\"\\n );\\n\\n // The hash of the output is converted to bytes (abi.encode) and\\n // treated as data. The metadata output memory range stores that data while\\n // being indifferent to its contents. To prove that the received\\n // output is contained in the metadata output memory range we need to\\n // prove that x, where:\\n // x = keccak(\\n // keccak(\\n // keccak(hashOfOutput[0:7]),\\n // keccak(hashOfOutput[8:15])\\n // ),\\n // keccak(\\n // keccak(hashOfOutput[16:23]),\\n // keccak(hashOfOutput[24:31])\\n // )\\n // )\\n // is contained in it. We can't simply use hashOfOutput because the\\n // log2size of the leaf is three (8 bytes) not five (32 bytes)\\n bytes32 merkleRootOfHashOfOutput = Merkle.getMerkleRootFromBytes(\\n abi.encodePacked(keccak256(_encodedOutput)),\\n KECCAK_LOG2_SIZE\\n );\\n\\n // prove that merkle root hash of bytes(hashOfOutput) is contained\\n // in the output metadata array memory range\\n require(\\n Merkle.getRootAfterReplacementInDrive(\\n getIntraDrivePosition(_v.outputIndex, KECCAK_LOG2_SIZE),\\n KECCAK_LOG2_SIZE,\\n _outputHashesLog2Size,\\n merkleRootOfHashOfOutput,\\n _v.keccakInHashesSiblings\\n ) == _v.outputHashesRootHash,\\n \\\"outputHashesRootHash incorrect\\\"\\n );\\n }\\n\\n /// @notice isValidVoucherProof reverts if the proof is invalid\\n function isValidVoucherProof(\\n bytes memory _encodedVoucher,\\n bytes32 _epochHash,\\n OutputValidityProof calldata _v\\n ) public pure {\\n isValidProof(\\n _encodedVoucher,\\n _epochHash,\\n _v.vouchersEpochRootHash,\\n EPOCH_VOUCHER_LOG2_SIZE,\\n VOUCHER_METADATA_LOG2_SIZE,\\n _v\\n );\\n }\\n\\n /// @notice isValidNoticeProof reverts if the proof is invalid\\n function isValidNoticeProof(\\n bytes memory _encodedNotice,\\n bytes32 _epochHash,\\n OutputValidityProof calldata _v\\n ) public pure {\\n isValidProof(\\n _encodedNotice,\\n _epochHash,\\n _v.noticesEpochRootHash,\\n EPOCH_NOTICE_LOG2_SIZE,\\n NOTICE_METADATA_LOG2_SIZE,\\n _v\\n );\\n }\\n\\n /// @notice get voucher position on bitmask\\n /// @param _voucher of voucher inside the input\\n /// @param _input which input, inside the epoch, the voucher belongs to\\n /// @param _epoch which epoch the voucher belongs to\\n /// @return position of that voucher on bitmask\\n function getBitMaskPosition(\\n uint256 _voucher,\\n uint256 _input,\\n uint256 _epoch\\n ) public pure returns (uint256) {\\n // voucher * 2 ** 128 + input * 2 ** 64 + epoch\\n // this can't overflow because its impossible to have > 2**128 vouchers\\n return (((_voucher << 128) | (_input << 64)) | _epoch);\\n }\\n\\n /// @notice returns the position of a intra memory range on a memory range\\n // with contents with the same size\\n /// @param _index index of intra memory range\\n /// @param _log2Size of intra memory range\\n function getIntraDrivePosition(uint256 _index, uint256 _log2Size)\\n public\\n pure\\n returns (uint256)\\n {\\n return (_index << _log2Size);\\n }\\n\\n /// @notice get number of finalized epochs\\n function getNumberOfFinalizedEpochs()\\n public\\n view\\n override\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n return outputDS.getNumberOfFinalizedEpochs();\\n }\\n\\n /// @notice get log2 size of voucher metadata memory range\\n function getVoucherMetadataLog2Size()\\n public\\n pure\\n override\\n returns (uint256)\\n {\\n return VOUCHER_METADATA_LOG2_SIZE;\\n }\\n\\n /// @notice get log2 size of epoch voucher memory range\\n function getEpochVoucherLog2Size() public pure override returns (uint256) {\\n return EPOCH_VOUCHER_LOG2_SIZE;\\n }\\n\\n /// @notice get log2 size of notice metadata memory range\\n function getNoticeMetadataLog2Size()\\n public\\n pure\\n override\\n returns (uint256)\\n {\\n return NOTICE_METADATA_LOG2_SIZE;\\n }\\n\\n /// @notice get log2 size of epoch notice memory range\\n function getEpochNoticeLog2Size() public pure override returns (uint256) {\\n return EPOCH_NOTICE_LOG2_SIZE;\\n }\\n}\\n\",\"keccak256\":\"0x58671cc25ce982551e78e4d6c87de5592ccc691d6a4158ff71c5c004ba76f69f\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IOutput.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output interface\\npragma solidity >=0.7.0;\\n\\n/// @param epochIndex which epoch the output belongs to\\n/// @param inputIndex which input, inside the epoch, the output belongs to\\n/// @param outputIndex index of output inside the input\\n/// @param outputHashesRootHash merkle root of all epoch's output metadata hashes\\n/// @param vouchersEpochRootHash merkle root of all epoch's voucher metadata hashes\\n/// @param noticesEpochRootHash merkle root of all epoch's notice metadata hashes\\n/// @param machineStateHash hash of the machine state claimed this epoch\\n/// @param keccakInHashesSiblings proof that this output metadata is in metadata memory range\\n/// @param outputHashesInEpochSiblings proof that this output metadata is in epoch's output memory range\\nstruct OutputValidityProof {\\n uint256 epochIndex;\\n uint256 inputIndex;\\n uint256 outputIndex;\\n bytes32 outputHashesRootHash;\\n bytes32 vouchersEpochRootHash;\\n bytes32 noticesEpochRootHash;\\n bytes32 machineStateHash;\\n bytes32[] keccakInHashesSiblings;\\n bytes32[] outputHashesInEpochSiblings;\\n}\\n\\ninterface IOutput {\\n /// @notice executes voucher\\n /// @param _destination address that will execute the payload\\n /// @param _payload payload to be executed by destination\\n /// @param _v validity proof for this encoded voucher\\n /// @return true if voucher was executed successfully\\n /// @dev vouchers can only be executed once\\n function executeVoucher(\\n address _destination,\\n bytes calldata _payload,\\n OutputValidityProof calldata _v\\n ) external returns (bool);\\n\\n /// @notice get number of finalized epochs\\n function getNumberOfFinalizedEpochs() external view returns (uint256);\\n\\n /// @notice get log2 size of voucher metadata memory range\\n function getVoucherMetadataLog2Size() external pure returns (uint256);\\n\\n /// @notice get log2 size of epoch voucher memory range\\n function getEpochVoucherLog2Size() external pure returns (uint256);\\n\\n /// @notice get log2 size of notice metadata memory range\\n function getNoticeMetadataLog2Size() external pure returns (uint256);\\n\\n /// @notice get log2 size of epoch notice memory range\\n function getEpochNoticeLog2Size() external pure returns (uint256);\\n\\n event VoucherExecuted(uint256 voucherPosition);\\n}\\n\",\"keccak256\":\"0x79a74b11ae72d4b8eea3c977f3f139b4b976c1a09029968e7c5d326c65286a3e\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610c7b806100206000396000f3fe608060405234801561001057600080fd5b506004361061009e5760003560e01c80638021be81116100665780638021be811461013557806383552b4d1461013c578063a238203614610163578063a981588a14610135578063f3af7efd1461016357600080fd5b806310517cfc146100a35780633ad58a27146100c85780633c0d9958146100dd5780635e439a0c146100ff5780636190d81e14610112575b600080fd5b6100b56100b1366004610886565b1b90565b6040519081526020015b60405180910390f35b6100db6100d63660046108d7565b61016a565b005b6100b56100eb3660046109b6565b608083901b604083901b1781179392505050565b6100db61010d3660046108d7565b610183565b6101256101203660046109e2565b610197565b60405190151581526020016100bf565b60156100b5565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea567546100b5565b60256100b5565b61017e83838360a00135602560158661055c565b505050565b61017e83838360800135602560158661055c565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea568546000907f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5669060ff161561022c5760405162461bcd60e51b81526020600482015260166024820152751c99595b9d1c985b98de481b9bdd08185b1b1bddd95960521b60448201526064015b60405180910390fd5b60028101805460ff1916600117905560006102647f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea56690565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc75549091507f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc73906001600160a01b03908116908916036102f85760405162461bcd60e51b815260206004820152600f60248201526e3130b2103232b9ba34b730ba34b7b760891b6044820152606401610223565b600088888860405160200161030f93929190610a98565b604051602081830303815290604052905061034e818460010188600001358154811061033d5761033d610ad8565b906000526020600020015488610183565b60006020870135604090811b9088013560801b178735176040516303fbaf7360e01b8152600481018690526024810182905290915073e7f1725E7734CE288F8367e1Bb143E90bb3F0512906303fbaf7390604401602060405180830381865af41580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190610aee565b156104305760405162461bcd60e51b815260206004820152601860248201527f72652d657865637574696f6e206e6f7420616c6c6f77656400000000000000006044820152606401610223565b60008a6001600160a01b03168a8a60405161044c929190610b17565b6000604051808303816000865af19150503d8060008114610489576040519150601f19603f3d011682016040523d82523d6000602084013e61048e565b606091505b505090508015610543576040516306449da160e41b815260048101869052602481018390526001604482015273e7f1725E7734CE288F8367e1Bb143E90bb3F051290636449da109060640160006040518083038186803b1580156104f157600080fd5b505af4158015610505573d6000803e3d6000fd5b505050507f0eb7ee080f865f1cadc4f54daf58cc3b8879e888832867d13351edcec0fbdc548260405161053a91815260200190565b60405180910390a15b955050505050600201805460ff19169055949350505050565b60408051608080840135602083015260a08401359282019290925260c0830135606082015286910160405160208183030381529060405280519060200120146105dd5760405162461bcd60e51b8152602060048201526013602482015272195c1bd8da12185cda081a5b98dbdc9c9958dd606a1b6044820152606401610223565b8373Cf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc96379de4601602084013560051b600587866060013560405160200161061a91815260200190565b60408051601f198184030181529190528051602090910120610640610100890189610b27565b6040518763ffffffff1660e01b815260040161066196959493929190610b78565b602060405180830381865af415801561067e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a29190610bcf565b146106ef5760405162461bcd60e51b815260206004820152601e60248201527f6f75747075747345706f6368526f6f744861736820696e636f727265637400006044820152606401610223565b600073Cf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc963c84583a1888051906020012060405160200161072591815260200190565b60405160208183030381529060405260056040518363ffffffff1660e01b8152600401610753929190610be8565b602060405180830381865af4158015610770573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107949190610bcf565b9050606082013573Cf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc96379de4601604085013560051b600587866107ce60e08a018a610b27565b6040518763ffffffff1660e01b81526004016107ef96959493929190610b78565b602060405180830381865af415801561080c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108309190610bcf565b1461087d5760405162461bcd60e51b815260206004820152601e60248201527f6f7574707574486173686573526f6f744861736820696e636f727265637400006044820152606401610223565b50505050505050565b6000806040838503121561089957600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600061012082840312156108d157600080fd5b50919050565b6000806000606084860312156108ec57600080fd5b833567ffffffffffffffff8082111561090457600080fd5b818601915086601f83011261091857600080fd5b81358181111561092a5761092a6108a8565b604051601f8201601f19908116603f01168101908382118183101715610952576109526108a8565b8160405282815289602084870101111561096b57600080fd5b8260208601602083013760006020848301015280975050505060208601359350604086013591508082111561099f57600080fd5b506109ac868287016108be565b9150509250925092565b6000806000606084860312156109cb57600080fd5b505081359360208301359350604090920135919050565b600080600080606085870312156109f857600080fd5b84356001600160a01b0381168114610a0f57600080fd5b9350602085013567ffffffffffffffff80821115610a2c57600080fd5b818701915087601f830112610a4057600080fd5b813581811115610a4f57600080fd5b886020828501011115610a6157600080fd5b602083019550809450506040870135915080821115610a7f57600080fd5b50610a8c878288016108be565b91505092959194509250565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610b0057600080fd5b81518015158114610b1057600080fd5b9392505050565b8183823760009101908152919050565b6000808335601e19843603018112610b3e57600080fd5b83018035915067ffffffffffffffff821115610b5957600080fd5b6020019150600581901b3603821315610b7157600080fd5b9250929050565b86815285602082015284604082015283606082015260a060808201528160a0820152600060018060fb1b03831115610baf57600080fd5b8260051b808560c08501376000920160c001918252509695505050505050565b600060208284031215610be157600080fd5b5051919050565b604081526000835180604084015260005b81811015610c165760208187018101516060868401015201610bf9565b81811115610c28576000606083860101525b50602083019390935250601f91909101601f19160160600191905056fea2646970667358221220466e987a6ad69c9b9648327f0c965f4c05297bb68be7c1491af5e8f2fc075ca064736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061009e5760003560e01c80638021be81116100665780638021be811461013557806383552b4d1461013c578063a238203614610163578063a981588a14610135578063f3af7efd1461016357600080fd5b806310517cfc146100a35780633ad58a27146100c85780633c0d9958146100dd5780635e439a0c146100ff5780636190d81e14610112575b600080fd5b6100b56100b1366004610886565b1b90565b6040519081526020015b60405180910390f35b6100db6100d63660046108d7565b61016a565b005b6100b56100eb3660046109b6565b608083901b604083901b1781179392505050565b6100db61010d3660046108d7565b610183565b6101256101203660046109e2565b610197565b60405190151581526020016100bf565b60156100b5565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea567546100b5565b60256100b5565b61017e83838360a00135602560158661055c565b505050565b61017e83838360800135602560158661055c565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea568546000907f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5669060ff161561022c5760405162461bcd60e51b81526020600482015260166024820152751c99595b9d1c985b98de481b9bdd08185b1b1bddd95960521b60448201526064015b60405180910390fd5b60028101805460ff1916600117905560006102647f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea56690565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc75549091507f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc73906001600160a01b03908116908916036102f85760405162461bcd60e51b815260206004820152600f60248201526e3130b2103232b9ba34b730ba34b7b760891b6044820152606401610223565b600088888860405160200161030f93929190610a98565b604051602081830303815290604052905061034e818460010188600001358154811061033d5761033d610ad8565b906000526020600020015488610183565b60006020870135604090811b9088013560801b178735176040516303fbaf7360e01b8152600481018690526024810182905290915073__$f57eb21c11c6dae369da3ca36f4f48eb77$__906303fbaf7390604401602060405180830381865af41580156103bf573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103e39190610aee565b156104305760405162461bcd60e51b815260206004820152601860248201527f72652d657865637574696f6e206e6f7420616c6c6f77656400000000000000006044820152606401610223565b60008a6001600160a01b03168a8a60405161044c929190610b17565b6000604051808303816000865af19150503d8060008114610489576040519150601f19603f3d011682016040523d82523d6000602084013e61048e565b606091505b505090508015610543576040516306449da160e41b815260048101869052602481018390526001604482015273__$f57eb21c11c6dae369da3ca36f4f48eb77$__90636449da109060640160006040518083038186803b1580156104f157600080fd5b505af4158015610505573d6000803e3d6000fd5b505050507f0eb7ee080f865f1cadc4f54daf58cc3b8879e888832867d13351edcec0fbdc548260405161053a91815260200190565b60405180910390a15b955050505050600201805460ff19169055949350505050565b60408051608080840135602083015260a08401359282019290925260c0830135606082015286910160405160208183030381529060405280519060200120146105dd5760405162461bcd60e51b8152602060048201526013602482015272195c1bd8da12185cda081a5b98dbdc9c9958dd606a1b6044820152606401610223565b8373__$c7dbd794b8c7b5c2028db781007df1176e$__6379de4601602084013560051b600587866060013560405160200161061a91815260200190565b60408051601f198184030181529190528051602090910120610640610100890189610b27565b6040518763ffffffff1660e01b815260040161066196959493929190610b78565b602060405180830381865af415801561067e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106a29190610bcf565b146106ef5760405162461bcd60e51b815260206004820152601e60248201527f6f75747075747345706f6368526f6f744861736820696e636f727265637400006044820152606401610223565b600073__$c7dbd794b8c7b5c2028db781007df1176e$__63c84583a1888051906020012060405160200161072591815260200190565b60405160208183030381529060405260056040518363ffffffff1660e01b8152600401610753929190610be8565b602060405180830381865af4158015610770573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107949190610bcf565b9050606082013573__$c7dbd794b8c7b5c2028db781007df1176e$__6379de4601604085013560051b600587866107ce60e08a018a610b27565b6040518763ffffffff1660e01b81526004016107ef96959493929190610b78565b602060405180830381865af415801561080c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108309190610bcf565b1461087d5760405162461bcd60e51b815260206004820152601e60248201527f6f7574707574486173686573526f6f744861736820696e636f727265637400006044820152606401610223565b50505050505050565b6000806040838503121561089957600080fd5b50508035926020909101359150565b634e487b7160e01b600052604160045260246000fd5b600061012082840312156108d157600080fd5b50919050565b6000806000606084860312156108ec57600080fd5b833567ffffffffffffffff8082111561090457600080fd5b818601915086601f83011261091857600080fd5b81358181111561092a5761092a6108a8565b604051601f8201601f19908116603f01168101908382118183101715610952576109526108a8565b8160405282815289602084870101111561096b57600080fd5b8260208601602083013760006020848301015280975050505060208601359350604086013591508082111561099f57600080fd5b506109ac868287016108be565b9150509250925092565b6000806000606084860312156109cb57600080fd5b505081359360208301359350604090920135919050565b600080600080606085870312156109f857600080fd5b84356001600160a01b0381168114610a0f57600080fd5b9350602085013567ffffffffffffffff80821115610a2c57600080fd5b818701915087601f830112610a4057600080fd5b813581811115610a4f57600080fd5b886020828501011115610a6157600080fd5b602083019550809450506040870135915080821115610a7f57600080fd5b50610a8c878288016108be565b91505092959194509250565b6001600160a01b03841681526040602082018190528101829052818360608301376000818301606090810191909152601f909201601f1916010192915050565b634e487b7160e01b600052603260045260246000fd5b600060208284031215610b0057600080fd5b81518015158114610b1057600080fd5b9392505050565b8183823760009101908152919050565b6000808335601e19843603018112610b3e57600080fd5b83018035915067ffffffffffffffff821115610b5957600080fd5b6020019150600581901b3603821315610b7157600080fd5b9250929050565b86815285602082015284604082015283606082015260a060808201528160a0820152600060018060fb1b03831115610baf57600080fd5b8260051b808560c08501376000920160c001918252509695505050505050565b600060208284031215610be157600080fd5b5051919050565b604081526000835180604084015260005b81811015610c165760208187018101516060868401015201610bf9565b81811115610c28576000606083860101525b50602083019390935250601f91909101601f19160160600191905056fea2646970667358221220466e987a6ad69c9b9648327f0c965f4c05297bb68be7c1491af5e8f2fc075ca064736f6c634300080d0033", + "libraries": { + "Bitmask": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512", + "Merkle": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9" + }, + "devdoc": { + "kind": "dev", + "methods": { + "executeVoucher(address,bytes,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))": { + "details": "vouchers can only be executed once", + "params": { + "_destination": "address that will execute the payload", + "_payload": "payload to be executed by destination", + "_v": "validity proof for this encoded voucher" + }, + "returns": { + "_0": "true if voucher was executed successfully" + } + }, + "getBitMaskPosition(uint256,uint256,uint256)": { + "params": { + "_epoch": "which epoch the voucher belongs to", + "_input": "which input, inside the epoch, the voucher belongs to", + "_voucher": "of voucher inside the input" + }, + "returns": { + "_0": "position of that voucher on bitmask" + } + }, + "getIntraDrivePosition(uint256,uint256)": { + "params": { + "_index": "index of intra memory range", + "_log2Size": "of intra memory range" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "executeVoucher(address,bytes,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))": { + "notice": "executes voucher" + }, + "getBitMaskPosition(uint256,uint256,uint256)": { + "notice": "get voucher position on bitmask" + }, + "getEpochNoticeLog2Size()": { + "notice": "get log2 size of epoch notice memory range" + }, + "getEpochVoucherLog2Size()": { + "notice": "get log2 size of epoch voucher memory range" + }, + "getNoticeMetadataLog2Size()": { + "notice": "get log2 size of notice metadata memory range" + }, + "getNumberOfFinalizedEpochs()": { + "notice": "get number of finalized epochs" + }, + "getVoucherMetadataLog2Size()": { + "notice": "get log2 size of voucher metadata memory range" + }, + "isValidNoticeProof(bytes,bytes32,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))": { + "notice": "isValidNoticeProof reverts if the proof is invalid" + }, + "isValidVoucherProof(bytes,bytes32,(uint256,uint256,uint256,bytes32,bytes32,bytes32,bytes32,bytes32[],bytes32[]))": { + "notice": "isValidVoucherProof reverts if the proof is invalid" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/OwnershipFacet.json b/echo-js/deployments/localhost/OwnershipFacet.json new file mode 100644 index 00000000..1faf973c --- /dev/null +++ b/echo-js/deployments/localhost/OwnershipFacet.json @@ -0,0 +1,105 @@ +{ + "address": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x80e062474a7a1e9dbb655053703b048ef42744b554cdc57530cc04e49ef2e66f", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82", + "transactionIndex": 0, + "gasUsed": "179473", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd1729958723714bfd7efc05c1d51d1f971aa290b6483b5acc668064d45991a4d", + "transactionHash": "0x80e062474a7a1e9dbb655053703b048ef42744b554cdc57530cc04e49ef2e66f", + "logs": [], + "blockNumber": 14, + "cumulativeGasUsed": "179473", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"owner()\":{\"returns\":{\"owner_\":\"The address of the owner.\"}},\"transferOwnership(address)\":{\"details\":\"Set _newOwner to address(0) to renounce any ownership.\",\"params\":{\"_newOwner\":\"The address of the new owner of the contract\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"owner()\":{\"notice\":\"Get the address of the owner\"},\"transferOwnership(address)\":{\"notice\":\"Set the address of the new owner of the contract\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/OwnershipFacet.sol\":\"OwnershipFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/facets/OwnershipFacet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\nimport {LibDiamond} from \\\"../libraries/LibDiamond.sol\\\";\\nimport {IERC173} from \\\"../interfaces/IERC173.sol\\\";\\n\\ncontract OwnershipFacet is IERC173 {\\n function transferOwnership(address _newOwner) external override {\\n LibDiamond.enforceIsContractOwner();\\n LibDiamond.setContractOwner(_newOwner);\\n }\\n\\n function owner() external view override returns (address owner_) {\\n owner_ = LibDiamond.contractOwner();\\n }\\n}\\n\",\"keccak256\":\"0x08a198b9541f25536ae7fa16f3de069de7450f66709605911e34834e65ad6419\",\"license\":\"MIT\"},\"contracts/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {\\n Add,\\n Replace,\\n Remove\\n }\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\\n}\\n\",\"keccak256\":\"0x6a3129be1f39b6fec871f2c94bf7debf2d6a4e665547a4d83e7f2def38359e44\",\"license\":\"MIT\"},\"contracts/interfaces/IERC173.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/// @title ERC-173 Contract Ownership Standard\\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\\n/* is ERC165 */\\ninterface IERC173 {\\n /// @dev This emits when ownership of a contract changes.\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n /// @notice Get the address of the owner\\n /// @return owner_ The address of the owner.\\n function owner() external view returns (address owner_);\\n\\n /// @notice Set the address of the new owner of the contract\\n /// @dev Set _newOwner to address(0) to renounce any ownership.\\n /// @param _newOwner The address of the new owner of the contract\\n function transferOwnership(address _newOwner) external;\\n}\\n\",\"keccak256\":\"0xc47289cda9c9cdb749612eb82ccb9abf9ab08dca74bdca22292ae7f765a15a5f\",\"license\":\"MIT\"},\"contracts/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport {IDiamondCut} from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // maps function selectors to the facets that execute the functions.\\n // and maps the selectors to their position in the selectorSlots array.\\n // func selector => address facet, selector position\\n mapping(bytes4 => bytes32) facets;\\n // array of slots of function selectors.\\n // each slot holds 8 function selectors.\\n mapping(uint256 => bytes32) selectorSlots;\\n // The number of function selectors in selectorSlots\\n uint16 selectorCount;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(\\n address indexed previousOwner,\\n address indexed newOwner\\n );\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(\\n msg.sender == diamondStorage().contractOwner,\\n \\\"LibDiamond: Must be contract owner\\\"\\n );\\n }\\n\\n event DiamondCut(\\n IDiamondCut.FacetCut[] diamondCut,\\n address init,\\n bytes callData\\n );\\n\\n bytes32 constant CLEAR_ADDRESS_MASK =\\n bytes32(uint256(0xffffffffffffffffffffffff));\\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\\n\\n // Internal function version of diamondCut\\n // This code is almost the same as the external diamondCut,\\n // except it is using 'Facet[] memory _diamondCut' instead of\\n // 'Facet[] calldata _diamondCut'.\\n // The code is duplicated to prevent copying calldata to memory which\\n // causes an error for a two dimensional array.\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n DiamondStorage storage ds = diamondStorage();\\n uint256 originalSelectorCount = ds.selectorCount;\\n uint256 selectorCount = originalSelectorCount;\\n bytes32 selectorSlot;\\n // Check if last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // get last selectorSlot\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\\n }\\n // loop through diamond cut\\n for (\\n uint256 facetIndex;\\n facetIndex < _diamondCut.length;\\n facetIndex++\\n ) {\\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\\n selectorCount,\\n selectorSlot,\\n _diamondCut[facetIndex].facetAddress,\\n _diamondCut[facetIndex].action,\\n _diamondCut[facetIndex].functionSelectors\\n );\\n }\\n if (selectorCount != originalSelectorCount) {\\n ds.selectorCount = uint16(selectorCount);\\n }\\n // If last selector slot is not full\\n // \\\"selectorCount & 7\\\" is a gas efficient modulo by eight \\\"selectorCount % 8\\\"\\n if (selectorCount & 7 > 0) {\\n // \\\"selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"selectorSlot / 8\\\"\\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addReplaceRemoveFacetSelectors(\\n uint256 _selectorCount,\\n bytes32 _selectorSlot,\\n address _newFacetAddress,\\n IDiamondCut.FacetCutAction _action,\\n bytes4[] memory _selectors\\n ) internal returns (uint256, bytes32) {\\n DiamondStorage storage ds = diamondStorage();\\n require(\\n _selectors.length > 0,\\n \\\"LibDiamondCut: No selectors in facet to cut\\\"\\n );\\n if (_action == IDiamondCut.FacetCutAction.Add) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Add facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) == address(0),\\n \\\"LibDiamondCut: Can't add function that already exists\\\"\\n );\\n // add facet for selector\\n ds.facets[selector] =\\n bytes20(_newFacetAddress) |\\n bytes32(_selectorCount);\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\\n // clear selector position in slot and add selector\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\\n (bytes32(selector) >> selectorInSlotPosition);\\n // if slot is full then write it to storage\\n if (selectorInSlotPosition == 224) {\\n // \\\"_selectorSlot >> 3\\\" is a gas efficient division by 8 \\\"_selectorSlot / 8\\\"\\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\\n _selectorSlot = 0;\\n }\\n _selectorCount++;\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\\n enforceHasContractCode(\\n _newFacetAddress,\\n \\\"LibDiamondCut: Replace facet has no code\\\"\\n );\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n address oldFacetAddress = address(bytes20(oldFacet));\\n // only useful if immutable functions exist\\n require(\\n oldFacetAddress != address(this),\\n \\\"LibDiamondCut: Can't replace immutable function\\\"\\n );\\n require(\\n oldFacetAddress != _newFacetAddress,\\n \\\"LibDiamondCut: Can't replace function with same function\\\"\\n );\\n require(\\n oldFacetAddress != address(0),\\n \\\"LibDiamondCut: Can't replace function that doesn't exist\\\"\\n );\\n // replace old facet address\\n ds.facets[selector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(_newFacetAddress);\\n }\\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\\n require(\\n _newFacetAddress == address(0),\\n \\\"LibDiamondCut: Remove facet address must be address(0)\\\"\\n );\\n // \\\"_selectorCount >> 3\\\" is a gas efficient division by 8 \\\"_selectorCount / 8\\\"\\n uint256 selectorSlotCount = _selectorCount >> 3;\\n // \\\"_selectorCount & 7\\\" is a gas efficient modulo by eight \\\"_selectorCount % 8\\\"\\n uint256 selectorInSlotIndex = _selectorCount & 7;\\n for (\\n uint256 selectorIndex;\\n selectorIndex < _selectors.length;\\n selectorIndex++\\n ) {\\n if (_selectorSlot == 0) {\\n // get last selectorSlot\\n selectorSlotCount--;\\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\\n selectorInSlotIndex = 7;\\n } else {\\n selectorInSlotIndex--;\\n }\\n bytes4 lastSelector;\\n uint256 oldSelectorsSlotCount;\\n uint256 oldSelectorInSlotPosition;\\n // adding a block here prevents stack too deep error\\n {\\n bytes4 selector = _selectors[selectorIndex];\\n bytes32 oldFacet = ds.facets[selector];\\n require(\\n address(bytes20(oldFacet)) != address(0),\\n \\\"LibDiamondCut: Can't remove function that doesn't exist\\\"\\n );\\n // only useful if immutable functions exist\\n require(\\n address(bytes20(oldFacet)) != address(this),\\n \\\"LibDiamondCut: Can't remove immutable function\\\"\\n );\\n // replace selector with last selector in ds.facets\\n // gets the last selector\\n lastSelector = bytes4(\\n _selectorSlot << (selectorInSlotIndex << 5)\\n );\\n if (lastSelector != selector) {\\n // update last selector slot position info\\n ds.facets[lastSelector] =\\n (oldFacet & CLEAR_ADDRESS_MASK) |\\n bytes20(ds.facets[lastSelector]);\\n }\\n delete ds.facets[selector];\\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\\n // \\\"oldSelectorCount >> 3\\\" is a gas efficient division by 8 \\\"oldSelectorCount / 8\\\"\\n oldSelectorsSlotCount = oldSelectorCount >> 3;\\n // \\\"oldSelectorCount & 7\\\" is a gas efficient modulo by eight \\\"oldSelectorCount % 8\\\"\\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\\n }\\n if (oldSelectorsSlotCount != selectorSlotCount) {\\n bytes32 oldSelectorSlot = ds.selectorSlots[\\n oldSelectorsSlotCount\\n ];\\n // clears the selector we are deleting and puts the last selector in its place.\\n oldSelectorSlot =\\n (oldSelectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n // update storage with the modified slot\\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\\n } else {\\n // clears the selector we are deleting and puts the last selector in its place.\\n _selectorSlot =\\n (_selectorSlot &\\n ~(CLEAR_SELECTOR_MASK >>\\n oldSelectorInSlotPosition)) |\\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\\n }\\n if (selectorInSlotIndex == 0) {\\n delete ds.selectorSlots[selectorSlotCount];\\n _selectorSlot = 0;\\n }\\n }\\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n return (_selectorCount, _selectorSlot);\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata)\\n internal\\n {\\n if (_init == address(0)) {\\n require(\\n _calldata.length == 0,\\n \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\"\\n );\\n } else {\\n require(\\n _calldata.length > 0,\\n \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\"\\n );\\n if (_init != address(this)) {\\n enforceHasContractCode(\\n _init,\\n \\\"LibDiamondCut: _init address has no code\\\"\\n );\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(\\n address _contract,\\n string memory _errorMessage\\n ) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x740ea3845282f09bb822e66a189ed431ac799ab08184de7457ef53799b2e99d6\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610248806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c80638da5cb5b1461003b578063f2fde38b1461005f575b600080fd5b610043610074565b6040516001600160a01b03909116815260200160405180910390f35b61007261006d3660046101e2565b6100ac565b005b60006100a77fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c1320546001600160a01b031690565b905090565b6100b46100c0565b6100bd8161014d565b50565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c600401546001600160a01b0316331461014b5760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b606482015260840160405180910390fd5b565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b038481169182179093556040517fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6000602082840312156101f457600080fd5b81356001600160a01b038116811461020b57600080fd5b939250505056fea264697066735822122028a4df310106ca3538d88cb1b0ac2c4586b78c8eafbbc533269b52abf6654d8d64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c80638da5cb5b1461003b578063f2fde38b1461005f575b600080fd5b610043610074565b6040516001600160a01b03909116815260200160405180910390f35b61007261006d3660046101e2565b6100ac565b005b60006100a77fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c1320546001600160a01b031690565b905090565b6100b46100c0565b6100bd8161014d565b50565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c600401546001600160a01b0316331461014b5760405162461bcd60e51b815260206004820152602260248201527f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60448201526132b960f11b606482015260840160405180910390fd5b565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080546001600160a01b031981166001600160a01b038481169182179093556040517fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b6000602082840312156101f457600080fd5b81356001600160a01b038116811461020b57600080fd5b939250505056fea264697066735822122028a4df310106ca3538d88cb1b0ac2c4586b78c8eafbbc533269b52abf6654d8d64736f6c634300080d0033", + "devdoc": { + "kind": "dev", + "methods": { + "owner()": { + "returns": { + "owner_": "The address of the owner." + } + }, + "transferOwnership(address)": { + "details": "Set _newOwner to address(0) to renounce any ownership.", + "params": { + "_newOwner": "The address of the new owner of the contract" + } + } + }, + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": { + "owner()": { + "notice": "Get the address of the owner" + }, + "transferOwnership(address)": { + "notice": "Set the address of the new owner of the contract" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/RollupsFacet.json b/echo-js/deployments/localhost/RollupsFacet.json new file mode 100644 index 00000000..1e031563 --- /dev/null +++ b/echo-js/deployments/localhost/RollupsFacet.json @@ -0,0 +1,295 @@ +{ + "address": "0x09635F643e140090A9A8Dcd712eD6285858ceBef", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "claimer", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "epochHash", + "type": "bytes32" + } + ], + "name": "Claim", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "uint256", + "name": "epochNumber", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "epochHash", + "type": "bytes32" + } + ], + "name": "FinalizeEpoch", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Phase", + "name": "newPhase", + "type": "uint8" + } + ], + "name": "PhaseChange", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "winner", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "loser", + "type": "address" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "winningClaim", + "type": "bytes32" + } + ], + "name": "ResolveDispute", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "_epochHash", + "type": "bytes32" + } + ], + "name": "claim", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "finalizeEpoch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "getChallengePeriod", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentEpoch", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentPhase", + "outputs": [ + { + "internalType": "enum Phase", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInputAccumulationStart", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getInputDuration", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getSealingEpochTimestamp", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTemplateHash", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xe9686301791672797d70426db27ef8ff18afc98cb7c85cd4ff8143cb73e384ea", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x09635F643e140090A9A8Dcd712eD6285858ceBef", + "transactionIndex": 0, + "gasUsed": "1327531", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xd8a3728954c2373bd2b83519c81bb0aba9b9003ce7c78f66a61c36eff153ca4e", + "transactionHash": "0xe9686301791672797d70426db27ef8ff18afc98cb7c85cd4ff8143cb73e384ea", + "logs": [], + "blockNumber": 28, + "cumulativeGasUsed": "1327531", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"epochNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"claimer\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"epochHash\",\"type\":\"bytes32\"}],\"name\":\"Claim\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"uint256\",\"name\":\"epochNumber\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"epochHash\",\"type\":\"bytes32\"}],\"name\":\"FinalizeEpoch\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enum Phase\",\"name\":\"newPhase\",\"type\":\"uint8\"}],\"name\":\"PhaseChange\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"winner\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"loser\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"winningClaim\",\"type\":\"bytes32\"}],\"name\":\"ResolveDispute\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"_epochHash\",\"type\":\"bytes32\"}],\"name\":\"claim\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"finalizeEpoch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getChallengePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentEpoch\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentPhase\",\"outputs\":[{\"internalType\":\"enum Phase\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInputAccumulationStart\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getInputDuration\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getSealingEpochTimestamp\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTemplateHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"claim(bytes32)\":{\"details\":\"ValidatorManager makes sure that msg.sender is allowed and that claim != bytes32(0) TODO: add signatures for aggregated claims\",\"params\":{\"_epochHash\":\"hash of epoch\"}},\"finalizeEpoch()\":{\"details\":\"can only be called if challenge period is over\"},\"getCurrentEpoch()\":{\"details\":\"if phase is input accumulation, then the epoch number is length of finalized epochs array, else there are two non finalized epochs, one awaiting consensus/dispute and another accumulating input\",\"returns\":{\"_0\":\"index of current epoch\"}}},\"version\":1},\"userdoc\":{\"events\":{\"Claim(uint256,address,bytes32)\":{\"notice\":\"claim submitted\"},\"FinalizeEpoch(uint256,bytes32)\":{\"notice\":\"epoch finalized\"},\"PhaseChange(uint8)\":{\"notice\":\"phase change\"},\"ResolveDispute(address,address,bytes32)\":{\"notice\":\"dispute resolved\"}},\"kind\":\"user\",\"methods\":{\"claim(bytes32)\":{\"notice\":\"claim the result of current epoch\"},\"finalizeEpoch()\":{\"notice\":\"finalize epoch after timeout\"},\"getChallengePeriod()\":{\"notice\":\"returns the challenge period in seconds\"},\"getCurrentEpoch()\":{\"notice\":\"returns index of current (accumulating) epoch\"},\"getCurrentPhase()\":{\"notice\":\"returns the current phase\"},\"getInputAccumulationStart()\":{\"notice\":\"returns the input accumulation start timestamp\"},\"getInputDuration()\":{\"notice\":\"returns the input duration in seconds\"},\"getSealingEpochTimestamp()\":{\"notice\":\"returns the sealing epoch timestamp\"},\"getTemplateHash()\":{\"notice\":\"returns the machine's template hash\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/RollupsFacet.sol\":\"RollupsFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/RollupsFacet.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups facet\\npragma solidity ^0.8.0;\\n\\nimport {IRollups, Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\n\\ncontract RollupsFacet is IRollups {\\n ////\\n // All claims agreed OR challenge period ended\\n // functions: claim() or finalizeEpoch()\\n // +--------------------------------------------------+\\n // | |\\n // +--------v-----------+ new input after IPAD +---------+----------+\\n // | +--------------------------->+ |\\n // START ---> | Input Accumulation | firt claim after IPAD | Awaiting Consensus |\\n // | +--------------------------->+ |\\n // +-+------------------+ +-----------------+--+\\n // ^ ^ |\\n // | dispute resolved | |\\n // | dispute resolved before challenge | |\\n // | after challenge +--------------------+ period ended | |\\n // | period ended | +---------------------+ |\\n // +----------------------+ Awaiting Dispute | |\\n // | +<-----------------------+\\n // +--------------------+ conflicting claim\\n ///\\n\\n using LibRollups for LibRollups.DiamondStorage;\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) public override {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n\\n Phase currentPhase = Phase(rollupsDS.currentPhase_int);\\n uint256 inputAccumulationStart = rollupsDS.inputAccumulationStart;\\n uint256 inputDuration = rollupsDS.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n currentPhase = Phase.AwaitingConsensus;\\n rollupsDS.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n\\n // warns input of new epoch\\n inputDS.onNewInputAccumulation();\\n // update timestamp of sealing epoch proposal\\n rollupsDS.sealingEpochTimestamp = uint32(block.timestamp);\\n }\\n\\n require(\\n currentPhase == Phase.AwaitingConsensus,\\n \\\"Phase != AwaitingConsensus\\\"\\n );\\n (result, claims, claimers) = validatorManagerDS.onClaim(\\n payable(msg.sender),\\n _epochHash\\n );\\n\\n // emit the claim event before processing it\\n // so if the epoch is finalized in this claim (consensus)\\n // the number of final epochs doesnt gets contaminated\\n emit Claim(\\n outputDS.getNumberOfFinalizedEpochs(),\\n msg.sender,\\n _epochHash\\n );\\n\\n rollupsDS.resolveValidatorResult(result, claims, claimers);\\n }\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() public override {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n Phase currentPhase = Phase(rollupsDS.currentPhase_int);\\n require(\\n currentPhase == Phase.AwaitingConsensus,\\n \\\"Phase != Awaiting Consensus\\\"\\n );\\n\\n uint256 sealingEpochTimestamp = rollupsDS.sealingEpochTimestamp;\\n uint256 challengePeriod = rollupsDS.challengePeriod;\\n require(\\n block.timestamp > sealingEpochTimestamp + challengePeriod,\\n \\\"Challenge period not over\\\"\\n );\\n\\n require(\\n validatorManagerDS.currentClaim != bytes32(0),\\n \\\"No Claim to be finalized\\\"\\n );\\n\\n rollupsDS.startNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch() public view override returns (uint256) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return rollupsDS.getCurrentEpoch();\\n }\\n\\n /// @notice returns the current phase\\n function getCurrentPhase() public view returns (Phase) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return Phase(rollupsDS.currentPhase_int);\\n }\\n\\n /// @notice returns the input accumulation start timestamp\\n function getInputAccumulationStart() public view returns (uint256) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return uint256(rollupsDS.inputAccumulationStart);\\n }\\n\\n /// @notice returns the sealing epoch timestamp\\n function getSealingEpochTimestamp() public view returns (uint256) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return uint256(rollupsDS.sealingEpochTimestamp);\\n }\\n\\n /// @notice returns the input duration in seconds\\n function getInputDuration() public view returns (uint256) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return uint256(rollupsDS.inputDuration);\\n }\\n\\n /// @notice returns the challenge period in seconds\\n function getChallengePeriod() public view returns (uint256) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return uint256(rollupsDS.challengePeriod);\\n }\\n\\n /// @notice returns the machine's template hash\\n function getTemplateHash() public view returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n return rollupsDS.templateHash;\\n }\\n}\\n\",\"keccak256\":\"0xb4fa1894b1be726ec583569a1027ce9d509528fcb5e1e012228344b5a7343360\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups interface\\npragma solidity >=0.7.0;\\n\\n// InputAccumulation - Inputs being accumulated for currrent epoch\\n// AwaitingConsensus - No disagreeing claims (or no claims)\\n// AwaitingDispute - Waiting for dispute to be over\\n// inputs received during InputAccumulation will be included in the\\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\\n// are accumulated for the next epoch\\nenum Phase {\\n InputAccumulation,\\n AwaitingConsensus,\\n AwaitingDispute\\n}\\n\\ninterface IRollups {\\n /// @notice claim the result of current epoch\\n /// @param _epochHash hash of epoch\\n /// @dev ValidatorManager makes sure that msg.sender is allowed\\n /// and that claim != bytes32(0)\\n /// TODO: add signatures for aggregated claims\\n function claim(bytes32 _epochHash) external;\\n\\n /// @notice finalize epoch after timeout\\n /// @dev can only be called if challenge period is over\\n function finalizeEpoch() external;\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two epochs two non\\n /// finalized epochs, one awaiting consensus/dispute and another\\n /// accumulating input\\n function getCurrentEpoch() external view returns (uint256);\\n\\n /// @notice claim submitted\\n /// @param epochHash claim being submitted by this epoch\\n /// @param claimer address of current claimer\\n /// @param epochNumber number of the epoch being submitted\\n event Claim(\\n uint256 indexed epochNumber,\\n address claimer,\\n bytes32 epochHash\\n );\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n}\\n\",\"keccak256\":\"0x241c3ee8bb900067903ac836d5f3ee81eca587c7f225ad6df686478a6b27329b\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibDisputeManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Dispute Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibDisputeManager {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n /// @notice initiates a dispute betweent two players\\n /// @param claims conflicting claims\\n /// @param claimers addresses of senders of conflicting claim\\n /// @dev this is a mock implementation that just gives the win\\n /// to the address in the first posititon of claimers array\\n function initiateDispute(\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\\n }\\n}\\n\",\"keccak256\":\"0x7d3fdb94a17c7f61ef8f6431f42eaa307b30398e3c24093c0526f449752563c9\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibInput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Input library\\npragma solidity ^0.8.0;\\n\\nimport {LibRollups} from \\\"../libraries/LibRollups.sol\\\";\\n\\nlibrary LibInput {\\n using LibRollups for LibRollups.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Input.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n // always needs to keep track of two input boxes:\\n // 1 for the input accumulation of next epoch\\n // and 1 for the messages during current epoch. To save gas we alternate\\n // between inputBox0 and inputBox1\\n bytes32[] inputBox0;\\n bytes32[] inputBox1;\\n uint256 inputDriveSize; // size of input flashdrive\\n uint256 currentInputBox;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice get input inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @param index index of input inside that inbox\\n /// @return hash of input at index index\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getInput(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (bytes32)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\\n }\\n\\n /// @notice get number of inputs inside inbox of currently proposed claim\\n /// @param ds diamond storage pointer\\n /// @return number of inputs on that input box\\n /// @dev currentInputBox being zero means that the inputs for\\n /// the claimed epoch are on input box one\\n function getNumberOfInputs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return\\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\\n }\\n\\n /// @notice add input to processed by next epoch\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, msg.sender);\\n }\\n\\n /// @notice add internal input to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\\n internal\\n returns (bytes32)\\n {\\n return addInputFromSender(ds, input, address(this));\\n }\\n\\n /// @notice add input from a specific sender to processed by next epoch\\n /// @notice this function is to be reserved for internal usage only\\n /// @notice for normal inputs, call `addInput` instead\\n /// @param ds diamond storage pointer\\n /// @param input input to be understood by offchain machine\\n /// @param sender input sender address\\n /// @dev offchain code is responsible for making sure\\n /// that input size is power of 2 and multiple of 8 since\\n /// the offchain machine has a 8 byte word\\n function addInputFromSender(\\n DiamondStorage storage ds,\\n bytes memory input,\\n address sender\\n ) internal returns (bytes32) {\\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\\n .diamondStorage();\\n\\n require(input.length <= ds.inputDriveSize, \\\"input len: [0,driveSize]\\\");\\n\\n // notifyInput returns true if that input\\n // belongs to a new epoch\\n if (rollupsDS.notifyInput()) {\\n swapInputBox(ds);\\n }\\n\\n // points to correct inputBox\\n bytes32[] storage inputBox = ds.currentInputBox == 0\\n ? ds.inputBox0\\n : ds.inputBox1;\\n\\n // get current epoch index\\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\\n\\n // keccak 64 bytes into 32 bytes\\n bytes32 keccakMetadata = keccak256(\\n abi.encode(\\n sender,\\n block.number,\\n block.timestamp,\\n currentEpoch, // epoch index\\n inputBox.length // input index\\n )\\n );\\n\\n bytes32 keccakInput = keccak256(input);\\n\\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\\n\\n // add input to correct inbox\\n inputBox.push(inputHash);\\n\\n emit InputAdded(\\n currentEpoch,\\n inputBox.length - 1,\\n sender,\\n block.timestamp,\\n input\\n );\\n\\n return inputHash;\\n }\\n\\n /// @notice called when a new input accumulation phase begins\\n /// swap inbox to receive inputs for upcoming epoch\\n /// @param ds diamond storage pointer\\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\\n swapInputBox(ds);\\n }\\n\\n /// @notice called when a new epoch begins, clears deprecated inputs\\n /// @param ds diamond storage pointer\\n function onNewEpoch(DiamondStorage storage ds) internal {\\n // clear input box for new inputs\\n // the current input box should be accumulating inputs\\n // for the new epoch already. So we clear the other one.\\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\\n }\\n\\n /// @notice changes current input box\\n /// @param ds diamond storage pointer\\n function swapInputBox(DiamondStorage storage ds) internal {\\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\\n }\\n\\n /// @notice input added\\n /// @param epochNumber which epoch this input belongs to\\n /// @param inputIndex index of the input just added\\n /// @param sender msg.sender\\n /// @param timestamp block.timestamp\\n /// @param input input data\\n event InputAdded(\\n uint256 indexed epochNumber,\\n uint256 indexed inputIndex,\\n address sender,\\n uint256 timestamp,\\n bytes input\\n );\\n}\\n\",\"keccak256\":\"0x9fec6d72c872e8f7f3adc79fa2bc5de8396d6ae97e2e23817e780e7d7a6cfaea\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibOutput.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Output library\\npragma solidity ^0.8.0;\\n\\nlibrary LibOutput {\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Output.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n mapping(uint256 => uint256) voucherBitmask;\\n bytes32[] epochHashes;\\n bool lock; //reentrancy lock\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice to be called when an epoch is finalized\\n /// @param ds diamond storage pointer\\n /// @param epochHash hash of finalized epoch\\n /// @dev an epoch being finalized means that its vouchers can be called\\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\\n ds.epochHashes.push(epochHash);\\n }\\n\\n /// @notice get number of finalized epochs\\n /// @param ds diamond storage pointer\\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.epochHashes.length;\\n }\\n}\\n\",\"keccak256\":\"0xd0f88e13210013e9d5bde03399bb76304d6ab4e1f06d01c7e3525adc87a2d65e\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibRollups.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Rollups library\\npragma solidity ^0.8.0;\\n\\nimport {Phase} from \\\"../interfaces/IRollups.sol\\\";\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibInput} from \\\"../libraries/LibInput.sol\\\";\\nimport {LibOutput} from \\\"../libraries/LibOutput.sol\\\";\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibDisputeManager} from \\\"../libraries/LibDisputeManager.sol\\\";\\n\\nlibrary LibRollups {\\n using LibInput for LibInput.DiamondStorage;\\n using LibOutput for LibOutput.DiamondStorage;\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"Rollups.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 templateHash; // state hash of the cartesi machine at t0\\n uint32 inputDuration; // duration of input accumulation phase in seconds\\n uint32 challengePeriod; // duration of challenge period in seconds\\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\\n uint32 currentPhase_int; // current phase in integer form\\n }\\n\\n /// @notice epoch finalized\\n /// @param epochNumber number of the epoch being finalized\\n /// @param epochHash claim being submitted by this epoch\\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\\n\\n /// @notice dispute resolved\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\\n\\n /// @notice phase change\\n /// @param newPhase new phase\\n event PhaseChange(Phase newPhase);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when new input arrives, manages the phase changes\\n /// @param ds diamond storage pointer\\n /// @dev can only be called by input contract\\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\\n uint256 inputDuration = ds.inputDuration;\\n\\n if (\\n currentPhase == Phase.InputAccumulation &&\\n block.timestamp > inputAccumulationStart + inputDuration\\n ) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n return true;\\n }\\n return false;\\n }\\n\\n /// @notice called when a dispute is resolved by the dispute manager\\n /// @param ds diamond storage pointer\\n /// @param winner winner of dispute\\n /// @param loser loser of dispute\\n /// @param winningClaim initial claim of winning validator\\n function resolveDispute(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n ) internal {\\n Result result;\\n bytes32[2] memory claims;\\n address payable[2] memory claimers;\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\\n winner,\\n loser,\\n winningClaim\\n );\\n\\n // restart challenge period\\n ds.sealingEpochTimestamp = uint32(block.timestamp);\\n\\n emit ResolveDispute(winner, loser, winningClaim);\\n resolveValidatorResult(ds, result, claims, claimers);\\n }\\n\\n /// @notice resolve results returned by validator manager\\n /// @param ds diamond storage pointer\\n /// @param result result from claim or dispute operation\\n /// @param claims array of claims in case of new conflict\\n /// @param claimers array of claimers in case of new conflict\\n function resolveValidatorResult(\\n DiamondStorage storage ds,\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory claimers\\n ) internal {\\n if (result == Result.NoConflict) {\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingConsensus) {\\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\\n emit PhaseChange(Phase.AwaitingConsensus);\\n }\\n } else if (result == Result.Consensus) {\\n startNewEpoch(ds);\\n } else {\\n // for the case when result == Result.Conflict\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n if (currentPhase != Phase.AwaitingDispute) {\\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\\n emit PhaseChange(Phase.AwaitingDispute);\\n }\\n LibDisputeManager.initiateDispute(claims, claimers);\\n }\\n }\\n\\n /// @notice starts new epoch\\n /// @param ds diamond storage pointer\\n function startNewEpoch(DiamondStorage storage ds) internal {\\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n\\n // reset input accumulation start and deactivate challenge period start\\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\\n emit PhaseChange(Phase.InputAccumulation);\\n ds.inputAccumulationStart = uint32(block.timestamp);\\n ds.sealingEpochTimestamp = type(uint32).max;\\n\\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\\n\\n // emit event before finalized epoch is added to the Output storage\\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\\n\\n outputDS.onNewEpoch(finalClaim);\\n inputDS.onNewEpoch();\\n }\\n\\n /// @notice returns index of current (accumulating) epoch\\n /// @param ds diamond storage pointer\\n /// @return index of current epoch\\n /// @dev if phase is input accumulation, then the epoch number is length\\n /// of finalized epochs array, else there are two non finalized epochs,\\n /// one awaiting consensus/dispute and another accumulating input\\n function getCurrentEpoch(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\\n\\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\\n\\n Phase currentPhase = Phase(ds.currentPhase_int);\\n\\n return\\n currentPhase == Phase.InputAccumulation\\n ? finalizedEpochs\\n : finalizedEpochs + 1;\\n }\\n}\\n\",\"keccak256\":\"0x04f72881c6032af40537ac14ff3720df2899a5746a42abd841b2292d66db11ca\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061170f806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063a3a40ea511610066578063a3a40ea51461010b578063b97dd9e214610120578063bd66528a14610128578063ddf7bcf01461013b578063e17ba0121461015d57600080fd5b806354ee1da51461009857806361b12c66146100c95780637864b77d146100de57806382ae9ef714610101575b600080fd5b60008051602061165a83398151915254600160601b900463ffffffff165b6040519081526020015b60405180910390f35b6000805160206116ba833981519152546100b6565b60008051602061165a83398151915254640100000000900463ffffffff166100b6565b610109610178565b005b610113610304565b6040516100c091906114fb565b6100b661034b565b61010961013636600461150e565b610365565b60008051602061165a83398151915254600160401b900463ffffffff166100b6565b60008051602061165a8339815191525463ffffffff166100b6565b60008051602061165a833981519152546000805160206116ba8339815191529060008051602061169a83398151915290600090600160801b900463ffffffff1660028111156101c9576101c96114c7565b905060018160028111156101df576101df6114c7565b146102315760405162461bcd60e51b815260206004820152601b60248201527f506861736520213d204177616974696e6720436f6e73656e737573000000000060448201526064015b60405180910390fd5b600183015463ffffffff600160601b8204811691640100000000900416610258818361153d565b42116102a65760405162461bcd60e51b815260206004820152601960248201527f4368616c6c656e676520706572696f64206e6f74206f766572000000000000006044820152606401610228565b83546102f45760405162461bcd60e51b815260206004820152601860248201527f4e6f20436c61696d20746f2062652066696e616c697a656400000000000000006044820152606401610228565b6102fd8561057f565b5050505050565b60008051602061165a833981519152546000906000805160206116ba83398151915290600160801b900463ffffffff166002811115610345576103456114c7565b91505090565b60006000805160206116ba833981519152610345816106b7565b6000805160206116ba8339815191527f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea56660008051602061169a83398151915260006103cf611477565b6103d7611477565b6001870154600090600160801b900463ffffffff1660028111156103fd576103fd6114c7565b600189015490915063ffffffff600160401b8204811691166000836002811115610429576104296114c7565b14801561043e575061043b818361153d565b42115b156104af5760018a8101805463ffffffff60801b1916600160801b17905560405190935060008051602061167a8339815191529061047d9085906114fb565b60405180910390a161048e89610759565b60018a01805463ffffffff60601b1916600160601b4263ffffffff16021790555b60018360028111156104c3576104c36114c7565b146105105760405162461bcd60e51b815260206004820152601a60248201527f506861736520213d204177616974696e67436f6e73656e7375730000000000006044820152606401610228565b61051b87338d610765565b9197509550935061052d886001015490565b60408051338152602081018e90527fd31325e5dc55b03edf08c70299d3b1bc8d4c2ca8512c90138ddd03e3f54fce6c910160405180910390a26105728a878787610986565b5050505050505050505050565b60018101805463ffffffff60801b191690556040517f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff907f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5669060008051602061169a8339815191529060008051602061167a83398151915290610604906000906114fb565b60405180910390a160018401805463ffffffff60601b1963ffffffff4216600160401b02166fffffffffffffffff0000000000000000199091161763ffffffff60601b179055600061065582610adc565b9050610662836001015490565b6040518281527f6e3d05bc77b9307d9ba574c7c3196a746edd51104ded1c823edc63be4b8a63c39060200160405180910390a2600180840180549182018155600090815260209020018190556102fd84610b39565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff166002811115610723576107236114c7565b90506000816002811115610739576107396114c7565b1461074e5761074982600161153d565b610750565b815b95945050505050565b61076281610b5c565b50565b600061076f611477565b610777611477565b836107b25760405162461bcd60e51b815260206004820152600b60248201526a656d70747920636c61696d60a81b6044820152606401610228565b6107bc8686610b7b565b6107fd5760405162461bcd60e51b81526020600482015260126024820152711cd95b99195c881b9bdd08185b1b1bddd95960721b6044820152606401610228565b60006108098787610c2a565b600388015490915060f81c811c600116156108765760405162461bcd60e51b815260206004820152602760248201527f73656e6465722068616420636c61696d656420696e20746869732065706f6368604482015266206265666f726560c81b6064820152608401610228565b8654610884578487556108e4565b865485146108e4576108d8600260405180604001604052808a6000015481526020018881525060405180604001604052806108be8c610d09565b6001600160a01b0390811682528b16602090910152610dc3565b9350935093505061097d565b6108ee8787610e1c565b6108f787610e47565b61093b576040805180820182528681526000602080830182905283518085019094526001600160a01b038a168452830181905261093692909190610dc3565b610975565b6040805180820182528681526000602080830182905283518085019094526001600160a01b038a1684528301526109759160019190610dc3565b935093509350505b93509350939050565b600083600281111561099a5761099a6114c7565b03610a24576001840154600090600160801b900463ffffffff1660028111156109c5576109c56114c7565b905060018160028111156109db576109db6114c7565b14610a1e576001858101805463ffffffff60801b1916600160801b17905560405160008051602061167a83398151915291610a15916114fb565b60405180910390a15b50610ad6565b6001836002811115610a3857610a386114c7565b03610a4b57610a468461057f565b610ad6565b6001840154600090600160801b900463ffffffff166002811115610a7157610a716114c7565b90506002816002811115610a8757610a876114c7565b14610acc5760018501805463ffffffff60801b1916600160811b17905560405160008051602061167a83398151915290610ac3906002906114fb565b60405180910390a15b6102fd8383610e69565b50505050565b6000610ae782610e92565b81546000835560038301546001600160f81b031660038401556040518181527fddc860800a99149017c480ec51523bf4143b7215e78956ae5c31e5c568f5383a9060200160405180910390a192915050565b600381015415610b4e57610762816000611495565b610762600182016000611495565b600381015415610b6d576000610b70565b60015b60ff16600390910155565b60006001600160a01b038216610bbf5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b6044820152606401610228565b60005b6001840154811015610c1e57836001018181548110610be357610be3611555565b6000918252602090912001546001600160a01b0390811690841603610c0c576001915050610c24565b80610c168161156b565b915050610bc2565b50600090505b92915050565b60006001600160a01b038216610c6e5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b6044820152606401610228565b60005b6001840154811015610cca57836001018181548110610c9257610c92611555565b6000918252602090912001546001600160a01b0390811690841603610cb8579050610c24565b80610cc28161156b565b915050610c71565b5060405162461bcd60e51b81526020600482015260136024820152721d985b1a59185d1bdc881b9bdd08199bdd5b99606a1b6044820152606401610228565b600080610d1a836003015460f81c90565b905060005b6001840154811015610d7a576001811b821615610d6857836001018181548110610d4b57610d4b611555565b6000918252602090912001546001600160a01b0316949350505050565b80610d728161156b565b915050610d1f565b5060405162461bcd60e51b815260206004820152601c60248201527f4167726565696e672076616c696461746f72206e6f7420666f756e64000000006044820152606401610228565b6000610dcd611477565b610dd5611477565b7f495383aed97965c56495cdbadedfe9667a1b028c54d3fc4b5335895146e02b70868686604051610e0893929190611584565b60405180910390a150939492935090919050565b6000610e288383610c2a565b6003840154909150610e3a9082610ee7565b8360030181905550505050565b600381015460009060f081901c60ff16610e618260f81c90565b149392505050565b8051602082015183516000805160206116ba83398151915292610e8d928492610f25565b505050565b6000610ea2826003015460f81c90565b905060005b6001830154811015610e8d576001811b821615610ed5576003830154610ecf90826001610fdb565b60038401555b80610edf8161156b565b915050610ea7565b600060088210610f095760405162461bcd60e51b8152600401610228906115f7565b6000610f168360f861153d565b6001901b841791505092915050565b6000610f2f611477565b610f37611477565b60008051602061169a833981519152610f528188888861102e565b60018b01805463ffffffff60601b1916600160601b4263ffffffff1602179055604080516001600160a01b03808d1682528b16602082015290810189905292965090945092507f2afbde4d47160a9c5de25b0df88d5b83e705286f2a447cac162db5e99ad6f5d29060600160405180910390a1610fd188858585610986565b5050505050505050565b600060088310610ffd5760405162461bcd60e51b8152600401610228906115f7565b600061100985856111e2565b90506000611017848361153d565b9050611024868683611230565b9695505050505050565b6000611038611477565b611040611477565b61104a87866112e4565b865484036110e45761105b87610e47565b61109f576040805180820182528581526000602080830182905283518085019094526001600160a01b038a168452830181905261109a929091906113b8565b6110d9565b6040805180820182528581526000602080830182905283518085019094526001600160a01b038a1684528301526110d991600191906113b8565b9250925092506111d8565b600387015460f81c1561113d576110d9600260405180604001604052808a6000015481526020018781525060405180604001604052806111238c610d09565b6001600160a01b0390811682528b166020909101526113b8565b83875561114a8787610e1c565b61115387610e47565b611197576040805180820182528581526000602080830182905283518085019094526001600160a01b038a1684528301819052611192929091906113b8565b6111d1565b6040805180820182528581526000602080830182905283518085019094526001600160a01b038a1684528301526111d191600191906113b8565b9250925092505b9450945094915050565b6000600882106112045760405162461bcd60e51b8152600401610228906115f7565b600061121560016340000000611623565b90508061122384601e61163a565b85901c1691505092915050565b6000600883106112525760405162461bcd60e51b8152600401610228906115f7565b61126160016340000000611623565b8211156112a65760405162461bcd60e51b8152602060048201526013602482015272436c61696d734d61736b204f766572666c6f7760681b6044820152606401610228565b60006112b384601e61163a565b6112c260016340000000611623565b901b1990508481166112d585601e61163a565b9390931b909217949350505050565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7360005b6001840154811015610ad65783600101818154811061132957611329611555565b6000918252602090912001546001600160a01b03908116908416036113a657600084600101828154811061135f5761135f611555565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600384015461139790826113fd565b6003850155610a46828261145a565b806113b08161156b565b915050611308565b60006113c2611477565b6113ca611477565b7f09201c193a07cae1df95ae692cc698685574c942a04514c48a4c3249f38594ff868686604051610e0893929190611584565b60006008821061141f5760405162461bcd60e51b8152600401610228906115f7565b82600061142d8460f861153d565b6001901b199182169190506114438460f061153d565b6001901b1991821691905061075082856000611230565b600382015461146b90826000611230565b82600301819055505050565b60405180604001604052806002906020820280368337509192915050565b508054600082559060005260206000209081019061076291905b808211156114c357600081556001016114af565b5090565b634e487b7160e01b600052602160045260246000fd5b6003811061076257634e487b7160e01b600052602160045260246000fd5b60208101611508836114dd565b91905290565b60006020828403121561152057600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561155057611550611527565b500190565b634e487b7160e01b600052603260045260246000fd5b60006001820161157d5761157d611527565b5060010190565b60a08101611591856114dd565b84825260208083018560005b60028110156115ba5781518352918301919083019060010161159d565b505050606083018460005b60028110156115eb5781516001600160a01b0316835291830191908301906001016115c5565b50505050949350505050565b602080825260129082015271696e646578206f7574206f662072616e676560701b604082015260600190565b60008282101561163557611635611527565b500390565b600081600019048311821515161561165457611654611527565b50029056fed32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189ded606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fcd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189ca264697066735822122005a48434be4f5e94111d6d06fc627e4729c541be34424a5e0fb455dd1e4422ab64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063a3a40ea511610066578063a3a40ea51461010b578063b97dd9e214610120578063bd66528a14610128578063ddf7bcf01461013b578063e17ba0121461015d57600080fd5b806354ee1da51461009857806361b12c66146100c95780637864b77d146100de57806382ae9ef714610101575b600080fd5b60008051602061165a83398151915254600160601b900463ffffffff165b6040519081526020015b60405180910390f35b6000805160206116ba833981519152546100b6565b60008051602061165a83398151915254640100000000900463ffffffff166100b6565b610109610178565b005b610113610304565b6040516100c091906114fb565b6100b661034b565b61010961013636600461150e565b610365565b60008051602061165a83398151915254600160401b900463ffffffff166100b6565b60008051602061165a8339815191525463ffffffff166100b6565b60008051602061165a833981519152546000805160206116ba8339815191529060008051602061169a83398151915290600090600160801b900463ffffffff1660028111156101c9576101c96114c7565b905060018160028111156101df576101df6114c7565b146102315760405162461bcd60e51b815260206004820152601b60248201527f506861736520213d204177616974696e6720436f6e73656e737573000000000060448201526064015b60405180910390fd5b600183015463ffffffff600160601b8204811691640100000000900416610258818361153d565b42116102a65760405162461bcd60e51b815260206004820152601960248201527f4368616c6c656e676520706572696f64206e6f74206f766572000000000000006044820152606401610228565b83546102f45760405162461bcd60e51b815260206004820152601860248201527f4e6f20436c61696d20746f2062652066696e616c697a656400000000000000006044820152606401610228565b6102fd8561057f565b5050505050565b60008051602061165a833981519152546000906000805160206116ba83398151915290600160801b900463ffffffff166002811115610345576103456114c7565b91505090565b60006000805160206116ba833981519152610345816106b7565b6000805160206116ba8339815191527f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea56660008051602061169a83398151915260006103cf611477565b6103d7611477565b6001870154600090600160801b900463ffffffff1660028111156103fd576103fd6114c7565b600189015490915063ffffffff600160401b8204811691166000836002811115610429576104296114c7565b14801561043e575061043b818361153d565b42115b156104af5760018a8101805463ffffffff60801b1916600160801b17905560405190935060008051602061167a8339815191529061047d9085906114fb565b60405180910390a161048e89610759565b60018a01805463ffffffff60601b1916600160601b4263ffffffff16021790555b60018360028111156104c3576104c36114c7565b146105105760405162461bcd60e51b815260206004820152601a60248201527f506861736520213d204177616974696e67436f6e73656e7375730000000000006044820152606401610228565b61051b87338d610765565b9197509550935061052d886001015490565b60408051338152602081018e90527fd31325e5dc55b03edf08c70299d3b1bc8d4c2ca8512c90138ddd03e3f54fce6c910160405180910390a26105728a878787610986565b5050505050505050505050565b60018101805463ffffffff60801b191690556040517f943d5d24442f02461445e15c5d7d4a4ef0acb0d32c5d6f6af37a6882249912ff907f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5669060008051602061169a8339815191529060008051602061167a83398151915290610604906000906114fb565b60405180910390a160018401805463ffffffff60601b1963ffffffff4216600160401b02166fffffffffffffffff0000000000000000199091161763ffffffff60601b179055600061065582610adc565b9050610662836001015490565b6040518281527f6e3d05bc77b9307d9ba574c7c3196a746edd51104ded1c823edc63be4b8a63c39060200160405180910390a2600180840180549182018155600090815260209020018190556102fd84610b39565b7f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea5675460018201546000917f0635ad75fae4d4e8d896461a635d23700076a1c3fd8da26276f18cb1c09ea566918390600160801b900463ffffffff166002811115610723576107236114c7565b90506000816002811115610739576107396114c7565b1461074e5761074982600161153d565b610750565b815b95945050505050565b61076281610b5c565b50565b600061076f611477565b610777611477565b836107b25760405162461bcd60e51b815260206004820152600b60248201526a656d70747920636c61696d60a81b6044820152606401610228565b6107bc8686610b7b565b6107fd5760405162461bcd60e51b81526020600482015260126024820152711cd95b99195c881b9bdd08185b1b1bddd95960721b6044820152606401610228565b60006108098787610c2a565b600388015490915060f81c811c600116156108765760405162461bcd60e51b815260206004820152602760248201527f73656e6465722068616420636c61696d656420696e20746869732065706f6368604482015266206265666f726560c81b6064820152608401610228565b8654610884578487556108e4565b865485146108e4576108d8600260405180604001604052808a6000015481526020018881525060405180604001604052806108be8c610d09565b6001600160a01b0390811682528b16602090910152610dc3565b9350935093505061097d565b6108ee8787610e1c565b6108f787610e47565b61093b576040805180820182528681526000602080830182905283518085019094526001600160a01b038a168452830181905261093692909190610dc3565b610975565b6040805180820182528681526000602080830182905283518085019094526001600160a01b038a1684528301526109759160019190610dc3565b935093509350505b93509350939050565b600083600281111561099a5761099a6114c7565b03610a24576001840154600090600160801b900463ffffffff1660028111156109c5576109c56114c7565b905060018160028111156109db576109db6114c7565b14610a1e576001858101805463ffffffff60801b1916600160801b17905560405160008051602061167a83398151915291610a15916114fb565b60405180910390a15b50610ad6565b6001836002811115610a3857610a386114c7565b03610a4b57610a468461057f565b610ad6565b6001840154600090600160801b900463ffffffff166002811115610a7157610a716114c7565b90506002816002811115610a8757610a876114c7565b14610acc5760018501805463ffffffff60801b1916600160811b17905560405160008051602061167a83398151915290610ac3906002906114fb565b60405180910390a15b6102fd8383610e69565b50505050565b6000610ae782610e92565b81546000835560038301546001600160f81b031660038401556040518181527fddc860800a99149017c480ec51523bf4143b7215e78956ae5c31e5c568f5383a9060200160405180910390a192915050565b600381015415610b4e57610762816000611495565b610762600182016000611495565b600381015415610b6d576000610b70565b60015b60ff16600390910155565b60006001600160a01b038216610bbf5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b6044820152606401610228565b60005b6001840154811015610c1e57836001018181548110610be357610be3611555565b6000918252602090912001546001600160a01b0390811690841603610c0c576001915050610c24565b80610c168161156b565b915050610bc2565b50600090505b92915050565b60006001600160a01b038216610c6e5760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b6044820152606401610228565b60005b6001840154811015610cca57836001018181548110610c9257610c92611555565b6000918252602090912001546001600160a01b0390811690841603610cb8579050610c24565b80610cc28161156b565b915050610c71565b5060405162461bcd60e51b81526020600482015260136024820152721d985b1a59185d1bdc881b9bdd08199bdd5b99606a1b6044820152606401610228565b600080610d1a836003015460f81c90565b905060005b6001840154811015610d7a576001811b821615610d6857836001018181548110610d4b57610d4b611555565b6000918252602090912001546001600160a01b0316949350505050565b80610d728161156b565b915050610d1f565b5060405162461bcd60e51b815260206004820152601c60248201527f4167726565696e672076616c696461746f72206e6f7420666f756e64000000006044820152606401610228565b6000610dcd611477565b610dd5611477565b7f495383aed97965c56495cdbadedfe9667a1b028c54d3fc4b5335895146e02b70868686604051610e0893929190611584565b60405180910390a150939492935090919050565b6000610e288383610c2a565b6003840154909150610e3a9082610ee7565b8360030181905550505050565b600381015460009060f081901c60ff16610e618260f81c90565b149392505050565b8051602082015183516000805160206116ba83398151915292610e8d928492610f25565b505050565b6000610ea2826003015460f81c90565b905060005b6001830154811015610e8d576001811b821615610ed5576003830154610ecf90826001610fdb565b60038401555b80610edf8161156b565b915050610ea7565b600060088210610f095760405162461bcd60e51b8152600401610228906115f7565b6000610f168360f861153d565b6001901b841791505092915050565b6000610f2f611477565b610f37611477565b60008051602061169a833981519152610f528188888861102e565b60018b01805463ffffffff60601b1916600160601b4263ffffffff1602179055604080516001600160a01b03808d1682528b16602082015290810189905292965090945092507f2afbde4d47160a9c5de25b0df88d5b83e705286f2a447cac162db5e99ad6f5d29060600160405180910390a1610fd188858585610986565b5050505050505050565b600060088310610ffd5760405162461bcd60e51b8152600401610228906115f7565b600061100985856111e2565b90506000611017848361153d565b9050611024868683611230565b9695505050505050565b6000611038611477565b611040611477565b61104a87866112e4565b865484036110e45761105b87610e47565b61109f576040805180820182528581526000602080830182905283518085019094526001600160a01b038a168452830181905261109a929091906113b8565b6110d9565b6040805180820182528581526000602080830182905283518085019094526001600160a01b038a1684528301526110d991600191906113b8565b9250925092506111d8565b600387015460f81c1561113d576110d9600260405180604001604052808a6000015481526020018781525060405180604001604052806111238c610d09565b6001600160a01b0390811682528b166020909101526113b8565b83875561114a8787610e1c565b61115387610e47565b611197576040805180820182528581526000602080830182905283518085019094526001600160a01b038a1684528301819052611192929091906113b8565b6111d1565b6040805180820182528581526000602080830182905283518085019094526001600160a01b038a1684528301526111d191600191906113b8565b9250925092505b9450945094915050565b6000600882106112045760405162461bcd60e51b8152600401610228906115f7565b600061121560016340000000611623565b90508061122384601e61163a565b85901c1691505092915050565b6000600883106112525760405162461bcd60e51b8152600401610228906115f7565b61126160016340000000611623565b8211156112a65760405162461bcd60e51b8152602060048201526013602482015272436c61696d734d61736b204f766572666c6f7760681b6044820152606401610228565b60006112b384601e61163a565b6112c260016340000000611623565b901b1990508481166112d585601e61163a565b9390931b909217949350505050565b7f844e22529543d6e722c6477171dd50ffe5b412198b92cd9aeea62bbfabe4cc7360005b6001840154811015610ad65783600101818154811061132957611329611555565b6000918252602090912001546001600160a01b03908116908416036113a657600084600101828154811061135f5761135f611555565b600091825260209091200180546001600160a01b0319166001600160a01b0392909216919091179055600384015461139790826113fd565b6003850155610a46828261145a565b806113b08161156b565b915050611308565b60006113c2611477565b6113ca611477565b7f09201c193a07cae1df95ae692cc698685574c942a04514c48a4c3249f38594ff868686604051610e0893929190611584565b60006008821061141f5760405162461bcd60e51b8152600401610228906115f7565b82600061142d8460f861153d565b6001901b199182169190506114438460f061153d565b6001901b1991821691905061075082856000611230565b600382015461146b90826000611230565b82600301819055505050565b60405180604001604052806002906020820280368337509192915050565b508054600082559060005260206000209081019061076291905b808211156114c357600081556001016114af565b5090565b634e487b7160e01b600052602160045260246000fd5b6003811061076257634e487b7160e01b600052602160045260246000fd5b60208101611508836114dd565b91905290565b60006020828403121561152057600080fd5b5035919050565b634e487b7160e01b600052601160045260246000fd5b6000821982111561155057611550611527565b500190565b634e487b7160e01b600052603260045260246000fd5b60006001820161157d5761157d611527565b5060010190565b60a08101611591856114dd565b84825260208083018560005b60028110156115ba5781518352918301919083019060010161159d565b505050606083018460005b60028110156115eb5781516001600160a01b0316835291830191908301906001016115c5565b50505050949350505050565b602080825260129082015271696e646578206f7574206f662072616e676560701b604082015260600190565b60008282101561163557611635611527565b500390565b600081600019048311821515161561165457611654611527565b50029056fed32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189ded606d544c2202d032d2626c390923e6f260ca5d89625bba0cfe70d2bdda4e8f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fcd32d7f90491bee81172a406b65f3270d810392fe53bb0379dde8bdd4e624189ca264697066735822122005a48434be4f5e94111d6d06fc627e4729c541be34424a5e0fb455dd1e4422ab64736f6c634300080d0033", + "libraries": { + "LibClaimsMask": "0x9A676e781A523b5d0C0e43731313A708CB607508" + }, + "devdoc": { + "kind": "dev", + "methods": { + "claim(bytes32)": { + "details": "ValidatorManager makes sure that msg.sender is allowed and that claim != bytes32(0) TODO: add signatures for aggregated claims", + "params": { + "_epochHash": "hash of epoch" + } + }, + "finalizeEpoch()": { + "details": "can only be called if challenge period is over" + }, + "getCurrentEpoch()": { + "details": "if phase is input accumulation, then the epoch number is length of finalized epochs array, else there are two non finalized epochs, one awaiting consensus/dispute and another accumulating input", + "returns": { + "_0": "index of current epoch" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "Claim(uint256,address,bytes32)": { + "notice": "claim submitted" + }, + "FinalizeEpoch(uint256,bytes32)": { + "notice": "epoch finalized" + }, + "PhaseChange(uint8)": { + "notice": "phase change" + }, + "ResolveDispute(address,address,bytes32)": { + "notice": "dispute resolved" + } + }, + "kind": "user", + "methods": { + "claim(bytes32)": { + "notice": "claim the result of current epoch" + }, + "finalizeEpoch()": { + "notice": "finalize epoch after timeout" + }, + "getChallengePeriod()": { + "notice": "returns the challenge period in seconds" + }, + "getCurrentEpoch()": { + "notice": "returns index of current (accumulating) epoch" + }, + "getCurrentPhase()": { + "notice": "returns the current phase" + }, + "getInputAccumulationStart()": { + "notice": "returns the input accumulation start timestamp" + }, + "getInputDuration()": { + "notice": "returns the input duration in seconds" + }, + "getSealingEpochTimestamp()": { + "notice": "returns the sealing epoch timestamp" + }, + "getTemplateHash()": { + "notice": "returns the machine's template hash" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/SimpleFaucet.json b/echo-js/deployments/localhost/SimpleFaucet.json new file mode 100644 index 00000000..fb238b34 --- /dev/null +++ b/echo-js/deployments/localhost/SimpleFaucet.json @@ -0,0 +1,114 @@ +{ + "address": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + "abi": [ + { + "constant": true, + "inputs": [ + { + "name": "_address", + "type": "address" + } + ], + "name": "allowedToWithdraw", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [], + "name": "requestTokens", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "tokenInstance", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "waitTime", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "tokenAmount", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "name": "_tokenInstance", + "type": "address" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + } + ], + "transactionHash": "0x7715e966bfe11ddea38d18ff072aec7cc49c6ba811be3d78d6cf1d911ac7ffb3", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318", + "transactionIndex": 0, + "gasUsed": "280767", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb8498cc0d27b95c9cf3499642a3fe4173e34671919e0fce1148ca39dab794269", + "transactionHash": "0x7715e966bfe11ddea38d18ff072aec7cc49c6ba811be3d78d6cf1d911ac7ffb3", + "logs": [], + "blockNumber": 10, + "cumulativeGasUsed": "280767", + "status": 1, + "byzantium": true + }, + "args": [ + "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853" + ], + "numDeployments": 1, + "bytecode": "0x608060405234801561001057600080fd5b506040516020806104758339810180604052602081101561003057600080fd5b8101908080519060200190929190505050600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161415151561007d57600080fd5b806000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550506103a8806100cd6000396000f3fe608060405234801561001057600080fd5b50600436106100575760003560e01c80632d291cad1461005c578063359cf2b7146100b8578063658030b3146100c2578063ccca123b1461010c578063eec7faa11461012a575b600080fd5b61009e6004803603602081101561007257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610148565b604051808215151515815260200191505060405180910390f35b6100c06101f5565b005b6100ca610342565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610114610367565b6040518082815260200191505060405180910390f35b61013261036e565b6040518082815260200191505060405180910390f35b600080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561019a57600190506101f0565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054421015156101eb57600190506101f0565b600090505b919050565b6101fe33610148565b151561020957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb3369152d02c7e14af68000006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156102bb57600080fd5b505af11580156102cf573d6000803e3d6000fd5b505050506040513d60208110156102e557600080fd5b8101908080519060200190929190505050506224ea004201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6224ea0081565b69152d02c7e14af68000008156fea165627a7a723058201a95fe0177c1cf4bc787a7385da5ab9120c37ac47a5207b31bfe92023fefe3100029", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100575760003560e01c80632d291cad1461005c578063359cf2b7146100b8578063658030b3146100c2578063ccca123b1461010c578063eec7faa11461012a575b600080fd5b61009e6004803603602081101561007257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050610148565b604051808215151515815260200191505060405180910390f35b6100c06101f5565b005b6100ca610342565b604051808273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b610114610367565b6040518082815260200191505060405180910390f35b61013261036e565b6040518082815260200191505060405180910390f35b600080600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054141561019a57600190506101f0565b600160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054421015156101eb57600190506101f0565b600090505b919050565b6101fe33610148565b151561020957600080fd5b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb3369152d02c7e14af68000006040518363ffffffff1660e01b8152600401808373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200182815260200192505050602060405180830381600087803b1580156102bb57600080fd5b505af11580156102cf573d6000803e3d6000fd5b505050506040513d60208110156102e557600080fd5b8101908080519060200190929190505050506224ea004201600160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002081905550565b6000809054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b6224ea0081565b69152d02c7e14af68000008156fea165627a7a723058201a95fe0177c1cf4bc787a7385da5ab9120c37ac47a5207b31bfe92023fefe3100029", + "devdoc": { + "methods": {} + }, + "userdoc": { + "methods": {} + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/ValidatorManagerFacet.json b/echo-js/deployments/localhost/ValidatorManagerFacet.json new file mode 100644 index 00000000..61c749a9 --- /dev/null +++ b/echo-js/deployments/localhost/ValidatorManagerFacet.json @@ -0,0 +1,294 @@ +{ + "address": "0xc5a5C42992dECbae36851359345FE25997F5C42d", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Result", + "name": "result", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32[2]", + "name": "claims", + "type": "bytes32[2]" + }, + { + "indexed": false, + "internalType": "address payable[2]", + "name": "validators", + "type": "address[2]" + } + ], + "name": "ClaimReceived", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "enum Result", + "name": "result", + "type": "uint8" + }, + { + "indexed": false, + "internalType": "bytes32[2]", + "name": "claims", + "type": "bytes32[2]" + }, + { + "indexed": false, + "internalType": "address payable[2]", + "name": "validators", + "type": "address[2]" + } + ], + "name": "DisputeEnded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "bytes32", + "name": "claim", + "type": "bytes32" + } + ], + "name": "NewEpoch", + "type": "event" + }, + { + "inputs": [], + "name": "getAgreementMask", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getConsensusGoalMask", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getCurrentClaim", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getMaxNumValidators", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_sender", + "type": "address" + } + ], + "name": "getNumberOfClaimsByAddress", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "_index", + "type": "uint256" + } + ], + "name": "getNumberOfClaimsByIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_sender", + "type": "address" + } + ], + "name": "getValidatorIndex", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0xaebc401b4231e3cc9c6f419212e677aafabc809d3b7654a46b68f799fc3b0a65", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xc5a5C42992dECbae36851359345FE25997F5C42d", + "transactionIndex": 0, + "gasUsed": "330748", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x88eabc1025619559e6b04dc2a295af2db58c5ea123090e6999d828b28156a77e", + "transactionHash": "0xaebc401b4231e3cc9c6f419212e677aafabc809d3b7654a46b68f799fc3b0a65", + "logs": [], + "blockNumber": 29, + "cumulativeGasUsed": "330748", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "853463bf44733f3d929a32fa4eacb9e6", + "metadata": "{\"compiler\":{\"version\":\"0.8.13+commit.abaa5c0e\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enum Result\",\"name\":\"result\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32[2]\",\"name\":\"claims\",\"type\":\"bytes32[2]\"},{\"indexed\":false,\"internalType\":\"address payable[2]\",\"name\":\"validators\",\"type\":\"address[2]\"}],\"name\":\"ClaimReceived\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"enum Result\",\"name\":\"result\",\"type\":\"uint8\"},{\"indexed\":false,\"internalType\":\"bytes32[2]\",\"name\":\"claims\",\"type\":\"bytes32[2]\"},{\"indexed\":false,\"internalType\":\"address payable[2]\",\"name\":\"validators\",\"type\":\"address[2]\"}],\"name\":\"DisputeEnded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"claim\",\"type\":\"bytes32\"}],\"name\":\"NewEpoch\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getAgreementMask\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getConsensusGoalMask\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCurrentClaim\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getMaxNumValidators\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_sender\",\"type\":\"address\"}],\"name\":\"getNumberOfClaimsByAddress\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"getNumberOfClaimsByIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"}],\"name\":\"getValidatorIndex\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAgreementMask()\":{\"returns\":{\"_0\":\"current state of agreement mask\"}},\"getConsensusGoalMask()\":{\"returns\":{\"_0\":\"current consensus goal mask\"}},\"getCurrentClaim()\":{\"returns\":{\"_0\":\"current claim\"}},\"getMaxNumValidators()\":{\"returns\":{\"_0\":\"the maximum number of validators\"}},\"getNumberOfClaimsByAddress(address)\":{\"params\":{\"_sender\":\"validator address\"},\"returns\":{\"_0\":\"#claims\"}},\"getNumberOfClaimsByIndex(uint256)\":{\"params\":{\"_index\":\"the index in validator set\"},\"returns\":{\"_0\":\"#claims\"}},\"getValidatorIndex(address)\":{\"params\":{\"_sender\":\"validator address\"},\"returns\":{\"_0\":\"validator index or revert\"}}},\"version\":1},\"userdoc\":{\"events\":{\"ClaimReceived(uint8,bytes32[2],address[2])\":{\"notice\":\"emitted on Claim received\"},\"DisputeEnded(uint8,bytes32[2],address[2])\":{\"notice\":\"emitted on Dispute end\"},\"NewEpoch(bytes32)\":{\"notice\":\"emitted on new Epoch\"}},\"kind\":\"user\",\"methods\":{\"getAgreementMask()\":{\"notice\":\"get agreement mask\"},\"getConsensusGoalMask()\":{\"notice\":\"get consensus goal mask\"},\"getCurrentClaim()\":{\"notice\":\"get current claim\"},\"getMaxNumValidators()\":{\"notice\":\"get the maximum number of validators defined in validator manager\"},\"getNumberOfClaimsByAddress(address)\":{\"notice\":\"get number of claims the sender has made\"},\"getNumberOfClaimsByIndex(uint256)\":{\"notice\":\"get number of claims by the index in the validator set\"},\"getValidatorIndex(address)\":{\"notice\":\"find the validator and return the index or revert\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ValidatorManagerFacet.sol\":\"ValidatorManagerFacet\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"contracts/IBank.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n// @title Bank interface\\npragma solidity ^0.8.0;\\n\\nimport {IERC20} from \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\ninterface IBank {\\n /// @notice returns the token used internally\\n function getToken() external view returns (IERC20);\\n\\n /// @notice get balance of `_owner`\\n /// @param _owner account owner\\n function balanceOf(address _owner) external view returns (uint256);\\n\\n /// @notice transfer `_value` tokens from bank to `_to`\\n /// @notice decrease the balance of caller by `_value`\\n /// @param _to account that will receive `_value` tokens\\n /// @param _value amount of tokens to be transfered\\n function transferTokens(address _to, uint256 _value) external;\\n\\n /// @notice transfer `_value` tokens from caller to bank\\n /// @notice increase the balance of `_to` by `_value`\\n /// @dev you may need to call `token.approve(bank, _value)`\\n /// @param _to account that will have their balance increased by `_value`\\n /// @param _value amount of tokens to be transfered\\n function depositTokens(address _to, uint256 _value) external;\\n\\n /// @notice `value` tokens were transfered from the bank to `to`\\n /// @notice the balance of `from` was decreased by `value`\\n /// @dev is triggered on any successful call to `transferTokens`\\n /// @param from the account/contract that called `transferTokens` and\\n /// got their balance decreased by `value`\\n /// @param to the one that received `value` tokens from the bank\\n /// @param value amount of tokens that were transfered\\n event Transfer(address indexed from, address to, uint256 value);\\n\\n /// @notice `value` tokens were transfered from `from` to bank\\n /// @notice the balance of `to` was increased by `value`\\n /// @dev is triggered on any successful call to `depositTokens`\\n /// @param from the account/contract that called `depositTokens` and\\n /// transfered `value` tokens to the bank\\n /// @param to the one that got their balance increased by `value`\\n /// @param value amount of tokens that were transfered\\n event Deposit(address from, address indexed to, uint256 value);\\n}\\n\",\"keccak256\":\"0x483dc9b0c26e3a5d43148cf847bd4df2af03438a0d76d60d33549de3ca2dd77d\",\"license\":\"Apache-2.0\"},\"contracts/facets/ValidatorManagerFacet.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager facet\\npragma solidity ^0.8.0;\\n\\nimport {IValidatorManager} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\n\\ncontract ValidatorManagerFacet is IValidatorManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n /// @notice get agreement mask\\n /// @return current state of agreement mask\\n function getAgreementMask() public view returns (uint256) {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.claimsMask.getAgreementMask();\\n }\\n\\n /// @notice get consensus goal mask\\n /// @return current consensus goal mask\\n function getConsensusGoalMask() public view returns (uint256) {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get current claim\\n /// @return current claim\\n function getCurrentClaim() public view override returns (bytes32) {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.currentClaim;\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(address payable _sender)\\n public\\n view\\n returns (uint256)\\n {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.getNumberOfClaimsByAddress(_sender);\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param _sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(address _sender) public view returns (uint256) {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.getValidatorIndex(_sender);\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param _index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(uint256 _index)\\n public\\n view\\n returns (uint256)\\n {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.getNumberOfClaimsByIndex(_index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @return the maximum number of validators\\n function getMaxNumValidators() public view returns (uint256) {\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n return validatorManagerDS.getMaxNumValidators();\\n }\\n}\\n\",\"keccak256\":\"0x10f7fe77f1ed0f1e97927589a8b51128ace21e41fd8e4b757f82ee22a8e92abc\",\"license\":\"Apache-2.0\"},\"contracts/interfaces/IValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager interface\\npragma solidity >=0.7.0;\\n\\n// NoConflict - No conflicting claims or consensus\\n// Consensus - All validators had equal claims\\n// Conflict - Claim is conflicting with previous one\\nenum Result {\\n NoConflict,\\n Consensus,\\n Conflict\\n}\\n\\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\\ninterface IValidatorManager {\\n /// @notice get current claim\\n function getCurrentClaim() external view returns (bytes32);\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n}\\n\",\"keccak256\":\"0x7eccbaf15dc80cd402459e8c940b0012fd3d3b8d2882fa13798afe92a9ea3b86\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibClaimsMask.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title ClaimsMask library\\npragma solidity >=0.8.8;\\n\\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\\n// agreement mask and consensus goal mask are not used.\\n\\ntype ClaimsMask is uint256;\\n\\nlibrary LibClaimsMask {\\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\\n\\n /// @notice this function creates a new ClaimsMask variable with value _value\\n /// @param _value the value following the format of ClaimsMask\\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\\n return ClaimsMask.wrap(_value);\\n }\\n\\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\\n /// according to the number of validators\\n /// @param _numValidators the number of validators\\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_numValidators <= 8, \\\"up to 8 validators\\\");\\n uint256 consensusMask = (1 << _numValidators) - 1;\\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\\n }\\n\\n /// @notice this function returns the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (uint256)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 bitmask = (1 << claimsBitLen) - 1;\\n return\\n (ClaimsMask.unwrap(_claimsMask) >>\\n (claimsBitLen * _validatorIndex)) & bitmask;\\n }\\n\\n /// @notice this function increases the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the increase amount\\n function increaseNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\\n }\\n\\n /// @notice this function sets the #claims for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n /// @param _value the set value\\n function setNumClaims(\\n ClaimsMask _claimsMask,\\n uint256 _validatorIndex,\\n uint256 _value\\n ) internal pure returns (ClaimsMask) {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n require(_value <= ((1 << claimsBitLen) - 1), \\\"ClaimsMask Overflow\\\");\\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\\n (claimsBitLen * _validatorIndex));\\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\\n _claimsMask = ClaimsMask.wrap(\\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\\n );\\n return _claimsMask;\\n }\\n\\n /// @notice get consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function clearAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\\n return ClaimsMask.wrap(clearedMask);\\n }\\n\\n /// @notice get the entire agreement mask\\n /// @param _claimsMask the ClaimsMask value\\n function getAgreementMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\\n }\\n\\n /// @notice check if a validator has already claimed\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (bool)\\n {\\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\\n return\\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\\n 1) != 0;\\n }\\n\\n /// @notice set agreement mask for the specified validator\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\\n return ClaimsMask.wrap(setMask);\\n }\\n\\n /// @notice get the entire consensus goal mask\\n /// @param _claimsMask the ClaimsMask value\\n function getConsensusGoalMask(ClaimsMask _claimsMask)\\n internal\\n pure\\n returns (uint256)\\n {\\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\\n }\\n\\n /// @notice remove validator from the ClaimsMask\\n /// @param _claimsMask the ClaimsMask value\\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\\n internal\\n pure\\n returns (ClaimsMask)\\n {\\n require(_validatorIndex < 8, \\\"index out of range\\\");\\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\\n // remove validator from agreement bitmask\\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from consensus goal mask\\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\\n claimsMaskValue = (claimsMaskValue & zeroMask);\\n // remove validator from #claims\\n return\\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\\n }\\n}\\n\",\"keccak256\":\"0x80b7355ef8d176c87e9c446542c4a7de8ee208601639af8acc23f6854f8f0080\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibFeeManager.sol\":{\"content\":\"// Copyright 2022 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Fee Manager library\\npragma solidity ^0.8.0;\\n\\nimport {LibValidatorManager} from \\\"../libraries/LibValidatorManager.sol\\\";\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {IBank} from \\\"../IBank.sol\\\";\\n\\nlibrary LibFeeManager {\\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n using LibClaimsMask for ClaimsMask;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"FeeManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n address owner; // owner of Fee Manager\\n uint256 feePerClaim;\\n IBank bank; // bank that holds the tokens to pay validators\\n bool lock; // reentrancy lock\\n // A bit set used for up to 8 validators.\\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask numClaimsRedeemed;\\n }\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n function onlyOwner(DiamondStorage storage ds) internal view {\\n require(ds.owner == msg.sender, \\\"caller is not the owner\\\");\\n }\\n\\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\\n valIndex\\n );\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n // underflow checked by default with sol0.8\\n // which means if the validator is removed, calling this function will\\n // either return 0 or revert\\n return totalClaims - redeemedClaims;\\n }\\n\\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator\\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\\n internal\\n view\\n returns (uint256)\\n {\\n require(_validator != address(0), \\\"address should not be 0\\\");\\n\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\\n\\n return redeemedClaims;\\n }\\n\\n /// @notice contract owner can reset the value of fee per claim\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _value the new value of fee per claim\\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\\n internal\\n {\\n // before resetting the feePerClaim, pay fees for all validators as per current rates\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n for (\\n uint256 valIndex;\\n valIndex < validatorManagerDS.maxNumValidators;\\n valIndex++\\n ) {\\n address validator = validatorManagerDS.validators[valIndex];\\n if (validator != address(0)) {\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\\n if (nowRedeemingClaims > 0) {\\n ds.numClaimsRedeemed = ds\\n .numClaimsRedeemed\\n .increaseNumClaims(valIndex, nowRedeemingClaims);\\n\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(validator, nowRedeemingClaims);\\n }\\n }\\n }\\n ds.feePerClaim = _value;\\n emit FeePerClaimReset(_value);\\n }\\n\\n /// @notice this function can be called to redeem fees for validators\\n /// @param ds pointer to FeeManager's diamond storage\\n /// @param _validator address of the validator that is redeeming\\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\\n // follow the Checks-Effects-Interactions pattern for security\\n\\n // ** checks **\\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\\n require(nowRedeemingClaims > 0, \\\"nothing to redeem yet\\\");\\n\\n // ** effects **\\n LibValidatorManager.DiamondStorage\\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\\n valIndex,\\n nowRedeemingClaims\\n );\\n\\n // ** interactions **\\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\\n // emit the number of claimed being redeemed, instead of the amount of tokens\\n emit FeeRedeemed(_validator, nowRedeemingClaims);\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param index index of validator to be removed\\n function removeValidator(DiamondStorage storage ds, uint256 index)\\n internal\\n {\\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\\n }\\n\\n /// @notice emitted on resetting feePerClaim\\n event FeePerClaimReset(uint256 value);\\n\\n /// @notice emitted on ERC20 funds redeemed by validator\\n event FeeRedeemed(address validator, uint256 claims);\\n}\\n\",\"keccak256\":\"0xb06531049bb43f957ad6fd40635bbfdd16668bf0cc3dc637f11535122e9ce968\",\"license\":\"Apache-2.0\"},\"contracts/libraries/LibValidatorManager.sol\":{\"content\":\"// Copyright 2021 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title Validator Manager library\\npragma solidity ^0.8.0;\\n\\nimport {Result} from \\\"../interfaces/IValidatorManager.sol\\\";\\n\\nimport {LibClaimsMask, ClaimsMask} from \\\"../libraries/LibClaimsMask.sol\\\";\\nimport {LibFeeManager} from \\\"../libraries/LibFeeManager.sol\\\";\\n\\nlibrary LibValidatorManager {\\n using LibClaimsMask for ClaimsMask;\\n using LibFeeManager for LibFeeManager.DiamondStorage;\\n\\n bytes32 constant DIAMOND_STORAGE_POSITION =\\n keccak256(\\\"ValidatorManager.diamond.storage\\\");\\n\\n struct DiamondStorage {\\n bytes32 currentClaim; // current claim - first claim of this epoch\\n address payable[] validators; // up to 8 validators\\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\\n // A bit set used for up to 8 validators.\\n // The first 8 bits are used to indicate whom supports the current claim\\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\\n // The following every 30 bits are used to indicate the number of total claims each validator has made\\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\\n ClaimsMask claimsMask;\\n }\\n\\n /// @notice emitted on Claim received\\n event ClaimReceived(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on Dispute end\\n event DisputeEnded(\\n Result result,\\n bytes32[2] claims,\\n address payable[2] validators\\n );\\n\\n /// @notice emitted on new Epoch\\n event NewEpoch(bytes32 claim);\\n\\n function diamondStorage()\\n internal\\n pure\\n returns (DiamondStorage storage ds)\\n {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n /// @notice called when a dispute ends in rollups\\n /// @param ds diamond storage pointer\\n /// @param winner address of dispute winner\\n /// @param loser address of dispute loser\\n /// @param winningClaim the winnning claim\\n /// @return result of dispute being finished\\n function onDisputeEnd(\\n DiamondStorage storage ds,\\n address payable winner,\\n address payable loser,\\n bytes32 winningClaim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n removeValidator(ds, loser);\\n\\n if (winningClaim == ds.currentClaim) {\\n // first claim stood, dont need to update the bitmask\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n // if first claim lost, and other validators have agreed with it\\n // there is a new dispute to be played\\n if (ds.claimsMask.getAgreementMask() != 0) {\\n return\\n emitDisputeEndedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, winningClaim],\\n [getClaimerOfCurrentClaim(ds), winner]\\n );\\n }\\n // else there are no valdiators that agree with losing claim\\n // we can update current claim and check for consensus in case\\n // the winner is the only validator left\\n ds.currentClaim = winningClaim;\\n updateClaimAgreementMask(ds, winner);\\n return\\n isConsensus(ds)\\n ? emitDisputeEndedAndReturn(\\n Result.Consensus,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n )\\n : emitDisputeEndedAndReturn(\\n Result.NoConflict,\\n [winningClaim, bytes32(0)],\\n [winner, payable(0)]\\n );\\n }\\n\\n /// @notice called when a new epoch starts\\n /// @param ds diamond storage pointer\\n /// @return current claim\\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\\n // reward validators who has made the correct claim by increasing their #claims\\n claimFinalizedIncreaseCounts(ds);\\n\\n bytes32 tmpClaim = ds.currentClaim;\\n\\n // clear current claim\\n ds.currentClaim = bytes32(0);\\n // clear validator agreement bit mask\\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\\n\\n emit NewEpoch(tmpClaim);\\n return tmpClaim;\\n }\\n\\n /// @notice called when a claim is received by rollups\\n /// @param ds diamond storage pointer\\n /// @param sender address of sender of that claim\\n /// @param claim claim received by rollups\\n /// @return result of claim, Consensus | NoConflict | Conflict\\n /// @return [currentClaim, conflicting claim] if there is Conflict\\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\\n /// @return [claimer1, claimer2] if there is Conflcit\\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\\n function onClaim(\\n DiamondStorage storage ds,\\n address payable sender,\\n bytes32 claim\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n require(claim != bytes32(0), \\\"empty claim\\\");\\n require(isValidator(ds, sender), \\\"sender not allowed\\\");\\n\\n // require the validator hasn't claimed in the same epoch before\\n uint256 index = getValidatorIndex(ds, sender);\\n require(\\n !ds.claimsMask.alreadyClaimed(index),\\n \\\"sender had claimed in this epoch before\\\"\\n );\\n\\n // cant return because a single claim might mean consensus\\n if (ds.currentClaim == bytes32(0)) {\\n ds.currentClaim = claim;\\n } else if (claim != ds.currentClaim) {\\n return\\n emitClaimReceivedAndReturn(\\n Result.Conflict,\\n [ds.currentClaim, claim],\\n [getClaimerOfCurrentClaim(ds), sender]\\n );\\n }\\n updateClaimAgreementMask(ds, sender);\\n\\n return\\n isConsensus(ds)\\n ? emitClaimReceivedAndReturn(\\n Result.Consensus,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n )\\n : emitClaimReceivedAndReturn(\\n Result.NoConflict,\\n [claim, bytes32(0)],\\n [sender, payable(0)]\\n );\\n }\\n\\n /// @notice emits dispute ended event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitDisputeEndedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit DisputeEnded(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice emits claim received event and then return\\n /// @param result to be emitted and returned\\n /// @param claims to be emitted and returned\\n /// @param validators to be emitted and returned\\n /// @dev this function existis to make code more clear/concise\\n function emitClaimReceivedAndReturn(\\n Result result,\\n bytes32[2] memory claims,\\n address payable[2] memory validators\\n )\\n internal\\n returns (\\n Result,\\n bytes32[2] memory,\\n address payable[2] memory\\n )\\n {\\n emit ClaimReceived(result, claims, validators);\\n return (result, claims, validators);\\n }\\n\\n /// @notice only call this function when a claim has been finalized\\n /// Either a consensus has been reached or challenge period has past\\n /// @param ds pointer to diamond storage\\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n // if a validator agrees with the current claim\\n if ((agreementMask & (1 << i)) != 0) {\\n // increase #claims by 1\\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\\n }\\n }\\n }\\n\\n /// @notice removes a validator\\n /// @param ds diamond storage pointer\\n /// @param validator address of validator to be removed\\n function removeValidator(DiamondStorage storage ds, address validator)\\n internal\\n {\\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\\n .diamondStorage();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (validator == ds.validators[i]) {\\n // put address(0) in validators position\\n ds.validators[i] = payable(0);\\n // remove the validator from ValidatorManager's claimsMask\\n ds.claimsMask = ds.claimsMask.removeValidator(i);\\n // remove the validator from FeeManager's claimsMask (#redeems)\\n feeManagerDS.removeValidator(i);\\n break;\\n }\\n }\\n }\\n\\n /// @notice check if consensus has been reached\\n /// @param ds pointer to diamond storage\\n function isConsensus(DiamondStorage storage ds)\\n internal\\n view\\n returns (bool)\\n {\\n ClaimsMask claimsMask = ds.claimsMask;\\n return\\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\\n }\\n\\n /// @notice get one of the validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @return validator that agreed with current claim\\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\\n internal\\n view\\n returns (address payable)\\n {\\n // TODO: we are always getting the first validator\\n // on the array that agrees with the current claim to enter a dispute\\n // should this be random?\\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (agreementMask & (1 << i) != 0) {\\n return ds.validators[i];\\n }\\n }\\n revert(\\\"Agreeing validator not found\\\");\\n }\\n\\n /// @notice updates mask of validators that agreed with current claim\\n /// @param ds diamond storage pointer\\n /// @param sender address of validator that will be included in mask\\n function updateClaimAgreementMask(\\n DiamondStorage storage ds,\\n address payable sender\\n ) internal {\\n uint256 validatorIndex = getValidatorIndex(ds, sender);\\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\\n }\\n\\n /// @notice check if the sender is a validator\\n /// @param ds pointer to diamond storage\\n /// @param sender sender address\\n function isValidator(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (bool)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return true;\\n }\\n\\n return false;\\n }\\n\\n /// @notice find the validator and return the index or revert\\n /// @param ds pointer to diamond storage\\n /// @param sender validator address\\n /// @return validator index or revert\\n function getValidatorIndex(DiamondStorage storage ds, address sender)\\n internal\\n view\\n returns (uint256)\\n {\\n require(sender != address(0), \\\"address 0\\\");\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (sender == ds.validators[i]) return i;\\n }\\n revert(\\\"validator not found\\\");\\n }\\n\\n /// @notice get number of claims the sender has made\\n /// @param ds pointer to diamond storage\\n /// @param _sender validator address\\n /// @return #claims\\n function getNumberOfClaimsByAddress(\\n DiamondStorage storage ds,\\n address payable _sender\\n ) internal view returns (uint256) {\\n for (uint256 i; i < ds.validators.length; i++) {\\n if (_sender == ds.validators[i]) {\\n return getNumberOfClaimsByIndex(ds, i);\\n }\\n }\\n // if validator not found\\n return 0;\\n }\\n\\n /// @notice get number of claims by the index in the validator set\\n /// @param ds pointer to diamond storage\\n /// @param index the index in validator set\\n /// @return #claims\\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.claimsMask.getNumClaims(index);\\n }\\n\\n /// @notice get the maximum number of validators defined in validator manager\\n /// @param ds pointer to diamond storage\\n /// @return the maximum number of validators\\n function getMaxNumValidators(DiamondStorage storage ds)\\n internal\\n view\\n returns (uint256)\\n {\\n return ds.maxNumValidators;\\n }\\n}\\n\",\"keccak256\":\"0xc5c11d8a0f745c785a8ca19b27f3ab232a53ecdab6b179b4d0c5df353690bce5\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610506806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c80638219fda41161005b5780638219fda4146100c2578063cc8a2451146100d7578063d2992f54146100ea578063f6023815146100f257600080fd5b8063101494ce146100825780631fcc449e1461009c57806355564a70146100af575b600080fd5b61008a6100fa565b60405190815260200160405180910390f35b61008a6100aa3660046103ff565b610139565b61008a6100bd3660046103ff565b61015b565b6000805160206104b18339815191525461008a565b61008a6100e536600461041c565b610176565b61008a610191565b61008a6101cb565b7f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1ff546000906000805160206104b18339815191529060f81c5b91505090565b60006000805160206104b1833981519152610154818461020b565b9392505050565b60006000805160206104b183398151915261015481846102f5565b60006000805160206104b18339815191526101548184610367565b7f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fe546000906000805160206104b183398151915290610133565b7f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1ff546000906000805160206104b18339815191529060f01c60ff16610133565b60006001600160a01b0382166102545760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b60448201526064015b60405180910390fd5b60005b60018401548110156102b05783600101818154811061027857610278610435565b6000918252602090912001546001600160a01b039081169084160361029e5790506102ef565b806102a881610461565b915050610257565b5060405162461bcd60e51b81526020600482015260136024820152721d985b1a59185d1bdc881b9bdd08199bdd5b99606a1b604482015260640161024b565b92915050565b6000805b600184015481101561035d5783600101818154811061031a5761031a610435565b6000918252602090912001546001600160a01b039081169084160361034b576103438482610367565b9150506102ef565b8061035581610461565b9150506102f9565b5060009392505050565b600382015460009061015490836000600882106103bb5760405162461bcd60e51b8152602060048201526012602482015271696e646578206f7574206f662072616e676560701b604482015260640161024b565b60006103cc6001634000000061047a565b9050806103da84601e610491565b85901c1691505092915050565b6001600160a01b03811681146103fc57600080fd5b50565b60006020828403121561041157600080fd5b8135610154816103e7565b60006020828403121561042e57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016104735761047361044b565b5060010190565b60008282101561048c5761048c61044b565b500390565b60008160001904831182151516156104ab576104ab61044b565b50029056fe8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fca26469706673582212202b700a34055d7bd57f021e5c896711657796122af288967d1a632e9fce47fadb64736f6c634300080d0033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c80638219fda41161005b5780638219fda4146100c2578063cc8a2451146100d7578063d2992f54146100ea578063f6023815146100f257600080fd5b8063101494ce146100825780631fcc449e1461009c57806355564a70146100af575b600080fd5b61008a6100fa565b60405190815260200160405180910390f35b61008a6100aa3660046103ff565b610139565b61008a6100bd3660046103ff565b61015b565b6000805160206104b18339815191525461008a565b61008a6100e536600461041c565b610176565b61008a610191565b61008a6101cb565b7f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1ff546000906000805160206104b18339815191529060f81c5b91505090565b60006000805160206104b1833981519152610154818461020b565b9392505050565b60006000805160206104b183398151915261015481846102f5565b60006000805160206104b18339815191526101548184610367565b7f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fe546000906000805160206104b183398151915290610133565b7f8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1ff546000906000805160206104b18339815191529060f01c60ff16610133565b60006001600160a01b0382166102545760405162461bcd60e51b815260206004820152600960248201526806164647265737320360bc1b60448201526064015b60405180910390fd5b60005b60018401548110156102b05783600101818154811061027857610278610435565b6000918252602090912001546001600160a01b039081169084160361029e5790506102ef565b806102a881610461565b915050610257565b5060405162461bcd60e51b81526020600482015260136024820152721d985b1a59185d1bdc881b9bdd08199bdd5b99606a1b604482015260640161024b565b92915050565b6000805b600184015481101561035d5783600101818154811061031a5761031a610435565b6000918252602090912001546001600160a01b039081169084160361034b576103438482610367565b9150506102ef565b8061035581610461565b9150506102f9565b5060009392505050565b600382015460009061015490836000600882106103bb5760405162461bcd60e51b8152602060048201526012602482015271696e646578206f7574206f662072616e676560701b604482015260640161024b565b60006103cc6001634000000061047a565b9050806103da84601e610491565b85901c1691505092915050565b6001600160a01b03811681146103fc57600080fd5b50565b60006020828403121561041157600080fd5b8135610154816103e7565b60006020828403121561042e57600080fd5b5035919050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600182016104735761047361044b565b5060010190565b60008282101561048c5761048c61044b565b500390565b60008160001904831182151516156104ab576104ab61044b565b50029056fe8ab37fef2b2e34c4b62ff9948ee661cdcf34e209d7c20f4d1f6e83085e93b1fca26469706673582212202b700a34055d7bd57f021e5c896711657796122af288967d1a632e9fce47fadb64736f6c634300080d0033", + "libraries": { + "LibClaimsMask": "0x9A676e781A523b5d0C0e43731313A708CB607508" + }, + "devdoc": { + "kind": "dev", + "methods": { + "getAgreementMask()": { + "returns": { + "_0": "current state of agreement mask" + } + }, + "getConsensusGoalMask()": { + "returns": { + "_0": "current consensus goal mask" + } + }, + "getCurrentClaim()": { + "returns": { + "_0": "current claim" + } + }, + "getMaxNumValidators()": { + "returns": { + "_0": "the maximum number of validators" + } + }, + "getNumberOfClaimsByAddress(address)": { + "params": { + "_sender": "validator address" + }, + "returns": { + "_0": "#claims" + } + }, + "getNumberOfClaimsByIndex(uint256)": { + "params": { + "_index": "the index in validator set" + }, + "returns": { + "_0": "#claims" + } + }, + "getValidatorIndex(address)": { + "params": { + "_sender": "validator address" + }, + "returns": { + "_0": "validator index or revert" + } + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "ClaimReceived(uint8,bytes32[2],address[2])": { + "notice": "emitted on Claim received" + }, + "DisputeEnded(uint8,bytes32[2],address[2])": { + "notice": "emitted on Dispute end" + }, + "NewEpoch(bytes32)": { + "notice": "emitted on new Epoch" + } + }, + "kind": "user", + "methods": { + "getAgreementMask()": { + "notice": "get agreement mask" + }, + "getConsensusGoalMask()": { + "notice": "get consensus goal mask" + }, + "getCurrentClaim()": { + "notice": "get current claim" + }, + "getMaxNumValidators()": { + "notice": "get the maximum number of validators defined in validator manager" + }, + "getNumberOfClaimsByAddress(address)": { + "notice": "get number of claims the sender has made" + }, + "getNumberOfClaimsByIndex(uint256)": { + "notice": "get number of claims by the index in the validator set" + }, + "getValidatorIndex(address)": { + "notice": "find the validator and return the index or revert" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/WorkerAuthManagerImpl.json b/echo-js/deployments/localhost/WorkerAuthManagerImpl.json new file mode 100644 index 00000000..a3e633b8 --- /dev/null +++ b/echo-js/deployments/localhost/WorkerAuthManagerImpl.json @@ -0,0 +1,255 @@ +{ + "address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "_workerManager", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dapp", + "type": "address" + } + ], + "name": "Authorization", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dapp", + "type": "address" + } + ], + "name": "Deauthorization", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "authorize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "deauthorize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "isAuthorized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x7a4792ed907c93f174bd72de48d6e9c24dc679b57bbb861923aeb90a6756295b", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707", + "transactionIndex": 0, + "gasUsed": "425367", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xf0fd01a7d8a70fa3cc56b023076be1c3a0dd4d2386e00560975abb5c52b43624", + "transactionHash": "0x7a4792ed907c93f174bd72de48d6e9c24dc679b57bbb861923aeb90a6756295b", + "logs": [], + "blockNumber": 6, + "cumulativeGasUsed": "425367", + "status": 1, + "byzantium": true + }, + "args": [ + "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9" + ], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerManager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dapp\",\"type\":\"address\"}],\"name\":\"Authorization\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dapp\",\"type\":\"address\"}],\"name\":\"Deauthorization\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"authorize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"deauthorize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"isAuthorized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"authorize(address,address)\":{\"params\":{\"_dappAddress\":\"address of the dapp that permission will be given to\",\"_workerAddress\":\"address of the worker node to given permission\"}},\"isAuthorized(address,address)\":{\"params\":{\"_dappAddress\":\"address of the DApp\",\"_workerAddress\":\"address of the worker\"}}},\"stateVariables\":{\"permissions\":{\"details\":\"permissions keyed by hash(user, worker, dapp)\"}},\"version\":1},\"userdoc\":{\"events\":{\"Authorization(address,address,address)\":{\"notice\":\"A DApp has been authorized by a user for a worker\"},\"Deauthorization(address,address,address)\":{\"notice\":\"A DApp has been deauthorized by a user for a worker\"}},\"kind\":\"user\",\"methods\":{\"authorize(address,address)\":{\"notice\":\"Gives worker permission to act on a DApp\"},\"isAuthorized(address,address)\":{\"notice\":\"Returns is the dapp is authorized to be called by that worker\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/WorkerAuthManagerImpl.sol\":\"WorkerAuthManagerImpl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/WorkerAuthManager.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerAuthManager\\n/// @author Danilo Tuler\\npragma solidity >=0.7.0;\\n\\ninterface WorkerAuthManager {\\n /// @notice Gives worker permission to act on a DApp\\n /// @param _workerAddress address of the worker node to given permission\\n /// @param _dappAddress address of the dapp that permission will be given to\\n function authorize(address _workerAddress, address _dappAddress) external;\\n\\n /// @notice Removes worker's permission to act on a DApp\\n /// @param _workerAddress address of the proxy that will lose permission\\n /// @param _dappAddresses addresses of dapps that will lose permission\\n function deauthorize(address _workerAddress, address _dappAddresses)\\n external;\\n\\n /// @notice Returns is the dapp is authorized to be called by that worker\\n /// @param _workerAddress address of the worker\\n /// @param _dappAddress address of the DApp\\n function isAuthorized(address _workerAddress, address _dappAddress)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Get the owner of the worker node\\n /// @param workerAddress address of the worker node\\n function getOwner(address workerAddress) external view returns (address);\\n\\n /// @notice A DApp has been authorized by a user for a worker\\n event Authorization(\\n address indexed user,\\n address indexed worker,\\n address indexed dapp\\n );\\n\\n /// @notice A DApp has been deauthorized by a user for a worker\\n event Deauthorization(\\n address indexed user,\\n address indexed worker,\\n address indexed dapp\\n );\\n}\\n\",\"keccak256\":\"0xb69b2fc75aae609d5a4098b77fb8f48dc87ff8073a8a3b70c0261af5f62f36db\",\"license\":\"Apache-2.0\"},\"contracts/WorkerAuthManagerImpl.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerAuthManagerImpl\\n/// @author Danilo Tuler\\npragma solidity ^0.8.0;\\n\\nimport \\\"./WorkerManager.sol\\\";\\nimport \\\"./WorkerAuthManager.sol\\\";\\n\\ncontract WorkerAuthManagerImpl is WorkerAuthManager {\\n WorkerManager workerManager;\\n\\n /// @dev permissions keyed by hash(user, worker, dapp)\\n mapping(bytes32 => bool) private permissions;\\n\\n constructor(address _workerManager) {\\n workerManager = WorkerManager(_workerManager);\\n }\\n\\n modifier onlyByOwner(address _workerAddress) {\\n require(\\n workerManager.getOwner(_workerAddress) == msg.sender,\\n \\\"worker not hired by sender\\\"\\n );\\n _;\\n }\\n\\n function getAuthorizationKey(\\n address _user,\\n address _worker,\\n address _dapp\\n ) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_user, _worker, _dapp));\\n }\\n\\n function authorize(address _workerAddress, address _dappAddress)\\n public\\n override\\n onlyByOwner(_workerAddress)\\n {\\n bytes32 key = getAuthorizationKey(\\n msg.sender,\\n _workerAddress,\\n _dappAddress\\n );\\n require(permissions[key] == false, \\\"dapp already authorized\\\");\\n\\n // record authorization from that user\\n permissions[key] = true;\\n\\n // emit event\\n emit Authorization(msg.sender, _workerAddress, _dappAddress);\\n }\\n\\n function deauthorize(address _workerAddress, address _dappAddress)\\n public\\n override\\n onlyByOwner(_workerAddress)\\n {\\n bytes32 key = getAuthorizationKey(\\n msg.sender,\\n _workerAddress,\\n _dappAddress\\n );\\n require(permissions[key] == true, \\\"dapp not authorized\\\");\\n\\n // record deauthorization from that user\\n permissions[key] = false;\\n\\n // emit event\\n emit Deauthorization(msg.sender, _workerAddress, _dappAddress);\\n }\\n\\n function isAuthorized(address _workerAddress, address _dappAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return\\n permissions[getAuthorizationKey(\\n workerManager.getOwner(_workerAddress),\\n _workerAddress,\\n _dappAddress\\n )];\\n }\\n\\n function getOwner(address _workerAddress)\\n public\\n override\\n view\\n returns (address)\\n {\\n return workerManager.getOwner(_workerAddress);\\n }\\n\\n /*\\n // XXX: we can't do this because the worker need to accept the job before receiving an authorization\\n function hireAndAuthorize(\\n address payable _workerAddress,\\n address _dappAddress\\n ) public override payable {\\n workerManager.hire(_workerAddress);\\n authorize(_workerAddress, _dappAddress);\\n }\\n */\\n}\\n\",\"keccak256\":\"0x3c97f9e58f8190f0a081cf753c47dec51806ec4994ed66608e73522086ae0785\",\"license\":\"Apache-2.0\"},\"contracts/WorkerManager.sol\":{\"content\":\"// Copyright 2010 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerManager\\n/// @author Danilo Tuler\\npragma solidity >=0.7.0;\\n\\ninterface WorkerManager {\\n /// @notice Returns true if worker node is available\\n /// @param workerAddress address of the worker node\\n function isAvailable(address workerAddress) external view returns (bool);\\n\\n /// @notice Returns true if worker node is pending\\n /// @param workerAddress address of the worker node\\n function isPending(address workerAddress) external view returns (bool);\\n\\n /// @notice Get the owner of the worker node\\n /// @param workerAddress address of the worker node\\n function getOwner(address workerAddress) external view returns (address);\\n\\n /// @notice Get the user of the worker node, which may not be the owner yet, or how was the previous owner of a retired node\\n function getUser(address workerAddress) external view returns (address);\\n\\n /// @notice Returns true if worker node is owned by some user\\n function isOwned(address workerAddress) external view returns (bool);\\n\\n /// @notice Asks the worker to work for the sender. Sender needs to pay something.\\n /// @param workerAddress address of the worker\\n function hire(address payable workerAddress) external payable;\\n\\n /// @notice Called by the worker to accept the job\\n function acceptJob() external;\\n\\n /// @notice Called by the worker to reject a job offer\\n function rejectJob() external payable;\\n\\n /// @notice Called by the user to cancel a job offer\\n /// @param workerAddress address of the worker node\\n function cancelHire(address workerAddress) external;\\n\\n /// @notice Called by the user to retire his worker.\\n /// @param workerAddress address of the worker to be retired\\n /// @dev this also removes all authorizations in place\\n function retire(address payable workerAddress) external;\\n\\n /// @notice Returns true if worker node was retired by its owner\\n function isRetired(address workerAddress) external view returns (bool);\\n\\n /// @notice Events signalling every state transition\\n event JobOffer(address indexed worker, address indexed user);\\n event JobAccepted(address indexed worker, address indexed user);\\n event JobRejected(address indexed worker, address indexed user);\\n event Retired(address indexed worker, address indexed user);\\n}\\n\",\"keccak256\":\"0xb93bac1de98b3fb44421c2498f11bcd246795c7cffeeebb535a046e88c303410\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506040516106dc3803806106dc83398101604081905261002f91610054565b600080546001600160a01b0319166001600160a01b0392909216919091179055610082565b600060208284031215610065578081fd5b81516001600160a01b038116811461007b578182fd5b9392505050565b61064b806100916000396000f3fe608060405234801561001057600080fd5b506004361061004c5760003560e01c80632bef45951461005157806365e4ad9e146100665780636d892f7e1461008e578063fa544161146100a1575b600080fd5b61006461005f3660046105c5565b6100cc565b005b6100796100743660046105c5565b61026f565b60405190151581526020015b60405180910390f35b61006461009c3660046105c5565b610318565b6100b46100af366004610586565b6104ad565b6040516001600160a01b039091168152602001610085565b60005460405163fa54416160e01b81526001600160a01b0380851660048301528492339291169063fa5441619060240160206040518083038186803b15801561011457600080fd5b505afa158015610128573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014c91906105a9565b6001600160a01b0316146101a75760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e64657200000000000060448201526064015b60405180910390fd5b60006101b4338585610531565b60008181526001602052604090205490915060ff16156102165760405162461bcd60e51b815260206004820152601760248201527f6461707020616c726561647920617574686f72697a6564000000000000000000604482015260640161019e565b6000818152600160208190526040808320805460ff1916909217909155516001600160a01b03808616929087169133917fde756a416a233cdb16c23a1fa5dcb3113164968df8607e0a4eeca25974b96e0391a450505050565b6000805460405163fa54416160e01b81526001600160a01b03858116600483015260019284926102fd929091169063fa5441619060240160206040518083038186803b1580156102be57600080fd5b505afa1580156102d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f691906105a9565b8686610531565b815260208101919091526040016000205460ff169392505050565b60005460405163fa54416160e01b81526001600160a01b0380851660048301528492339291169063fa5441619060240160206040518083038186803b15801561036057600080fd5b505afa158015610374573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039891906105a9565b6001600160a01b0316146103ee5760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e646572000000000000604482015260640161019e565b60006103fb338585610531565b60008181526001602081905260409091205491925060ff90911615151461045a5760405162461bcd60e51b815260206004820152601360248201527219185c1c081b9bdd08185d5d1a1bdc9a5e9959606a1b604482015260640161019e565b600081815260016020526040808220805460ff19169055516001600160a01b03808616929087169133917f4d2275ddb8a6d9c36c95476c2eaf9746c1785b4ab76a99719fd647b36da46cee91a450505050565b6000805460405163fa54416160e01b81526001600160a01b0384811660048301529091169063fa5441619060240160206040518083038186803b1580156104f357600080fd5b505afa158015610507573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052b91906105a9565b92915050565b6040516bffffffffffffffffffffffff19606085811b8216602084015284811b8216603484015283901b166048820152600090605c016040516020818303038152906040528051906020012090509392505050565b600060208284031215610597578081fd5b81356105a2816105fd565b9392505050565b6000602082840312156105ba578081fd5b81516105a2816105fd565b600080604083850312156105d7578081fd5b82356105e2816105fd565b915060208301356105f2816105fd565b809150509250929050565b6001600160a01b038116811461061257600080fd5b5056fea2646970667358221220b1862e5175b3b9a9fc5da21d120da98326517836ca159b01590210084513622d64736f6c63430008040033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061004c5760003560e01c80632bef45951461005157806365e4ad9e146100665780636d892f7e1461008e578063fa544161146100a1575b600080fd5b61006461005f3660046105c5565b6100cc565b005b6100796100743660046105c5565b61026f565b60405190151581526020015b60405180910390f35b61006461009c3660046105c5565b610318565b6100b46100af366004610586565b6104ad565b6040516001600160a01b039091168152602001610085565b60005460405163fa54416160e01b81526001600160a01b0380851660048301528492339291169063fa5441619060240160206040518083038186803b15801561011457600080fd5b505afa158015610128573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061014c91906105a9565b6001600160a01b0316146101a75760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e64657200000000000060448201526064015b60405180910390fd5b60006101b4338585610531565b60008181526001602052604090205490915060ff16156102165760405162461bcd60e51b815260206004820152601760248201527f6461707020616c726561647920617574686f72697a6564000000000000000000604482015260640161019e565b6000818152600160208190526040808320805460ff1916909217909155516001600160a01b03808616929087169133917fde756a416a233cdb16c23a1fa5dcb3113164968df8607e0a4eeca25974b96e0391a450505050565b6000805460405163fa54416160e01b81526001600160a01b03858116600483015260019284926102fd929091169063fa5441619060240160206040518083038186803b1580156102be57600080fd5b505afa1580156102d2573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102f691906105a9565b8686610531565b815260208101919091526040016000205460ff169392505050565b60005460405163fa54416160e01b81526001600160a01b0380851660048301528492339291169063fa5441619060240160206040518083038186803b15801561036057600080fd5b505afa158015610374573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061039891906105a9565b6001600160a01b0316146103ee5760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e646572000000000000604482015260640161019e565b60006103fb338585610531565b60008181526001602081905260409091205491925060ff90911615151461045a5760405162461bcd60e51b815260206004820152601360248201527219185c1c081b9bdd08185d5d1a1bdc9a5e9959606a1b604482015260640161019e565b600081815260016020526040808220805460ff19169055516001600160a01b03808616929087169133917f4d2275ddb8a6d9c36c95476c2eaf9746c1785b4ab76a99719fd647b36da46cee91a450505050565b6000805460405163fa54416160e01b81526001600160a01b0384811660048301529091169063fa5441619060240160206040518083038186803b1580156104f357600080fd5b505afa158015610507573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061052b91906105a9565b92915050565b6040516bffffffffffffffffffffffff19606085811b8216602084015284811b8216603484015283901b166048820152600090605c016040516020818303038152906040528051906020012090509392505050565b600060208284031215610597578081fd5b81356105a2816105fd565b9392505050565b6000602082840312156105ba578081fd5b81516105a2816105fd565b600080604083850312156105d7578081fd5b82356105e2816105fd565b915060208301356105f2816105fd565b809150509250929050565b6001600160a01b038116811461061257600080fd5b5056fea2646970667358221220b1862e5175b3b9a9fc5da21d120da98326517836ca159b01590210084513622d64736f6c63430008040033", + "devdoc": { + "kind": "dev", + "methods": { + "authorize(address,address)": { + "params": { + "_dappAddress": "address of the dapp that permission will be given to", + "_workerAddress": "address of the worker node to given permission" + } + }, + "isAuthorized(address,address)": { + "params": { + "_dappAddress": "address of the DApp", + "_workerAddress": "address of the worker" + } + } + }, + "stateVariables": { + "permissions": { + "details": "permissions keyed by hash(user, worker, dapp)" + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "Authorization(address,address,address)": { + "notice": "A DApp has been authorized by a user for a worker" + }, + "Deauthorization(address,address,address)": { + "notice": "A DApp has been deauthorized by a user for a worker" + } + }, + "kind": "user", + "methods": { + "authorize(address,address)": { + "notice": "Gives worker permission to act on a DApp" + }, + "isAuthorized(address,address)": { + "notice": "Returns is the dapp is authorized to be called by that worker" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 63, + "contract": "contracts/WorkerAuthManagerImpl.sol:WorkerAuthManagerImpl", + "label": "workerManager", + "offset": 0, + "slot": "0", + "type": "t_contract(WorkerManager)343" + }, + { + "astId": 68, + "contract": "contracts/WorkerAuthManagerImpl.sol:WorkerAuthManagerImpl", + "label": "permissions", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_bytes32,t_bool)" + } + ], + "types": { + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_contract(WorkerManager)343": { + "encoding": "inplace", + "label": "contract WorkerManager", + "numberOfBytes": "20" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/WorkerManagerAuthManagerImpl.json b/echo-js/deployments/localhost/WorkerManagerAuthManagerImpl.json new file mode 100644 index 00000000..f2fcde3b --- /dev/null +++ b/echo-js/deployments/localhost/WorkerManagerAuthManagerImpl.json @@ -0,0 +1,553 @@ +{ + "address": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dapp", + "type": "address" + } + ], + "name": "Authorization", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "dapp", + "type": "address" + } + ], + "name": "Deauthorization", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "JobAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "JobOffer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "JobRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "Retired", + "type": "event" + }, + { + "inputs": [], + "name": "acceptJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "authorize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "cancelHire", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "deauthorize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "getUser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "hire", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "hireAndAuthorize", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "_dappAddress", + "type": "address" + } + ], + "name": "isAuthorized", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "workerAddress", + "type": "address" + } + ], + "name": "isAvailable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "isOwned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "workerAddress", + "type": "address" + } + ], + "name": "isPending", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "isRetired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rejectJob", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "retire", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0xe98b661726674730ed6df15d10b58950dd05412308a6300f0d49a0ca9bdb0d5a", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0x0165878A594ca255338adfa4d48449f69242Eb8F", + "transactionIndex": 0, + "gasUsed": "773218", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x9376e753aefd6e06c9604b345db1e9c4ee7d3d020f0a863ed2d819767d7c8d5e", + "transactionHash": "0xe98b661726674730ed6df15d10b58950dd05412308a6300f0d49a0ca9bdb0d5a", + "logs": [], + "blockNumber": 7, + "cumulativeGasUsed": "773218", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dapp\",\"type\":\"address\"}],\"name\":\"Authorization\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"dapp\",\"type\":\"address\"}],\"name\":\"Deauthorization\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"JobAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"JobOffer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"JobRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"Retired\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptJob\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"authorize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"cancelHire\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"deauthorize\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"getUser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"hire\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"hireAndAuthorize\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_dappAddress\",\"type\":\"address\"}],\"name\":\"isAuthorized\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workerAddress\",\"type\":\"address\"}],\"name\":\"isAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"isOwned\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workerAddress\",\"type\":\"address\"}],\"name\":\"isPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"isRetired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rejectJob\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"retire\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"authorize(address,address)\":{\"params\":{\"_dappAddress\":\"address of the dapp that permission will be given to\",\"_workerAddress\":\"address of the worker node to given permission\"}},\"isAuthorized(address,address)\":{\"params\":{\"_dappAddress\":\"address of the DApp\",\"_workerAddress\":\"address of the worker\"}},\"isAvailable(address)\":{\"params\":{\"workerAddress\":\"address of the worker node\"}},\"isPending(address)\":{\"params\":{\"workerAddress\":\"address of the worker node\"}}},\"stateVariables\":{\"MAXIMUM_FUNDING\":{\"details\":\"transfers bigger than maximum value should be done directly\"},\"MINIMUM_FUNDING\":{\"details\":\"user can only hire a worker if he sends more than minimum value\"},\"permissions\":{\"details\":\"permissions keyed by hash(user, worker, dapp)\"},\"stateOf\":{\"details\":\"mapping from worker to its internal state\"},\"userOf\":{\"details\":\"mapping from worker to its user\"}},\"version\":1},\"userdoc\":{\"events\":{\"Authorization(address,address,address)\":{\"notice\":\"A DApp has been authorized by a user for a worker\"},\"Deauthorization(address,address,address)\":{\"notice\":\"A DApp has been deauthorized by a user for a worker\"},\"JobOffer(address,address)\":{\"notice\":\"Events signalling every state transition\"}},\"kind\":\"user\",\"methods\":{\"acceptJob()\":{\"notice\":\"Called by the worker to accept the job\"},\"authorize(address,address)\":{\"notice\":\"Gives worker permission to act on a DApp\"},\"isAuthorized(address,address)\":{\"notice\":\"Returns is the dapp is authorized to be called by that worker\"},\"isAvailable(address)\":{\"notice\":\"Returns true if worker node is available\"},\"isPending(address)\":{\"notice\":\"Returns true if worker node is pending\"},\"rejectJob()\":{\"notice\":\"Called by the worker to reject a job offer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/WorkerManagerAuthManagerImpl.sol\":\"WorkerManagerAuthManagerImpl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/WorkerAuthManager.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerAuthManager\\n/// @author Danilo Tuler\\npragma solidity >=0.7.0;\\n\\ninterface WorkerAuthManager {\\n /// @notice Gives worker permission to act on a DApp\\n /// @param _workerAddress address of the worker node to given permission\\n /// @param _dappAddress address of the dapp that permission will be given to\\n function authorize(address _workerAddress, address _dappAddress) external;\\n\\n /// @notice Removes worker's permission to act on a DApp\\n /// @param _workerAddress address of the proxy that will lose permission\\n /// @param _dappAddresses addresses of dapps that will lose permission\\n function deauthorize(address _workerAddress, address _dappAddresses)\\n external;\\n\\n /// @notice Returns is the dapp is authorized to be called by that worker\\n /// @param _workerAddress address of the worker\\n /// @param _dappAddress address of the DApp\\n function isAuthorized(address _workerAddress, address _dappAddress)\\n external\\n view\\n returns (bool);\\n\\n /// @notice Get the owner of the worker node\\n /// @param workerAddress address of the worker node\\n function getOwner(address workerAddress) external view returns (address);\\n\\n /// @notice A DApp has been authorized by a user for a worker\\n event Authorization(\\n address indexed user,\\n address indexed worker,\\n address indexed dapp\\n );\\n\\n /// @notice A DApp has been deauthorized by a user for a worker\\n event Deauthorization(\\n address indexed user,\\n address indexed worker,\\n address indexed dapp\\n );\\n}\\n\",\"keccak256\":\"0xb69b2fc75aae609d5a4098b77fb8f48dc87ff8073a8a3b70c0261af5f62f36db\",\"license\":\"Apache-2.0\"},\"contracts/WorkerManager.sol\":{\"content\":\"// Copyright 2010 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerManager\\n/// @author Danilo Tuler\\npragma solidity >=0.7.0;\\n\\ninterface WorkerManager {\\n /// @notice Returns true if worker node is available\\n /// @param workerAddress address of the worker node\\n function isAvailable(address workerAddress) external view returns (bool);\\n\\n /// @notice Returns true if worker node is pending\\n /// @param workerAddress address of the worker node\\n function isPending(address workerAddress) external view returns (bool);\\n\\n /// @notice Get the owner of the worker node\\n /// @param workerAddress address of the worker node\\n function getOwner(address workerAddress) external view returns (address);\\n\\n /// @notice Get the user of the worker node, which may not be the owner yet, or how was the previous owner of a retired node\\n function getUser(address workerAddress) external view returns (address);\\n\\n /// @notice Returns true if worker node is owned by some user\\n function isOwned(address workerAddress) external view returns (bool);\\n\\n /// @notice Asks the worker to work for the sender. Sender needs to pay something.\\n /// @param workerAddress address of the worker\\n function hire(address payable workerAddress) external payable;\\n\\n /// @notice Called by the worker to accept the job\\n function acceptJob() external;\\n\\n /// @notice Called by the worker to reject a job offer\\n function rejectJob() external payable;\\n\\n /// @notice Called by the user to cancel a job offer\\n /// @param workerAddress address of the worker node\\n function cancelHire(address workerAddress) external;\\n\\n /// @notice Called by the user to retire his worker.\\n /// @param workerAddress address of the worker to be retired\\n /// @dev this also removes all authorizations in place\\n function retire(address payable workerAddress) external;\\n\\n /// @notice Returns true if worker node was retired by its owner\\n function isRetired(address workerAddress) external view returns (bool);\\n\\n /// @notice Events signalling every state transition\\n event JobOffer(address indexed worker, address indexed user);\\n event JobAccepted(address indexed worker, address indexed user);\\n event JobRejected(address indexed worker, address indexed user);\\n event Retired(address indexed worker, address indexed user);\\n}\\n\",\"keccak256\":\"0xb93bac1de98b3fb44421c2498f11bcd246795c7cffeeebb535a046e88c303410\",\"license\":\"Apache-2.0\"},\"contracts/WorkerManagerAuthManagerImpl.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerManagerAuthManagerImpl\\n/// @author Danilo Tuler\\npragma solidity ^0.8.0;\\n\\nimport \\\"./WorkerManager.sol\\\";\\nimport \\\"./WorkerAuthManager.sol\\\";\\n\\ncontract WorkerManagerAuthManagerImpl is WorkerManager, WorkerAuthManager {\\n /// @dev user can only hire a worker if he sends more than minimum value\\n uint256 constant MINIMUM_FUNDING = 0.001 ether;\\n\\n /// @dev transfers bigger than maximum value should be done directly\\n uint256 constant MAXIMUM_FUNDING = 3 ether;\\n\\n /// @notice A worker can be in 4 different states, starting from Available\\n enum WorkerState {Available, Pending, Owned, Retired}\\n\\n /// @dev mapping from worker to its user\\n mapping(address => address payable) private userOf;\\n\\n /// @dev mapping from worker to its internal state\\n mapping(address => WorkerState) private stateOf;\\n\\n /// @dev permissions keyed by hash(user, worker, dapp)\\n mapping(bytes32 => bool) private permissions;\\n\\n function isAvailable(address workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[workerAddress] == WorkerState.Available;\\n }\\n\\n function isPending(address workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[workerAddress] == WorkerState.Pending;\\n }\\n\\n function getOwner(address _workerAddress)\\n public\\n override(WorkerManager, WorkerAuthManager)\\n view\\n returns (address)\\n {\\n return\\n stateOf[_workerAddress] == WorkerState.Owned\\n ? userOf[_workerAddress]\\n : address(0);\\n }\\n\\n function getUser(address _workerAddress)\\n public\\n override\\n view\\n returns (address)\\n {\\n return userOf[_workerAddress];\\n }\\n\\n function isOwned(address _workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[_workerAddress] == WorkerState.Owned;\\n }\\n\\n function hire(address payable _workerAddress) public override payable {\\n require(isAvailable(_workerAddress), \\\"worker is not available\\\");\\n require(_workerAddress != address(0), \\\"worker address can not be 0x0\\\");\\n require(msg.value >= MINIMUM_FUNDING, \\\"funding below minimum\\\");\\n require(msg.value <= MAXIMUM_FUNDING, \\\"funding above maximum\\\");\\n\\n // set owner\\n userOf[_workerAddress] = payable(msg.sender);\\n\\n // change state\\n stateOf[_workerAddress] = WorkerState.Pending;\\n\\n // transfer ether to worker\\n _workerAddress.transfer(msg.value);\\n\\n // emit event\\n emit JobOffer(_workerAddress, msg.sender);\\n }\\n\\n function acceptJob() public override {\\n require(\\n stateOf[msg.sender] == WorkerState.Pending,\\n \\\"worker not is not in pending state\\\"\\n );\\n\\n // change state\\n stateOf[msg.sender] = WorkerState.Owned;\\n // from now on getOwner will return the user\\n\\n // emit event\\n emit JobAccepted(msg.sender, userOf[msg.sender]);\\n }\\n\\n function rejectJob() public override payable {\\n require(\\n userOf[msg.sender] != address(0),\\n \\\"worker does not have a job offer\\\"\\n );\\n\\n address payable owner = userOf[msg.sender];\\n\\n // reset hirer back to null\\n userOf[msg.sender] = payable(address(0));\\n\\n // change state\\n stateOf[msg.sender] = WorkerState.Available;\\n\\n // return the money\\n owner.transfer(msg.value);\\n\\n // emit event\\n emit JobRejected(msg.sender, userOf[msg.sender]);\\n }\\n\\n function cancelHire(address _workerAddress) public override {\\n require(\\n userOf[_workerAddress] == msg.sender,\\n \\\"only hirer can cancel the offer\\\"\\n );\\n\\n // change state\\n stateOf[_workerAddress] = WorkerState.Retired;\\n\\n // emit event\\n emit Retired(_workerAddress, msg.sender);\\n }\\n\\n function retire(address payable _workerAddress) public override {\\n require(\\n stateOf[_workerAddress] == WorkerState.Owned,\\n \\\"worker not owned\\\"\\n );\\n require(\\n userOf[_workerAddress] == msg.sender,\\n \\\"only owner can retire worker\\\"\\n );\\n\\n // change state\\n stateOf[_workerAddress] = WorkerState.Retired;\\n\\n // emit event\\n emit Retired(_workerAddress, msg.sender);\\n }\\n\\n function isRetired(address _workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[_workerAddress] == WorkerState.Retired;\\n }\\n\\n modifier onlyByUser(address _workerAddress) {\\n require(\\n getUser(_workerAddress) == msg.sender,\\n \\\"worker not hired by sender\\\"\\n );\\n _;\\n }\\n\\n function getAuthorizationKey(\\n address _user,\\n address _worker,\\n address _dapp\\n ) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(_user, _worker, _dapp));\\n }\\n\\n function authorize(address _workerAddress, address _dappAddress)\\n public\\n override\\n onlyByUser(_workerAddress)\\n {\\n bytes32 key = getAuthorizationKey(\\n msg.sender,\\n _workerAddress,\\n _dappAddress\\n );\\n require(permissions[key] == false, \\\"dapp already authorized\\\");\\n\\n // record authorization from that user\\n permissions[key] = true;\\n\\n // emit event\\n emit Authorization(msg.sender, _workerAddress, _dappAddress);\\n }\\n\\n function deauthorize(address _workerAddress, address _dappAddress)\\n public\\n override\\n onlyByUser(_workerAddress)\\n {\\n bytes32 key = getAuthorizationKey(\\n msg.sender,\\n _workerAddress,\\n _dappAddress\\n );\\n require(permissions[key] == true, \\\"dapp not authorized\\\");\\n\\n // record deauthorization from that user\\n permissions[key] = false;\\n\\n // emit event\\n emit Deauthorization(msg.sender, _workerAddress, _dappAddress);\\n }\\n\\n function isAuthorized(address _workerAddress, address _dappAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return\\n permissions[getAuthorizationKey(\\n getOwner(_workerAddress),\\n _workerAddress,\\n _dappAddress\\n )];\\n }\\n\\n function hireAndAuthorize(\\n address payable _workerAddress,\\n address _dappAddress\\n ) public payable {\\n hire(_workerAddress);\\n authorize(_workerAddress, _dappAddress);\\n }\\n}\\n\",\"keccak256\":\"0x3bea45e35de87f18d8c79dffa4b9ccd6106590cace1a7868bf9fbf2a5112d3ff\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50610d08806100206000396000f3fe6080604052600436106100e85760003560e01c80639b789b7e1161008a578063d9d6bd8611610059578063d9d6bd8614610272578063dbd9655414610285578063f4dc754b14610298578063fa544161146102b857600080fd5b80639b789b7e146101fd5780639e6371ba14610212578063a00745b614610232578063b64b3bed1461025257600080fd5b806365e4ad9e116100c657806365e4ad9e1461014c5780636d3c62751461016c5780636d892f7e1461018c5780636f77926b146101ac57600080fd5b806303d6e81e146100ed5780632896f60b146100f75780632bef45951461012c575b600080fd5b6100f56102d8565b005b34801561010357600080fd5b50610117610112366004610c4d565b6103f0565b60405190151581526020015b60405180910390f35b34801561013857600080fd5b506100f5610147366004610ca8565b610436565b34801561015857600080fd5b50610117610167366004610ca8565b610575565b34801561017857600080fd5b50610117610187366004610c4d565b6105a9565b34801561019857600080fd5b506100f56101a7366004610ca8565b6105b2565b3480156101b857600080fd5b506101e56101c7366004610c4d565b6001600160a01b039081166000908152602081905260409020541690565b6040516001600160a01b039091168152602001610123565b34801561020957600080fd5b506100f56106e8565b34801561021e57600080fd5b506100f561022d366004610c4d565b6107cd565b34801561023e57600080fd5b5061011761024d366004610c4d565b610901565b34801561025e57600080fd5b506100f561026d366004610c4d565b61090a565b6100f5610280366004610c4d565b610973565b6100f5610293366004610c70565b610b6b565b3480156102a457600080fd5b506101176102b3366004610c4d565b610b82565b3480156102c457600080fd5b506101e56102d3366004610c4d565b610b8b565b336000908152602081905260409020546001600160a01b03166103425760405162461bcd60e51b815260206004820181905260248201527f776f726b657220646f6573206e6f7420686176652061206a6f62206f6666657260448201526064015b60405180910390fd5b3360009081526020818152604080832080546001600160a01b031981169091556001909252808320805460ff19169055516001600160a01b039091169182913480156108fc0292909190818181858888f193505050501580156103a9573d6000803e3d6000fd5b50336000818152602081905260408082205490516001600160a01b0390911692917fac8bfc64efe7b663f325ca81c7468a291a868aacc74c8f91cdc5c8141c15e38a91a350565b6000805b6001600160a01b03831660009081526001602052604090205460ff16600381111561042f57634e487b7160e01b600052602160045260246000fd5b1492915050565b813361045a826001600160a01b039081166000908152602081905260409020541690565b6001600160a01b0316146104b05760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e6465720000000000006044820152606401610339565b60006104bd338585610bf8565b60008181526002602052604090205490915060ff161561051f5760405162461bcd60e51b815260206004820152601760248201527f6461707020616c726561647920617574686f72697a65640000000000000000006044820152606401610339565b600081815260026020526040808220805460ff19166001179055516001600160a01b03808616929087169133917fde756a416a233cdb16c23a1fa5dcb3113164968df8607e0a4eeca25974b96e0391a450505050565b60006002600061058e61058786610b8b565b8686610bf8565b815260208101919091526040016000205460ff169392505050565b600060036103f4565b81336105d6826001600160a01b039081166000908152602081905260409020541690565b6001600160a01b03161461062c5760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e6465720000000000006044820152606401610339565b6000610639338585610bf8565b60008181526002602052604090205490915060ff1615156001146106955760405162461bcd60e51b815260206004820152601360248201527219185c1c081b9bdd08185d5d1a1bdc9a5e9959606a1b6044820152606401610339565b600081815260026020526040808220805460ff19169055516001600160a01b03808616929087169133917f4d2275ddb8a6d9c36c95476c2eaf9746c1785b4ab76a99719fd647b36da46cee91a450505050565b60013360009081526001602052604090205460ff16600381111561071c57634e487b7160e01b600052602160045260246000fd5b146107745760405162461bcd60e51b815260206004820152602260248201527f776f726b6572206e6f74206973206e6f7420696e2070656e64696e6720737461604482015261746560f01b6064820152608401610339565b336000818152600160209081526040808320805460ff19166002179055908290528082205490516001600160a01b0390911692917f0cfa12ab8ee8dc6f9b68938d5e764dafed737d43dc5ec8443abf81e645276eb691a3565b60026001600160a01b03821660009081526001602052604090205460ff16600381111561080a57634e487b7160e01b600052602160045260246000fd5b1461084a5760405162461bcd60e51b815260206004820152601060248201526f1ddbdc9ad95c881b9bdd081bdddb995960821b6044820152606401610339565b6001600160a01b038181166000908152602081905260409020541633146108b35760405162461bcd60e51b815260206004820152601c60248201527f6f6e6c79206f776e65722063616e2072657469726520776f726b6572000000006044820152606401610339565b6001600160a01b038116600081815260016020526040808220805460ff19166003179055513392917f657b373e1262c26d1f1a83e8949f0af9067fe48026b308e47eec5ef6b40ff25d91a350565b600060016103f4565b6001600160a01b038181166000908152602081905260409020541633146108b35760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792068697265722063616e2063616e63656c20746865206f66666572006044820152606401610339565b61097c816103f0565b6109c85760405162461bcd60e51b815260206004820152601760248201527f776f726b6572206973206e6f7420617661696c61626c650000000000000000006044820152606401610339565b6001600160a01b038116610a1e5760405162461bcd60e51b815260206004820152601d60248201527f776f726b657220616464726573732063616e206e6f74206265203078300000006044820152606401610339565b66038d7ea4c68000341015610a6d5760405162461bcd60e51b815260206004820152601560248201527466756e64696e672062656c6f77206d696e696d756d60581b6044820152606401610339565b6729a2241af62c0000341115610abd5760405162461bcd60e51b815260206004820152601560248201527466756e64696e672061626f7665206d6178696d756d60581b6044820152606401610339565b6001600160a01b03811660009081526020818152604080832080546001600160a01b03191633179055600191829052909120805460ff1916828002179055506040516001600160a01b038216903480156108fc02916000818181858888f19350505050158015610b31573d6000803e3d6000fd5b5060405133906001600160a01b038316907f2e0aa97ef0e6f4f76319861c90e91beec7a7a44a698cab856dfc1985a0c588f090600090a350565b610b7482610973565b610b7e8282610436565b5050565b600060026103f4565b600060026001600160a01b03831660009081526001602052604090205460ff166003811115610bca57634e487b7160e01b600052602160045260246000fd5b14610bd6576000610bf2565b6001600160a01b03808316600090815260208190526040902054165b92915050565b6040516bffffffffffffffffffffffff19606085811b8216602084015284811b8216603484015283901b166048820152600090605c016040516020818303038152906040528051906020012090509392505050565b600060208284031215610c5e578081fd5b8135610c6981610cba565b9392505050565b60008060408385031215610c82578081fd5b8235610c8d81610cba565b91506020830135610c9d81610cba565b809150509250929050565b60008060408385031215610c82578182fd5b6001600160a01b0381168114610ccf57600080fd5b5056fea26469706673582212202700c4e4bbaeb90fae58ff3eb584ca659cec3993a24873987c6c38e6b553627464736f6c63430008040033", + "deployedBytecode": "0x6080604052600436106100e85760003560e01c80639b789b7e1161008a578063d9d6bd8611610059578063d9d6bd8614610272578063dbd9655414610285578063f4dc754b14610298578063fa544161146102b857600080fd5b80639b789b7e146101fd5780639e6371ba14610212578063a00745b614610232578063b64b3bed1461025257600080fd5b806365e4ad9e116100c657806365e4ad9e1461014c5780636d3c62751461016c5780636d892f7e1461018c5780636f77926b146101ac57600080fd5b806303d6e81e146100ed5780632896f60b146100f75780632bef45951461012c575b600080fd5b6100f56102d8565b005b34801561010357600080fd5b50610117610112366004610c4d565b6103f0565b60405190151581526020015b60405180910390f35b34801561013857600080fd5b506100f5610147366004610ca8565b610436565b34801561015857600080fd5b50610117610167366004610ca8565b610575565b34801561017857600080fd5b50610117610187366004610c4d565b6105a9565b34801561019857600080fd5b506100f56101a7366004610ca8565b6105b2565b3480156101b857600080fd5b506101e56101c7366004610c4d565b6001600160a01b039081166000908152602081905260409020541690565b6040516001600160a01b039091168152602001610123565b34801561020957600080fd5b506100f56106e8565b34801561021e57600080fd5b506100f561022d366004610c4d565b6107cd565b34801561023e57600080fd5b5061011761024d366004610c4d565b610901565b34801561025e57600080fd5b506100f561026d366004610c4d565b61090a565b6100f5610280366004610c4d565b610973565b6100f5610293366004610c70565b610b6b565b3480156102a457600080fd5b506101176102b3366004610c4d565b610b82565b3480156102c457600080fd5b506101e56102d3366004610c4d565b610b8b565b336000908152602081905260409020546001600160a01b03166103425760405162461bcd60e51b815260206004820181905260248201527f776f726b657220646f6573206e6f7420686176652061206a6f62206f6666657260448201526064015b60405180910390fd5b3360009081526020818152604080832080546001600160a01b031981169091556001909252808320805460ff19169055516001600160a01b039091169182913480156108fc0292909190818181858888f193505050501580156103a9573d6000803e3d6000fd5b50336000818152602081905260408082205490516001600160a01b0390911692917fac8bfc64efe7b663f325ca81c7468a291a868aacc74c8f91cdc5c8141c15e38a91a350565b6000805b6001600160a01b03831660009081526001602052604090205460ff16600381111561042f57634e487b7160e01b600052602160045260246000fd5b1492915050565b813361045a826001600160a01b039081166000908152602081905260409020541690565b6001600160a01b0316146104b05760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e6465720000000000006044820152606401610339565b60006104bd338585610bf8565b60008181526002602052604090205490915060ff161561051f5760405162461bcd60e51b815260206004820152601760248201527f6461707020616c726561647920617574686f72697a65640000000000000000006044820152606401610339565b600081815260026020526040808220805460ff19166001179055516001600160a01b03808616929087169133917fde756a416a233cdb16c23a1fa5dcb3113164968df8607e0a4eeca25974b96e0391a450505050565b60006002600061058e61058786610b8b565b8686610bf8565b815260208101919091526040016000205460ff169392505050565b600060036103f4565b81336105d6826001600160a01b039081166000908152602081905260409020541690565b6001600160a01b03161461062c5760405162461bcd60e51b815260206004820152601a60248201527f776f726b6572206e6f742068697265642062792073656e6465720000000000006044820152606401610339565b6000610639338585610bf8565b60008181526002602052604090205490915060ff1615156001146106955760405162461bcd60e51b815260206004820152601360248201527219185c1c081b9bdd08185d5d1a1bdc9a5e9959606a1b6044820152606401610339565b600081815260026020526040808220805460ff19169055516001600160a01b03808616929087169133917f4d2275ddb8a6d9c36c95476c2eaf9746c1785b4ab76a99719fd647b36da46cee91a450505050565b60013360009081526001602052604090205460ff16600381111561071c57634e487b7160e01b600052602160045260246000fd5b146107745760405162461bcd60e51b815260206004820152602260248201527f776f726b6572206e6f74206973206e6f7420696e2070656e64696e6720737461604482015261746560f01b6064820152608401610339565b336000818152600160209081526040808320805460ff19166002179055908290528082205490516001600160a01b0390911692917f0cfa12ab8ee8dc6f9b68938d5e764dafed737d43dc5ec8443abf81e645276eb691a3565b60026001600160a01b03821660009081526001602052604090205460ff16600381111561080a57634e487b7160e01b600052602160045260246000fd5b1461084a5760405162461bcd60e51b815260206004820152601060248201526f1ddbdc9ad95c881b9bdd081bdddb995960821b6044820152606401610339565b6001600160a01b038181166000908152602081905260409020541633146108b35760405162461bcd60e51b815260206004820152601c60248201527f6f6e6c79206f776e65722063616e2072657469726520776f726b6572000000006044820152606401610339565b6001600160a01b038116600081815260016020526040808220805460ff19166003179055513392917f657b373e1262c26d1f1a83e8949f0af9067fe48026b308e47eec5ef6b40ff25d91a350565b600060016103f4565b6001600160a01b038181166000908152602081905260409020541633146108b35760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792068697265722063616e2063616e63656c20746865206f66666572006044820152606401610339565b61097c816103f0565b6109c85760405162461bcd60e51b815260206004820152601760248201527f776f726b6572206973206e6f7420617661696c61626c650000000000000000006044820152606401610339565b6001600160a01b038116610a1e5760405162461bcd60e51b815260206004820152601d60248201527f776f726b657220616464726573732063616e206e6f74206265203078300000006044820152606401610339565b66038d7ea4c68000341015610a6d5760405162461bcd60e51b815260206004820152601560248201527466756e64696e672062656c6f77206d696e696d756d60581b6044820152606401610339565b6729a2241af62c0000341115610abd5760405162461bcd60e51b815260206004820152601560248201527466756e64696e672061626f7665206d6178696d756d60581b6044820152606401610339565b6001600160a01b03811660009081526020818152604080832080546001600160a01b03191633179055600191829052909120805460ff1916828002179055506040516001600160a01b038216903480156108fc02916000818181858888f19350505050158015610b31573d6000803e3d6000fd5b5060405133906001600160a01b038316907f2e0aa97ef0e6f4f76319861c90e91beec7a7a44a698cab856dfc1985a0c588f090600090a350565b610b7482610973565b610b7e8282610436565b5050565b600060026103f4565b600060026001600160a01b03831660009081526001602052604090205460ff166003811115610bca57634e487b7160e01b600052602160045260246000fd5b14610bd6576000610bf2565b6001600160a01b03808316600090815260208190526040902054165b92915050565b6040516bffffffffffffffffffffffff19606085811b8216602084015284811b8216603484015283901b166048820152600090605c016040516020818303038152906040528051906020012090509392505050565b600060208284031215610c5e578081fd5b8135610c6981610cba565b9392505050565b60008060408385031215610c82578081fd5b8235610c8d81610cba565b91506020830135610c9d81610cba565b809150509250929050565b60008060408385031215610c82578182fd5b6001600160a01b0381168114610ccf57600080fd5b5056fea26469706673582212202700c4e4bbaeb90fae58ff3eb584ca659cec3993a24873987c6c38e6b553627464736f6c63430008040033", + "devdoc": { + "kind": "dev", + "methods": { + "authorize(address,address)": { + "params": { + "_dappAddress": "address of the dapp that permission will be given to", + "_workerAddress": "address of the worker node to given permission" + } + }, + "isAuthorized(address,address)": { + "params": { + "_dappAddress": "address of the DApp", + "_workerAddress": "address of the worker" + } + }, + "isAvailable(address)": { + "params": { + "workerAddress": "address of the worker node" + } + }, + "isPending(address)": { + "params": { + "workerAddress": "address of the worker node" + } + } + }, + "stateVariables": { + "MAXIMUM_FUNDING": { + "details": "transfers bigger than maximum value should be done directly" + }, + "MINIMUM_FUNDING": { + "details": "user can only hire a worker if he sends more than minimum value" + }, + "permissions": { + "details": "permissions keyed by hash(user, worker, dapp)" + }, + "stateOf": { + "details": "mapping from worker to its internal state" + }, + "userOf": { + "details": "mapping from worker to its user" + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "Authorization(address,address,address)": { + "notice": "A DApp has been authorized by a user for a worker" + }, + "Deauthorization(address,address,address)": { + "notice": "A DApp has been deauthorized by a user for a worker" + }, + "JobOffer(address,address)": { + "notice": "Events signalling every state transition" + } + }, + "kind": "user", + "methods": { + "acceptJob()": { + "notice": "Called by the worker to accept the job" + }, + "authorize(address,address)": { + "notice": "Gives worker permission to act on a DApp" + }, + "isAuthorized(address,address)": { + "notice": "Returns is the dapp is authorized to be called by that worker" + }, + "isAvailable(address)": { + "notice": "Returns true if worker node is available" + }, + "isPending(address)": { + "notice": "Returns true if worker node is pending" + }, + "rejectJob()": { + "notice": "Called by the worker to reject a job offer" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 369, + "contract": "contracts/WorkerManagerAuthManagerImpl.sol:WorkerManagerAuthManagerImpl", + "label": "userOf", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_address_payable)" + }, + { + "astId": 375, + "contract": "contracts/WorkerManagerAuthManagerImpl.sol:WorkerManagerAuthManagerImpl", + "label": "stateOf", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_enum(WorkerState)364)" + }, + { + "astId": 380, + "contract": "contracts/WorkerManagerAuthManagerImpl.sol:WorkerManagerAuthManagerImpl", + "label": "permissions", + "offset": 0, + "slot": "2", + "type": "t_mapping(t_bytes32,t_bool)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "encoding": "inplace", + "label": "address payable", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_bytes32": { + "encoding": "inplace", + "label": "bytes32", + "numberOfBytes": "32" + }, + "t_enum(WorkerState)364": { + "encoding": "inplace", + "label": "enum WorkerManagerAuthManagerImpl.WorkerState", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address_payable)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address payable)", + "numberOfBytes": "32", + "value": "t_address_payable" + }, + "t_mapping(t_address,t_enum(WorkerState)364)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => enum WorkerManagerAuthManagerImpl.WorkerState)", + "numberOfBytes": "32", + "value": "t_enum(WorkerState)364" + }, + "t_mapping(t_bytes32,t_bool)": { + "encoding": "mapping", + "key": "t_bytes32", + "label": "mapping(bytes32 => bool)", + "numberOfBytes": "32", + "value": "t_bool" + } + } + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/WorkerManagerImpl.json b/echo-js/deployments/localhost/WorkerManagerImpl.json new file mode 100644 index 00000000..96d277cc --- /dev/null +++ b/echo-js/deployments/localhost/WorkerManagerImpl.json @@ -0,0 +1,373 @@ +{ + "address": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "abi": [ + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "JobAccepted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "JobOffer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "JobRejected", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "worker", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "user", + "type": "address" + } + ], + "name": "Retired", + "type": "event" + }, + { + "inputs": [], + "name": "acceptJob", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "cancelHire", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "getOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "getUser", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "hire", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "workerAddress", + "type": "address" + } + ], + "name": "isAvailable", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "isOwned", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "workerAddress", + "type": "address" + } + ], + "name": "isPending", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "isRetired", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rejectJob", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address payable", + "name": "_workerAddress", + "type": "address" + } + ], + "name": "retire", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x7a5cf95d0aed9f45b4067319e731a5e7ae16220b11daa8f326b48f6293c857bc", + "receipt": { + "to": null, + "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266", + "contractAddress": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9", + "transactionIndex": 0, + "gasUsed": "571031", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xb7471845e401a6e68f62d39f642232c965e711f49ae001787ac622b66a1b9018", + "transactionHash": "0x7a5cf95d0aed9f45b4067319e731a5e7ae16220b11daa8f326b48f6293c857bc", + "logs": [], + "blockNumber": 5, + "cumulativeGasUsed": "571031", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "metadata": "{\"compiler\":{\"version\":\"0.8.4+commit.c7e474f2\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"JobAccepted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"JobOffer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"JobRejected\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"worker\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"user\",\"type\":\"address\"}],\"name\":\"Retired\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"acceptJob\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"cancelHire\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"getOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"getUser\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"hire\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workerAddress\",\"type\":\"address\"}],\"name\":\"isAvailable\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"isOwned\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"workerAddress\",\"type\":\"address\"}],\"name\":\"isPending\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"isRetired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rejectJob\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address payable\",\"name\":\"_workerAddress\",\"type\":\"address\"}],\"name\":\"retire\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"isAvailable(address)\":{\"params\":{\"workerAddress\":\"address of the worker node\"}},\"isPending(address)\":{\"params\":{\"workerAddress\":\"address of the worker node\"}}},\"stateVariables\":{\"MAXIMUM_FUNDING\":{\"details\":\"transfers bigger than maximum value should be done directly\"},\"MINIMUM_FUNDING\":{\"details\":\"user can only hire a worker if he sends more than minimum value\"},\"stateOf\":{\"details\":\"mapping from worker to its internal state\"},\"userOf\":{\"details\":\"mapping from worker to its user\"}},\"version\":1},\"userdoc\":{\"events\":{\"JobOffer(address,address)\":{\"notice\":\"Events signalling every state transition\"}},\"kind\":\"user\",\"methods\":{\"acceptJob()\":{\"notice\":\"Called by the worker to accept the job\"},\"isAvailable(address)\":{\"notice\":\"Returns true if worker node is available\"},\"isPending(address)\":{\"notice\":\"Returns true if worker node is pending\"},\"rejectJob()\":{\"notice\":\"Called by the worker to reject a job offer\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/WorkerManagerImpl.sol\":\"WorkerManagerImpl\"},\"evmVersion\":\"istanbul\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"contracts/WorkerManager.sol\":{\"content\":\"// Copyright 2010 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerManager\\n/// @author Danilo Tuler\\npragma solidity >=0.7.0;\\n\\ninterface WorkerManager {\\n /// @notice Returns true if worker node is available\\n /// @param workerAddress address of the worker node\\n function isAvailable(address workerAddress) external view returns (bool);\\n\\n /// @notice Returns true if worker node is pending\\n /// @param workerAddress address of the worker node\\n function isPending(address workerAddress) external view returns (bool);\\n\\n /// @notice Get the owner of the worker node\\n /// @param workerAddress address of the worker node\\n function getOwner(address workerAddress) external view returns (address);\\n\\n /// @notice Get the user of the worker node, which may not be the owner yet, or how was the previous owner of a retired node\\n function getUser(address workerAddress) external view returns (address);\\n\\n /// @notice Returns true if worker node is owned by some user\\n function isOwned(address workerAddress) external view returns (bool);\\n\\n /// @notice Asks the worker to work for the sender. Sender needs to pay something.\\n /// @param workerAddress address of the worker\\n function hire(address payable workerAddress) external payable;\\n\\n /// @notice Called by the worker to accept the job\\n function acceptJob() external;\\n\\n /// @notice Called by the worker to reject a job offer\\n function rejectJob() external payable;\\n\\n /// @notice Called by the user to cancel a job offer\\n /// @param workerAddress address of the worker node\\n function cancelHire(address workerAddress) external;\\n\\n /// @notice Called by the user to retire his worker.\\n /// @param workerAddress address of the worker to be retired\\n /// @dev this also removes all authorizations in place\\n function retire(address payable workerAddress) external;\\n\\n /// @notice Returns true if worker node was retired by its owner\\n function isRetired(address workerAddress) external view returns (bool);\\n\\n /// @notice Events signalling every state transition\\n event JobOffer(address indexed worker, address indexed user);\\n event JobAccepted(address indexed worker, address indexed user);\\n event JobRejected(address indexed worker, address indexed user);\\n event Retired(address indexed worker, address indexed user);\\n}\\n\",\"keccak256\":\"0xb93bac1de98b3fb44421c2498f11bcd246795c7cffeeebb535a046e88c303410\",\"license\":\"Apache-2.0\"},\"contracts/WorkerManagerImpl.sol\":{\"content\":\"// Copyright 2020 Cartesi Pte. Ltd.\\n\\n// SPDX-License-Identifier: Apache-2.0\\n// Licensed under the Apache License, Version 2.0 (the \\\"License\\\"); you may not use\\n// this file except in compliance with the License. You may obtain a copy of the\\n// License at http://www.apache.org/licenses/LICENSE-2.0\\n\\n// Unless required by applicable law or agreed to in writing, software distributed\\n// under the License is distributed on an \\\"AS IS\\\" BASIS, WITHOUT WARRANTIES OR\\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\\n// specific language governing permissions and limitations under the License.\\n\\n/// @title WorkerManagerImpl\\n/// @author Danilo Tuler\\npragma solidity ^0.8.0;\\n\\nimport \\\"./WorkerManager.sol\\\";\\n\\ncontract WorkerManagerImpl is WorkerManager {\\n /// @dev user can only hire a worker if he sends more than minimum value\\n uint256 constant MINIMUM_FUNDING = 0.001 ether;\\n\\n /// @dev transfers bigger than maximum value should be done directly\\n uint256 constant MAXIMUM_FUNDING = 3 ether;\\n\\n /// @notice A worker can be in 4 different states, starting from Available\\n enum WorkerState {Available, Pending, Owned, Retired}\\n\\n /// @dev mapping from worker to its user\\n mapping(address => address payable) private userOf;\\n\\n /// @dev mapping from worker to its internal state\\n mapping(address => WorkerState) private stateOf;\\n\\n function isAvailable(address workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[workerAddress] == WorkerState.Available;\\n }\\n\\n function isPending(address workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[workerAddress] == WorkerState.Pending;\\n }\\n\\n function getOwner(address _workerAddress)\\n public\\n override\\n view\\n returns (address)\\n {\\n return\\n stateOf[_workerAddress] == WorkerState.Owned\\n ? userOf[_workerAddress]\\n : address(0);\\n }\\n\\n function getUser(address _workerAddress)\\n public\\n override\\n view\\n returns (address)\\n {\\n return userOf[_workerAddress];\\n }\\n\\n function isOwned(address _workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[_workerAddress] == WorkerState.Owned;\\n }\\n\\n function hire(address payable _workerAddress) public override payable {\\n require(isAvailable(_workerAddress), \\\"worker is not available\\\");\\n require(_workerAddress != address(0), \\\"worker address can not be 0x0\\\");\\n require(msg.value >= MINIMUM_FUNDING, \\\"funding below minimum\\\");\\n require(msg.value <= MAXIMUM_FUNDING, \\\"funding above maximum\\\");\\n\\n // set owner\\n userOf[_workerAddress] = payable(msg.sender);\\n\\n // change state\\n stateOf[_workerAddress] = WorkerState.Pending;\\n\\n // transfer ether to worker\\n _workerAddress.transfer(msg.value);\\n\\n // emit event\\n emit JobOffer(_workerAddress, msg.sender);\\n }\\n\\n function acceptJob() public override {\\n require(\\n userOf[msg.sender] != address(0),\\n \\\"worker does not have a job offer\\\"\\n );\\n require(\\n stateOf[msg.sender] == WorkerState.Pending,\\n \\\"worker not is not in pending state\\\"\\n );\\n\\n // change state\\n stateOf[msg.sender] = WorkerState.Owned;\\n // from now on getOwner will return the user\\n\\n // emit event\\n emit JobAccepted(msg.sender, userOf[msg.sender]);\\n }\\n\\n function rejectJob() public override payable {\\n require(\\n userOf[msg.sender] != address(0),\\n \\\"worker does not have a job offer\\\"\\n );\\n\\n address payable owner = userOf[msg.sender];\\n\\n // reset hirer back to null\\n userOf[msg.sender] = payable(address(0));\\n\\n // change state\\n stateOf[msg.sender] = WorkerState.Available;\\n\\n // return the money\\n owner.transfer(msg.value);\\n\\n // emit event\\n emit JobRejected(msg.sender, userOf[msg.sender]);\\n }\\n\\n function cancelHire(address _workerAddress) public override {\\n require(\\n userOf[_workerAddress] != address(0),\\n \\\"worker does not have a job offer\\\"\\n );\\n\\n require(\\n userOf[_workerAddress] == msg.sender,\\n \\\"only hirer can cancel the offer\\\"\\n );\\n\\n // change state\\n stateOf[_workerAddress] = WorkerState.Retired;\\n\\n // emit event\\n emit Retired(_workerAddress, msg.sender);\\n }\\n\\n function retire(address payable _workerAddress) public override {\\n require(\\n stateOf[_workerAddress] == WorkerState.Owned,\\n \\\"worker not owned\\\"\\n );\\n require(\\n userOf[_workerAddress] == msg.sender,\\n \\\"only owner can retire worker\\\"\\n );\\n\\n // change state\\n stateOf[_workerAddress] = WorkerState.Retired;\\n\\n // emit event\\n emit Retired(_workerAddress, msg.sender);\\n }\\n\\n function isRetired(address _workerAddress)\\n public\\n override\\n view\\n returns (bool)\\n {\\n return stateOf[_workerAddress] == WorkerState.Retired;\\n }\\n}\\n\",\"keccak256\":\"0x71a604e959e92f3b30008ac43d25bfc9e73040e2b384e73d1daa607d85bdbd1e\",\"license\":\"Apache-2.0\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061095f806100206000396000f3fe60806040526004361061009c5760003560e01c80639e6371ba116100645780639e6371ba14610166578063a00745b614610186578063b64b3bed146101a6578063d9d6bd86146101c6578063f4dc754b146101d9578063fa544161146101f957600080fd5b806303d6e81e146100a15780632896f60b146100ab5780636d3c6275146100e05780636f77926b146101005780639b789b7e14610151575b600080fd5b6100a9610219565b005b3480156100b757600080fd5b506100cb6100c63660046108b9565b610305565b60405190151581526020015b60405180910390f35b3480156100ec57600080fd5b506100cb6100fb3660046108b9565b61034b565b34801561010c57600080fd5b5061013961011b3660046108b9565b6001600160a01b039081166000908152602081905260409020541690565b6040516001600160a01b0390911681526020016100d7565b34801561015d57600080fd5b506100a9610354565b34801561017257600080fd5b506100a96101813660046108b9565b61046e565b34801561019257600080fd5b506100cb6101a13660046108b9565b6105a2565b3480156101b257600080fd5b506100a96101c13660046108b9565b6105ab565b6100a96101d43660046108b9565b61064b565b3480156101e557600080fd5b506100cb6101f43660046108b9565b610843565b34801561020557600080fd5b506101396102143660046108b9565b61084c565b336000908152602081905260409020546001600160a01b03166102575760405162461bcd60e51b815260040161024e906108dc565b60405180910390fd5b3360009081526020818152604080832080546001600160a01b031981169091556001909252808320805460ff19169055516001600160a01b039091169182913480156108fc0292909190818181858888f193505050501580156102be573d6000803e3d6000fd5b50336000818152602081905260408082205490516001600160a01b0390911692917fac8bfc64efe7b663f325ca81c7468a291a868aacc74c8f91cdc5c8141c15e38a91a350565b6000805b6001600160a01b03831660009081526001602052604090205460ff16600381111561034457634e487b7160e01b600052602160045260246000fd5b1492915050565b60006003610309565b336000908152602081905260409020546001600160a01b03166103895760405162461bcd60e51b815260040161024e906108dc565b60013360009081526001602052604090205460ff1660038111156103bd57634e487b7160e01b600052602160045260246000fd5b146104155760405162461bcd60e51b815260206004820152602260248201527f776f726b6572206e6f74206973206e6f7420696e2070656e64696e6720737461604482015261746560f01b606482015260840161024e565b336000818152600160209081526040808320805460ff19166002179055908290528082205490516001600160a01b0390911692917f0cfa12ab8ee8dc6f9b68938d5e764dafed737d43dc5ec8443abf81e645276eb691a3565b60026001600160a01b03821660009081526001602052604090205460ff1660038111156104ab57634e487b7160e01b600052602160045260246000fd5b146104eb5760405162461bcd60e51b815260206004820152601060248201526f1ddbdc9ad95c881b9bdd081bdddb995960821b604482015260640161024e565b6001600160a01b038181166000908152602081905260409020541633146105545760405162461bcd60e51b815260206004820152601c60248201527f6f6e6c79206f776e65722063616e2072657469726520776f726b657200000000604482015260640161024e565b6001600160a01b038116600081815260016020526040808220805460ff19166003179055513392917f657b373e1262c26d1f1a83e8949f0af9067fe48026b308e47eec5ef6b40ff25d91a350565b60006001610309565b6001600160a01b03818116600090815260208190526040902054166105e25760405162461bcd60e51b815260040161024e906108dc565b6001600160a01b038181166000908152602081905260409020541633146105545760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792068697265722063616e2063616e63656c20746865206f6666657200604482015260640161024e565b61065481610305565b6106a05760405162461bcd60e51b815260206004820152601760248201527f776f726b6572206973206e6f7420617661696c61626c65000000000000000000604482015260640161024e565b6001600160a01b0381166106f65760405162461bcd60e51b815260206004820152601d60248201527f776f726b657220616464726573732063616e206e6f7420626520307830000000604482015260640161024e565b66038d7ea4c680003410156107455760405162461bcd60e51b815260206004820152601560248201527466756e64696e672062656c6f77206d696e696d756d60581b604482015260640161024e565b6729a2241af62c00003411156107955760405162461bcd60e51b815260206004820152601560248201527466756e64696e672061626f7665206d6178696d756d60581b604482015260640161024e565b6001600160a01b03811660009081526020818152604080832080546001600160a01b03191633179055600191829052909120805460ff1916828002179055506040516001600160a01b038216903480156108fc02916000818181858888f19350505050158015610809573d6000803e3d6000fd5b5060405133906001600160a01b038316907f2e0aa97ef0e6f4f76319861c90e91beec7a7a44a698cab856dfc1985a0c588f090600090a350565b60006002610309565b600060026001600160a01b03831660009081526001602052604090205460ff16600381111561088b57634e487b7160e01b600052602160045260246000fd5b146108975760006108b3565b6001600160a01b03808316600090815260208190526040902054165b92915050565b6000602082840312156108ca578081fd5b81356108d581610911565b9392505050565b6020808252818101527f776f726b657220646f6573206e6f7420686176652061206a6f62206f66666572604082015260600190565b6001600160a01b038116811461092657600080fd5b5056fea26469706673582212204f10e5c420944ca621a08a09fa16ebe0123c0a671181c14a268338dad73fcebc64736f6c63430008040033", + "deployedBytecode": "0x60806040526004361061009c5760003560e01c80639e6371ba116100645780639e6371ba14610166578063a00745b614610186578063b64b3bed146101a6578063d9d6bd86146101c6578063f4dc754b146101d9578063fa544161146101f957600080fd5b806303d6e81e146100a15780632896f60b146100ab5780636d3c6275146100e05780636f77926b146101005780639b789b7e14610151575b600080fd5b6100a9610219565b005b3480156100b757600080fd5b506100cb6100c63660046108b9565b610305565b60405190151581526020015b60405180910390f35b3480156100ec57600080fd5b506100cb6100fb3660046108b9565b61034b565b34801561010c57600080fd5b5061013961011b3660046108b9565b6001600160a01b039081166000908152602081905260409020541690565b6040516001600160a01b0390911681526020016100d7565b34801561015d57600080fd5b506100a9610354565b34801561017257600080fd5b506100a96101813660046108b9565b61046e565b34801561019257600080fd5b506100cb6101a13660046108b9565b6105a2565b3480156101b257600080fd5b506100a96101c13660046108b9565b6105ab565b6100a96101d43660046108b9565b61064b565b3480156101e557600080fd5b506100cb6101f43660046108b9565b610843565b34801561020557600080fd5b506101396102143660046108b9565b61084c565b336000908152602081905260409020546001600160a01b03166102575760405162461bcd60e51b815260040161024e906108dc565b60405180910390fd5b3360009081526020818152604080832080546001600160a01b031981169091556001909252808320805460ff19169055516001600160a01b039091169182913480156108fc0292909190818181858888f193505050501580156102be573d6000803e3d6000fd5b50336000818152602081905260408082205490516001600160a01b0390911692917fac8bfc64efe7b663f325ca81c7468a291a868aacc74c8f91cdc5c8141c15e38a91a350565b6000805b6001600160a01b03831660009081526001602052604090205460ff16600381111561034457634e487b7160e01b600052602160045260246000fd5b1492915050565b60006003610309565b336000908152602081905260409020546001600160a01b03166103895760405162461bcd60e51b815260040161024e906108dc565b60013360009081526001602052604090205460ff1660038111156103bd57634e487b7160e01b600052602160045260246000fd5b146104155760405162461bcd60e51b815260206004820152602260248201527f776f726b6572206e6f74206973206e6f7420696e2070656e64696e6720737461604482015261746560f01b606482015260840161024e565b336000818152600160209081526040808320805460ff19166002179055908290528082205490516001600160a01b0390911692917f0cfa12ab8ee8dc6f9b68938d5e764dafed737d43dc5ec8443abf81e645276eb691a3565b60026001600160a01b03821660009081526001602052604090205460ff1660038111156104ab57634e487b7160e01b600052602160045260246000fd5b146104eb5760405162461bcd60e51b815260206004820152601060248201526f1ddbdc9ad95c881b9bdd081bdddb995960821b604482015260640161024e565b6001600160a01b038181166000908152602081905260409020541633146105545760405162461bcd60e51b815260206004820152601c60248201527f6f6e6c79206f776e65722063616e2072657469726520776f726b657200000000604482015260640161024e565b6001600160a01b038116600081815260016020526040808220805460ff19166003179055513392917f657b373e1262c26d1f1a83e8949f0af9067fe48026b308e47eec5ef6b40ff25d91a350565b60006001610309565b6001600160a01b03818116600090815260208190526040902054166105e25760405162461bcd60e51b815260040161024e906108dc565b6001600160a01b038181166000908152602081905260409020541633146105545760405162461bcd60e51b815260206004820152601f60248201527f6f6e6c792068697265722063616e2063616e63656c20746865206f6666657200604482015260640161024e565b61065481610305565b6106a05760405162461bcd60e51b815260206004820152601760248201527f776f726b6572206973206e6f7420617661696c61626c65000000000000000000604482015260640161024e565b6001600160a01b0381166106f65760405162461bcd60e51b815260206004820152601d60248201527f776f726b657220616464726573732063616e206e6f7420626520307830000000604482015260640161024e565b66038d7ea4c680003410156107455760405162461bcd60e51b815260206004820152601560248201527466756e64696e672062656c6f77206d696e696d756d60581b604482015260640161024e565b6729a2241af62c00003411156107955760405162461bcd60e51b815260206004820152601560248201527466756e64696e672061626f7665206d6178696d756d60581b604482015260640161024e565b6001600160a01b03811660009081526020818152604080832080546001600160a01b03191633179055600191829052909120805460ff1916828002179055506040516001600160a01b038216903480156108fc02916000818181858888f19350505050158015610809573d6000803e3d6000fd5b5060405133906001600160a01b038316907f2e0aa97ef0e6f4f76319861c90e91beec7a7a44a698cab856dfc1985a0c588f090600090a350565b60006002610309565b600060026001600160a01b03831660009081526001602052604090205460ff16600381111561088b57634e487b7160e01b600052602160045260246000fd5b146108975760006108b3565b6001600160a01b03808316600090815260208190526040902054165b92915050565b6000602082840312156108ca578081fd5b81356108d581610911565b9392505050565b6020808252818101527f776f726b657220646f6573206e6f7420686176652061206a6f62206f66666572604082015260600190565b6001600160a01b038116811461092657600080fd5b5056fea26469706673582212204f10e5c420944ca621a08a09fa16ebe0123c0a671181c14a268338dad73fcebc64736f6c63430008040033", + "devdoc": { + "kind": "dev", + "methods": { + "isAvailable(address)": { + "params": { + "workerAddress": "address of the worker node" + } + }, + "isPending(address)": { + "params": { + "workerAddress": "address of the worker node" + } + } + }, + "stateVariables": { + "MAXIMUM_FUNDING": { + "details": "transfers bigger than maximum value should be done directly" + }, + "MINIMUM_FUNDING": { + "details": "user can only hire a worker if he sends more than minimum value" + }, + "stateOf": { + "details": "mapping from worker to its internal state" + }, + "userOf": { + "details": "mapping from worker to its user" + } + }, + "version": 1 + }, + "userdoc": { + "events": { + "JobOffer(address,address)": { + "notice": "Events signalling every state transition" + } + }, + "kind": "user", + "methods": { + "acceptJob()": { + "notice": "Called by the worker to accept the job" + }, + "isAvailable(address)": { + "notice": "Returns true if worker node is available" + }, + "isPending(address)": { + "notice": "Returns true if worker node is pending" + }, + "rejectJob()": { + "notice": "Called by the worker to reject a job offer" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 903, + "contract": "contracts/WorkerManagerImpl.sol:WorkerManagerImpl", + "label": "userOf", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_address_payable)" + }, + { + "astId": 909, + "contract": "contracts/WorkerManagerImpl.sol:WorkerManagerImpl", + "label": "stateOf", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_enum(WorkerState)898)" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_address_payable": { + "encoding": "inplace", + "label": "address payable", + "numberOfBytes": "20" + }, + "t_enum(WorkerState)898": { + "encoding": "inplace", + "label": "enum WorkerManagerImpl.WorkerState", + "numberOfBytes": "1" + }, + "t_mapping(t_address,t_address_payable)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => address payable)", + "numberOfBytes": "32", + "value": "t_address_payable" + }, + "t_mapping(t_address,t_enum(WorkerState)898)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => enum WorkerManagerImpl.WorkerState)", + "numberOfBytes": "32", + "value": "t_enum(WorkerState)898" + } + } + } +} \ No newline at end of file diff --git a/echo-js/deployments/localhost/dapp.address b/echo-js/deployments/localhost/dapp.address new file mode 100644 index 00000000..6e8c0685 --- /dev/null +++ b/echo-js/deployments/localhost/dapp.address @@ -0,0 +1 @@ +0xa37aE2b259D35aF4aBdde122eC90B204323ED304 \ No newline at end of file diff --git a/echo-js/deployments/localhost/solcInputs/853463bf44733f3d929a32fa4eacb9e6.json b/echo-js/deployments/localhost/solcInputs/853463bf44733f3d929a32fa4eacb9e6.json new file mode 100644 index 00000000..735c1e6d --- /dev/null +++ b/echo-js/deployments/localhost/solcInputs/853463bf44733f3d929a32fa4eacb9e6.json @@ -0,0 +1,203 @@ +{ + "language": "Solidity", + "sources": { + "contracts/Bank.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n// @title Bank contract\npragma solidity ^0.8.0;\n\nimport {IBank} from \"./IBank.sol\";\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ncontract Bank is IBank {\n IERC20 private immutable token;\n\n // `balances` maps account/contract addresses to balances\n mapping(address => uint256) private balances;\n\n constructor(address _token) {\n require(_token != address(0), \"Bank: invalid token\");\n token = IERC20(_token);\n }\n\n function getToken() public view override returns (IERC20) {\n return token;\n }\n\n function balanceOf(address _owner) public view override returns (uint256) {\n return balances[_owner];\n }\n\n function transferTokens(address _to, uint256 _value) public override {\n // checks\n uint256 balance = balances[msg.sender];\n require(_value <= balance, \"Bank: not enough balance\");\n\n // effects\n // Note: this should not underflow because we checked that\n // `_value <= balance` in the `require` above\n unchecked {\n balances[msg.sender] = balance - _value;\n }\n\n // interactions\n // Note: a well-implemented ERC-20 contract should already\n // require the recipient (in this case, `_to`) to be different\n // than address(0), so we don't need to check it ourselves\n require(token.transfer(_to, _value), \"Bank: transfer failed\");\n emit Transfer(msg.sender, _to, _value);\n }\n\n function depositTokens(address _to, uint256 _value) public override {\n // checks\n require(_to != address(0), \"Bank: invalid recipient\");\n\n // effects\n // Note: this should not overflow because `IERC20.totalSupply`\n // returns a `uint256` value, so there can't be more than\n // `uint256.max` tokens in an ERC-20 contract.\n balances[_to] += _value;\n\n // interactions\n // Note: transfers tokens to bank, but emits `Deposit` event\n // with recipient being `_to`\n require(\n token.transferFrom(msg.sender, address(this), _value),\n \"Bank: transferFrom failed\"\n );\n emit Deposit(msg.sender, _to, _value);\n }\n}\n" + }, + "contracts/IBank.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n// @title Bank interface\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface IBank {\n /// @notice returns the token used internally\n function getToken() external view returns (IERC20);\n\n /// @notice get balance of `_owner`\n /// @param _owner account owner\n function balanceOf(address _owner) external view returns (uint256);\n\n /// @notice transfer `_value` tokens from bank to `_to`\n /// @notice decrease the balance of caller by `_value`\n /// @param _to account that will receive `_value` tokens\n /// @param _value amount of tokens to be transfered\n function transferTokens(address _to, uint256 _value) external;\n\n /// @notice transfer `_value` tokens from caller to bank\n /// @notice increase the balance of `_to` by `_value`\n /// @dev you may need to call `token.approve(bank, _value)`\n /// @param _to account that will have their balance increased by `_value`\n /// @param _value amount of tokens to be transfered\n function depositTokens(address _to, uint256 _value) external;\n\n /// @notice `value` tokens were transfered from the bank to `to`\n /// @notice the balance of `from` was decreased by `value`\n /// @dev is triggered on any successful call to `transferTokens`\n /// @param from the account/contract that called `transferTokens` and\n /// got their balance decreased by `value`\n /// @param to the one that received `value` tokens from the bank\n /// @param value amount of tokens that were transfered\n event Transfer(address indexed from, address to, uint256 value);\n\n /// @notice `value` tokens were transfered from `from` to bank\n /// @notice the balance of `to` was increased by `value`\n /// @dev is triggered on any successful call to `depositTokens`\n /// @param from the account/contract that called `depositTokens` and\n /// transfered `value` tokens to the bank\n /// @param to the one that got their balance increased by `value`\n /// @param value amount of tokens that were transfered\n event Deposit(address from, address indexed to, uint256 value);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n }\n _balances[to] += amount;\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/ERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC721.sol\";\nimport \"./IERC721Receiver.sol\";\nimport \"./extensions/IERC721Metadata.sol\";\nimport \"../../utils/Address.sol\";\nimport \"../../utils/Context.sol\";\nimport \"../../utils/Strings.sol\";\nimport \"../../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\ncontract ERC721 is Context, ERC165, IERC721, IERC721Metadata {\n using Address for address;\n using Strings for uint256;\n\n // Token name\n string private _name;\n\n // Token symbol\n string private _symbol;\n\n // Mapping from token ID to owner address\n mapping(uint256 => address) private _owners;\n\n // Mapping owner address to token count\n mapping(address => uint256) private _balances;\n\n // Mapping from token ID to approved address\n mapping(uint256 => address) private _tokenApprovals;\n\n // Mapping from owner to operator approvals\n mapping(address => mapping(address => bool)) private _operatorApprovals;\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev See {IERC721-balanceOf}.\n */\n function balanceOf(address owner) public view virtual override returns (uint256) {\n require(owner != address(0), \"ERC721: balance query for the zero address\");\n return _balances[owner];\n }\n\n /**\n * @dev See {IERC721-ownerOf}.\n */\n function ownerOf(uint256 tokenId) public view virtual override returns (address) {\n address owner = _owners[tokenId];\n require(owner != address(0), \"ERC721: owner query for nonexistent token\");\n return owner;\n }\n\n /**\n * @dev See {IERC721Metadata-name}.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev See {IERC721Metadata-symbol}.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev See {IERC721Metadata-tokenURI}.\n */\n function tokenURI(uint256 tokenId) public view virtual override returns (string memory) {\n require(_exists(tokenId), \"ERC721Metadata: URI query for nonexistent token\");\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string(abi.encodePacked(baseURI, tokenId.toString())) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /**\n * @dev See {IERC721-approve}.\n */\n function approve(address to, uint256 tokenId) public virtual override {\n address owner = ERC721.ownerOf(tokenId);\n require(to != owner, \"ERC721: approval to current owner\");\n\n require(\n _msgSender() == owner || isApprovedForAll(owner, _msgSender()),\n \"ERC721: approve caller is not owner nor approved for all\"\n );\n\n _approve(to, tokenId);\n }\n\n /**\n * @dev See {IERC721-getApproved}.\n */\n function getApproved(uint256 tokenId) public view virtual override returns (address) {\n require(_exists(tokenId), \"ERC721: approved query for nonexistent token\");\n\n return _tokenApprovals[tokenId];\n }\n\n /**\n * @dev See {IERC721-setApprovalForAll}.\n */\n function setApprovalForAll(address operator, bool approved) public virtual override {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /**\n * @dev See {IERC721-isApprovedForAll}.\n */\n function isApprovedForAll(address owner, address operator) public view virtual override returns (bool) {\n return _operatorApprovals[owner][operator];\n }\n\n /**\n * @dev See {IERC721-transferFrom}.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n //solhint-disable-next-line max-line-length\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n\n _transfer(from, to, tokenId);\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) public virtual override {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /**\n * @dev See {IERC721-safeTransferFrom}.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) public virtual override {\n require(_isApprovedOrOwner(_msgSender(), tokenId), \"ERC721: transfer caller is not owner nor approved\");\n _safeTransfer(from, to, tokenId, _data);\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * `_data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _transfer(from, to, tokenId);\n require(_checkOnERC721Received(from, to, tokenId, _data), \"ERC721: transfer to non ERC721Receiver implementer\");\n }\n\n /**\n * @dev Returns whether `tokenId` exists.\n *\n * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}.\n *\n * Tokens start existing when they are minted (`_mint`),\n * and stop existing when they are burned (`_burn`).\n */\n function _exists(uint256 tokenId) internal view virtual returns (bool) {\n return _owners[tokenId] != address(0);\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `tokenId`.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function _isApprovedOrOwner(address spender, uint256 tokenId) internal view virtual returns (bool) {\n require(_exists(tokenId), \"ERC721: operator query for nonexistent token\");\n address owner = ERC721.ownerOf(tokenId);\n return (spender == owner || isApprovedForAll(owner, spender) || getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Safely mints `tokenId` and transfers it to `to`.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal virtual {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(\n address to,\n uint256 tokenId,\n bytes memory _data\n ) internal virtual {\n _mint(to, tokenId);\n require(\n _checkOnERC721Received(address(0), to, tokenId, _data),\n \"ERC721: transfer to non ERC721Receiver implementer\"\n );\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal virtual {\n require(to != address(0), \"ERC721: mint to the zero address\");\n require(!_exists(tokenId), \"ERC721: token already minted\");\n\n _beforeTokenTransfer(address(0), to, tokenId);\n\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(address(0), to, tokenId);\n\n _afterTokenTransfer(address(0), to, tokenId);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal virtual {\n address owner = ERC721.ownerOf(tokenId);\n\n _beforeTokenTransfer(owner, address(0), tokenId);\n\n // Clear approvals\n _approve(address(0), tokenId);\n\n _balances[owner] -= 1;\n delete _owners[tokenId];\n\n emit Transfer(owner, address(0), tokenId);\n\n _afterTokenTransfer(owner, address(0), tokenId);\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {\n require(ERC721.ownerOf(tokenId) == from, \"ERC721: transfer from incorrect owner\");\n require(to != address(0), \"ERC721: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, tokenId);\n\n // Clear approvals from the previous owner\n _approve(address(0), tokenId);\n\n _balances[from] -= 1;\n _balances[to] += 1;\n _owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n _afterTokenTransfer(from, to, tokenId);\n }\n\n /**\n * @dev Approve `to` to operate on `tokenId`\n *\n * Emits a {Approval} event.\n */\n function _approve(address to, uint256 tokenId) internal virtual {\n _tokenApprovals[tokenId] = to;\n emit Approval(ERC721.ownerOf(tokenId), to, tokenId);\n }\n\n /**\n * @dev Approve `operator` to operate on all of `owner` tokens\n *\n * Emits a {ApprovalForAll} event.\n */\n function _setApprovalForAll(\n address owner,\n address operator,\n bool approved\n ) internal virtual {\n require(owner != operator, \"ERC721: approve to caller\");\n _operatorApprovals[owner][operator] = approved;\n emit ApprovalForAll(owner, operator, approved);\n }\n\n /**\n * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address.\n * The call is not executed if the target address is not a contract.\n *\n * @param from address representing the previous owner of the given token ID\n * @param to target address that will receive the tokens\n * @param tokenId uint256 ID of the token to be transferred\n * @param _data bytes optional data to send along with the call\n * @return bool whether the call correctly returned the expected magic value\n */\n function _checkOnERC721Received(\n address from,\n address to,\n uint256 tokenId,\n bytes memory _data\n ) private returns (bool) {\n if (to.isContract()) {\n try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) {\n return retval == IERC721Receiver.onERC721Received.selector;\n } catch (bytes memory reason) {\n if (reason.length == 0) {\n revert(\"ERC721: transfer to non ERC721Receiver implementer\");\n } else {\n assembly {\n revert(add(32, reason), mload(reason))\n }\n }\n }\n } else {\n return true;\n }\n }\n\n /**\n * @dev Hook that is called before any token transfer. This includes minting\n * and burning.\n *\n * Calling conditions:\n *\n * - When `from` and `to` are both non-zero, ``from``'s `tokenId` will be\n * transferred to `to`.\n * - When `from` is zero, `tokenId` will be minted for `to`.\n * - When `to` is zero, ``from``'s `tokenId` will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 tokenId\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../utils/introspection/IERC165.sol\";\n\n/**\n * @dev Required interface of an ERC721 compliant contract.\n */\ninterface IERC721 is IERC165 {\n /**\n * @dev Emitted when `tokenId` token is transferred from `from` to `to`.\n */\n event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.\n */\n event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);\n\n /**\n * @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.\n */\n event ApprovalForAll(address indexed owner, address indexed operator, bool approved);\n\n /**\n * @dev Returns the number of tokens in ``owner``'s account.\n */\n function balanceOf(address owner) external view returns (uint256 balance);\n\n /**\n * @dev Returns the owner of the `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function ownerOf(uint256 tokenId) external view returns (address owner);\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId,\n bytes calldata data\n ) external;\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients\n * are aware of the ERC721 protocol to prevent tokens from being forever locked.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must exist and be owned by `from`.\n * - If the caller is not `from`, it must be have been allowed to move this token by either {approve} or {setApprovalForAll}.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function safeTransferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Transfers `tokenId` token from `from` to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {safeTransferFrom} whenever possible.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n * - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 tokenId\n ) external;\n\n /**\n * @dev Gives permission to `to` to transfer `tokenId` token to another account.\n * The approval is cleared when the token is transferred.\n *\n * Only a single account can be approved at a time, so approving the zero address clears previous approvals.\n *\n * Requirements:\n *\n * - The caller must own the token or be an approved operator.\n * - `tokenId` must exist.\n *\n * Emits an {Approval} event.\n */\n function approve(address to, uint256 tokenId) external;\n\n /**\n * @dev Approve or remove `operator` as an operator for the caller.\n * Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.\n *\n * Requirements:\n *\n * - The `operator` cannot be the caller.\n *\n * Emits an {ApprovalForAll} event.\n */\n function setApprovalForAll(address operator, bool _approved) external;\n\n /**\n * @dev Returns the account approved for `tokenId` token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n */\n function getApproved(uint256 tokenId) external view returns (address operator);\n\n /**\n * @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.\n *\n * See {setApprovalForAll}\n */\n function isApprovedForAll(address owner, address operator) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC721/IERC721Receiver.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title ERC721 token receiver interface\n * @dev Interface for any contract that wants to support safeTransfers\n * from ERC721 asset contracts.\n */\ninterface IERC721Receiver {\n /**\n * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}\n * by `operator` from `from`, this function is called.\n *\n * It must return its Solidity selector to confirm the token transfer.\n * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.\n *\n * The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.\n */\n function onERC721Received(\n address operator,\n address from,\n uint256 tokenId,\n bytes calldata data\n ) external returns (bytes4);\n}\n" + }, + "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC721/extensions/IERC721Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC721.sol\";\n\n/**\n * @title ERC-721 Non-Fungible Token Standard, optional metadata extension\n * @dev See https://eips.ethereum.org/EIPS/eip-721\n */\ninterface IERC721Metadata is IERC721 {\n /**\n * @dev Returns the token collection name.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the token collection symbol.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the Uniform Resource Identifier (URI) for `tokenId` token.\n */\n function tokenURI(uint256 tokenId) external view returns (string memory);\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCall(target, data, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n require(isContract(target), \"Address: call to non-contract\");\n\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n require(isContract(target), \"Address: static call to non-contract\");\n\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(isContract(target), \"Address: delegate call to non-contract\");\n\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResult(success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "contracts/facets/ERC721PortalFacet.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Generic ERC721 Portal facet\npragma solidity ^0.8.0;\n\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\n\nimport {IERC721Portal} from \"../interfaces/IERC721Portal.sol\";\n\nimport {LibInput} from \"../libraries/LibInput.sol\";\n\ncontract ERC721PortalFacet is IERC721Portal {\n using LibInput for LibInput.DiamondStorage;\n\n bytes32 constant INPUT_HEADER = keccak256(\"ERC721_Transfer\");\n\n /// @notice Handle the receipt of an NFT\n /// @dev The ERC721 smart contract calls this function on the recipient\n /// after a `transfer`. This function MAY throw to revert and reject the\n /// transfer. Return of other than the magic value MUST result in the\n /// transaction being reverted.\n /// Note: the contract address is always the message sender.\n /// @param _operator The address which called `safeTransferFrom` function\n /// @param _from The address which previously owned the token\n /// @param _tokenId The NFT identifier which is being transferred\n /// @param _data Additional data to be interpreted by L2\n /// @return this function selector unless throwing\n function onERC721Received(\n address _operator,\n address _from,\n uint256 _tokenId,\n bytes calldata _data\n ) public override returns (bytes4) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n address erc721Contract = msg.sender;\n\n bytes memory input = abi.encode(\n INPUT_HEADER,\n erc721Contract,\n _operator,\n _from,\n _tokenId,\n _data\n );\n\n inputDS.addInternalInput(input);\n\n emit ERC721Received(erc721Contract, _operator, _from, _tokenId, _data);\n\n // return the magic value to approve the transfer\n return this.onERC721Received.selector;\n }\n\n /// @notice withdraw an ERC721 token from the portal\n /// @param _data data with withdrawal information\n /// @dev can only be called by the Rollups contract\n function erc721Withdrawal(bytes calldata _data)\n public\n override\n returns (bool)\n {\n // Delegate calls preserve msg.sender, msg.value and address(this)\n require(msg.sender == address(this), \"only itself\");\n\n (address tokenAddr, address payable receiver, uint256 tokenId) = abi\n .decode(_data, (address, address, uint256));\n\n IERC721 token = IERC721(tokenAddr);\n\n // transfer reverts on failure\n token.safeTransferFrom(address(this), receiver, tokenId);\n\n emit ERC721Withdrawn(tokenAddr, receiver, tokenId);\n return true;\n }\n}\n" + }, + "contracts/interfaces/IERC721Portal.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Generic ERC721 Portal interface\npragma solidity >=0.7.0;\n\nimport {IERC721Receiver} from \"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol\";\n\ninterface IERC721Portal is IERC721Receiver {\n /// @notice withdraw an ERC721 token from the portal\n /// @param _data data with withdrawal information\n /// @dev can only be called by the Rollups contract\n function erc721Withdrawal(bytes calldata _data) external returns (bool);\n\n /// @notice emitted on a call to `onERC721Received`\n event ERC721Received(\n address ERC721,\n address operator,\n address sender,\n uint256 tokenId,\n bytes data\n );\n\n /// @notice emitted on ERC721 withdrawal\n event ERC721Withdrawn(\n address ERC721,\n address payable receiver,\n uint256 tokenId\n );\n}\n" + }, + "contracts/libraries/LibInput.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Input library\npragma solidity ^0.8.0;\n\nimport {LibRollups} from \"../libraries/LibRollups.sol\";\n\nlibrary LibInput {\n using LibRollups for LibRollups.DiamondStorage;\n\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"Input.diamond.storage\");\n\n struct DiamondStorage {\n // always needs to keep track of two input boxes:\n // 1 for the input accumulation of next epoch\n // and 1 for the messages during current epoch. To save gas we alternate\n // between inputBox0 and inputBox1\n bytes32[] inputBox0;\n bytes32[] inputBox1;\n uint256 inputDriveSize; // size of input flashdrive\n uint256 currentInputBox;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n /// @notice get input inside inbox of currently proposed claim\n /// @param ds diamond storage pointer\n /// @param index index of input inside that inbox\n /// @return hash of input at index index\n /// @dev currentInputBox being zero means that the inputs for\n /// the claimed epoch are on input box one\n function getInput(DiamondStorage storage ds, uint256 index)\n internal\n view\n returns (bytes32)\n {\n return\n ds.currentInputBox == 0 ? ds.inputBox1[index] : ds.inputBox0[index];\n }\n\n /// @notice get number of inputs inside inbox of currently proposed claim\n /// @param ds diamond storage pointer\n /// @return number of inputs on that input box\n /// @dev currentInputBox being zero means that the inputs for\n /// the claimed epoch are on input box one\n function getNumberOfInputs(DiamondStorage storage ds)\n internal\n view\n returns (uint256)\n {\n return\n ds.currentInputBox == 0 ? ds.inputBox1.length : ds.inputBox0.length;\n }\n\n /// @notice add input to processed by next epoch\n /// @param ds diamond storage pointer\n /// @param input input to be understood by offchain machine\n /// @dev offchain code is responsible for making sure\n /// that input size is power of 2 and multiple of 8 since\n /// the offchain machine has a 8 byte word\n function addInput(DiamondStorage storage ds, bytes memory input)\n internal\n returns (bytes32)\n {\n return addInputFromSender(ds, input, msg.sender);\n }\n\n /// @notice add internal input to processed by next epoch\n /// @notice this function is to be reserved for internal usage only\n /// @notice for normal inputs, call `addInput` instead\n /// @param ds diamond storage pointer\n /// @param input input to be understood by offchain machine\n /// @dev offchain code is responsible for making sure\n /// that input size is power of 2 and multiple of 8 since\n /// the offchain machine has a 8 byte word\n function addInternalInput(DiamondStorage storage ds, bytes memory input)\n internal\n returns (bytes32)\n {\n return addInputFromSender(ds, input, address(this));\n }\n\n /// @notice add input from a specific sender to processed by next epoch\n /// @notice this function is to be reserved for internal usage only\n /// @notice for normal inputs, call `addInput` instead\n /// @param ds diamond storage pointer\n /// @param input input to be understood by offchain machine\n /// @param sender input sender address\n /// @dev offchain code is responsible for making sure\n /// that input size is power of 2 and multiple of 8 since\n /// the offchain machine has a 8 byte word\n function addInputFromSender(\n DiamondStorage storage ds,\n bytes memory input,\n address sender\n ) internal returns (bytes32) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n\n require(input.length <= ds.inputDriveSize, \"input len: [0,driveSize]\");\n\n // notifyInput returns true if that input\n // belongs to a new epoch\n if (rollupsDS.notifyInput()) {\n swapInputBox(ds);\n }\n\n // points to correct inputBox\n bytes32[] storage inputBox = ds.currentInputBox == 0\n ? ds.inputBox0\n : ds.inputBox1;\n\n // get current epoch index\n uint256 currentEpoch = rollupsDS.getCurrentEpoch();\n\n // keccak 64 bytes into 32 bytes\n bytes32 keccakMetadata = keccak256(\n abi.encode(\n sender,\n block.number,\n block.timestamp,\n currentEpoch, // epoch index\n inputBox.length // input index\n )\n );\n\n bytes32 keccakInput = keccak256(input);\n\n bytes32 inputHash = keccak256(abi.encode(keccakMetadata, keccakInput));\n\n // add input to correct inbox\n inputBox.push(inputHash);\n\n emit InputAdded(\n currentEpoch,\n inputBox.length - 1,\n sender,\n block.timestamp,\n input\n );\n\n return inputHash;\n }\n\n /// @notice called when a new input accumulation phase begins\n /// swap inbox to receive inputs for upcoming epoch\n /// @param ds diamond storage pointer\n function onNewInputAccumulation(DiamondStorage storage ds) internal {\n swapInputBox(ds);\n }\n\n /// @notice called when a new epoch begins, clears deprecated inputs\n /// @param ds diamond storage pointer\n function onNewEpoch(DiamondStorage storage ds) internal {\n // clear input box for new inputs\n // the current input box should be accumulating inputs\n // for the new epoch already. So we clear the other one.\n ds.currentInputBox == 0 ? delete ds.inputBox1 : delete ds.inputBox0;\n }\n\n /// @notice changes current input box\n /// @param ds diamond storage pointer\n function swapInputBox(DiamondStorage storage ds) internal {\n ds.currentInputBox = (ds.currentInputBox == 0) ? 1 : 0;\n }\n\n /// @notice input added\n /// @param epochNumber which epoch this input belongs to\n /// @param inputIndex index of the input just added\n /// @param sender msg.sender\n /// @param timestamp block.timestamp\n /// @param input input data\n event InputAdded(\n uint256 indexed epochNumber,\n uint256 indexed inputIndex,\n address sender,\n uint256 timestamp,\n bytes input\n );\n}\n" + }, + "contracts/libraries/LibRollups.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Rollups library\npragma solidity ^0.8.0;\n\nimport {Phase} from \"../interfaces/IRollups.sol\";\nimport {Result} from \"../interfaces/IValidatorManager.sol\";\n\nimport {LibInput} from \"../libraries/LibInput.sol\";\nimport {LibOutput} from \"../libraries/LibOutput.sol\";\nimport {LibValidatorManager} from \"../libraries/LibValidatorManager.sol\";\nimport {LibDisputeManager} from \"../libraries/LibDisputeManager.sol\";\n\nlibrary LibRollups {\n using LibInput for LibInput.DiamondStorage;\n using LibOutput for LibOutput.DiamondStorage;\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\n\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"Rollups.diamond.storage\");\n\n struct DiamondStorage {\n bytes32 templateHash; // state hash of the cartesi machine at t0\n uint32 inputDuration; // duration of input accumulation phase in seconds\n uint32 challengePeriod; // duration of challenge period in seconds\n uint32 inputAccumulationStart; // timestamp when current input accumulation phase started\n uint32 sealingEpochTimestamp; // timestamp on when a proposed epoch (claim) becomes challengeable\n uint32 currentPhase_int; // current phase in integer form\n }\n\n /// @notice epoch finalized\n /// @param epochNumber number of the epoch being finalized\n /// @param epochHash claim being submitted by this epoch\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\n\n /// @notice dispute resolved\n /// @param winner winner of dispute\n /// @param loser loser of dispute\n /// @param winningClaim initial claim of winning validator\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\n\n /// @notice phase change\n /// @param newPhase new phase\n event PhaseChange(Phase newPhase);\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n /// @notice called when new input arrives, manages the phase changes\n /// @param ds diamond storage pointer\n /// @dev can only be called by input contract\n function notifyInput(DiamondStorage storage ds) internal returns (bool) {\n Phase currentPhase = Phase(ds.currentPhase_int);\n uint256 inputAccumulationStart = ds.inputAccumulationStart;\n uint256 inputDuration = ds.inputDuration;\n\n if (\n currentPhase == Phase.InputAccumulation &&\n block.timestamp > inputAccumulationStart + inputDuration\n ) {\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\n emit PhaseChange(Phase.AwaitingConsensus);\n return true;\n }\n return false;\n }\n\n /// @notice called when a dispute is resolved by the dispute manager\n /// @param ds diamond storage pointer\n /// @param winner winner of dispute\n /// @param loser loser of dispute\n /// @param winningClaim initial claim of winning validator\n function resolveDispute(\n DiamondStorage storage ds,\n address payable winner,\n address payable loser,\n bytes32 winningClaim\n ) internal {\n Result result;\n bytes32[2] memory claims;\n address payable[2] memory claimers;\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n\n (result, claims, claimers) = validatorManagerDS.onDisputeEnd(\n winner,\n loser,\n winningClaim\n );\n\n // restart challenge period\n ds.sealingEpochTimestamp = uint32(block.timestamp);\n\n emit ResolveDispute(winner, loser, winningClaim);\n resolveValidatorResult(ds, result, claims, claimers);\n }\n\n /// @notice resolve results returned by validator manager\n /// @param ds diamond storage pointer\n /// @param result result from claim or dispute operation\n /// @param claims array of claims in case of new conflict\n /// @param claimers array of claimers in case of new conflict\n function resolveValidatorResult(\n DiamondStorage storage ds,\n Result result,\n bytes32[2] memory claims,\n address payable[2] memory claimers\n ) internal {\n if (result == Result.NoConflict) {\n Phase currentPhase = Phase(ds.currentPhase_int);\n if (currentPhase != Phase.AwaitingConsensus) {\n ds.currentPhase_int = uint32(Phase.AwaitingConsensus);\n emit PhaseChange(Phase.AwaitingConsensus);\n }\n } else if (result == Result.Consensus) {\n startNewEpoch(ds);\n } else {\n // for the case when result == Result.Conflict\n Phase currentPhase = Phase(ds.currentPhase_int);\n if (currentPhase != Phase.AwaitingDispute) {\n ds.currentPhase_int = uint32(Phase.AwaitingDispute);\n emit PhaseChange(Phase.AwaitingDispute);\n }\n LibDisputeManager.initiateDispute(claims, claimers);\n }\n }\n\n /// @notice starts new epoch\n /// @param ds diamond storage pointer\n function startNewEpoch(DiamondStorage storage ds) internal {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n\n // reset input accumulation start and deactivate challenge period start\n ds.currentPhase_int = uint32(Phase.InputAccumulation);\n emit PhaseChange(Phase.InputAccumulation);\n ds.inputAccumulationStart = uint32(block.timestamp);\n ds.sealingEpochTimestamp = type(uint32).max;\n\n bytes32 finalClaim = validatorManagerDS.onNewEpoch();\n\n // emit event before finalized epoch is added to the Output storage\n emit FinalizeEpoch(outputDS.getNumberOfFinalizedEpochs(), finalClaim);\n\n outputDS.onNewEpoch(finalClaim);\n inputDS.onNewEpoch();\n }\n\n /// @notice returns index of current (accumulating) epoch\n /// @param ds diamond storage pointer\n /// @return index of current epoch\n /// @dev if phase is input accumulation, then the epoch number is length\n /// of finalized epochs array, else there are two non finalized epochs,\n /// one awaiting consensus/dispute and another accumulating input\n function getCurrentEpoch(DiamondStorage storage ds)\n internal\n view\n returns (uint256)\n {\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n\n uint256 finalizedEpochs = outputDS.getNumberOfFinalizedEpochs();\n\n Phase currentPhase = Phase(ds.currentPhase_int);\n\n return\n currentPhase == Phase.InputAccumulation\n ? finalizedEpochs\n : finalizedEpochs + 1;\n }\n}\n" + }, + "contracts/interfaces/IRollups.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Rollups interface\npragma solidity >=0.7.0;\n\n// InputAccumulation - Inputs being accumulated for currrent epoch\n// AwaitingConsensus - No disagreeing claims (or no claims)\n// AwaitingDispute - Waiting for dispute to be over\n// inputs received during InputAccumulation will be included in the\n// current epoch. Inputs received while WaitingClaims or ChallengesInProgress\n// are accumulated for the next epoch\nenum Phase {\n InputAccumulation,\n AwaitingConsensus,\n AwaitingDispute\n}\n\ninterface IRollups {\n /// @notice claim the result of current epoch\n /// @param _epochHash hash of epoch\n /// @dev ValidatorManager makes sure that msg.sender is allowed\n /// and that claim != bytes32(0)\n /// TODO: add signatures for aggregated claims\n function claim(bytes32 _epochHash) external;\n\n /// @notice finalize epoch after timeout\n /// @dev can only be called if challenge period is over\n function finalizeEpoch() external;\n\n /// @notice returns index of current (accumulating) epoch\n /// @return index of current epoch\n /// @dev if phase is input accumulation, then the epoch number is length\n /// of finalized epochs array, else there are two epochs two non\n /// finalized epochs, one awaiting consensus/dispute and another\n /// accumulating input\n function getCurrentEpoch() external view returns (uint256);\n\n /// @notice claim submitted\n /// @param epochHash claim being submitted by this epoch\n /// @param claimer address of current claimer\n /// @param epochNumber number of the epoch being submitted\n event Claim(\n uint256 indexed epochNumber,\n address claimer,\n bytes32 epochHash\n );\n\n /// @notice epoch finalized\n /// @param epochNumber number of the epoch being finalized\n /// @param epochHash claim being submitted by this epoch\n event FinalizeEpoch(uint256 indexed epochNumber, bytes32 epochHash);\n\n /// @notice dispute resolved\n /// @param winner winner of dispute\n /// @param loser loser of dispute\n /// @param winningClaim initial claim of winning validator\n event ResolveDispute(address winner, address loser, bytes32 winningClaim);\n\n /// @notice phase change\n /// @param newPhase new phase\n event PhaseChange(Phase newPhase);\n}\n" + }, + "contracts/interfaces/IValidatorManager.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Validator Manager interface\npragma solidity >=0.7.0;\n\n// NoConflict - No conflicting claims or consensus\n// Consensus - All validators had equal claims\n// Conflict - Claim is conflicting with previous one\nenum Result {\n NoConflict,\n Consensus,\n Conflict\n}\n\n// TODO: What is the incentive for validators to not just copy the first claim that arrived?\ninterface IValidatorManager {\n /// @notice get current claim\n function getCurrentClaim() external view returns (bytes32);\n\n /// @notice emitted on Claim received\n event ClaimReceived(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on Dispute end\n event DisputeEnded(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on new Epoch\n event NewEpoch(bytes32 claim);\n}\n" + }, + "contracts/libraries/LibOutput.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Output library\npragma solidity ^0.8.0;\n\nlibrary LibOutput {\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"Output.diamond.storage\");\n\n struct DiamondStorage {\n mapping(uint256 => uint256) voucherBitmask;\n bytes32[] epochHashes;\n bool lock; //reentrancy lock\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n /// @notice to be called when an epoch is finalized\n /// @param ds diamond storage pointer\n /// @param epochHash hash of finalized epoch\n /// @dev an epoch being finalized means that its vouchers can be called\n function onNewEpoch(DiamondStorage storage ds, bytes32 epochHash) internal {\n ds.epochHashes.push(epochHash);\n }\n\n /// @notice get number of finalized epochs\n /// @param ds diamond storage pointer\n function getNumberOfFinalizedEpochs(DiamondStorage storage ds)\n internal\n view\n returns (uint256)\n {\n return ds.epochHashes.length;\n }\n}\n" + }, + "contracts/libraries/LibValidatorManager.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Validator Manager library\npragma solidity ^0.8.0;\n\nimport {Result} from \"../interfaces/IValidatorManager.sol\";\n\nimport {LibClaimsMask, ClaimsMask} from \"../libraries/LibClaimsMask.sol\";\nimport {LibFeeManager} from \"../libraries/LibFeeManager.sol\";\n\nlibrary LibValidatorManager {\n using LibClaimsMask for ClaimsMask;\n using LibFeeManager for LibFeeManager.DiamondStorage;\n\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"ValidatorManager.diamond.storage\");\n\n struct DiamondStorage {\n bytes32 currentClaim; // current claim - first claim of this epoch\n address payable[] validators; // up to 8 validators\n uint256 maxNumValidators; // the maximum number of validators, set in the constructor\n // A bit set used for up to 8 validators.\n // The first 8 bits are used to indicate whom supports the current claim\n // The second 8 bits are used to indicate those should have claimed in order to reach consensus\n // The following every 30 bits are used to indicate the number of total claims each validator has made\n // | agreement mask | consensus mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\n // | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\n ClaimsMask claimsMask;\n }\n\n /// @notice emitted on Claim received\n event ClaimReceived(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on Dispute end\n event DisputeEnded(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on new Epoch\n event NewEpoch(bytes32 claim);\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n /// @notice called when a dispute ends in rollups\n /// @param ds diamond storage pointer\n /// @param winner address of dispute winner\n /// @param loser address of dispute loser\n /// @param winningClaim the winnning claim\n /// @return result of dispute being finished\n function onDisputeEnd(\n DiamondStorage storage ds,\n address payable winner,\n address payable loser,\n bytes32 winningClaim\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n removeValidator(ds, loser);\n\n if (winningClaim == ds.currentClaim) {\n // first claim stood, dont need to update the bitmask\n return\n isConsensus(ds)\n ? emitDisputeEndedAndReturn(\n Result.Consensus,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n )\n : emitDisputeEndedAndReturn(\n Result.NoConflict,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n );\n }\n\n // if first claim lost, and other validators have agreed with it\n // there is a new dispute to be played\n if (ds.claimsMask.getAgreementMask() != 0) {\n return\n emitDisputeEndedAndReturn(\n Result.Conflict,\n [ds.currentClaim, winningClaim],\n [getClaimerOfCurrentClaim(ds), winner]\n );\n }\n // else there are no valdiators that agree with losing claim\n // we can update current claim and check for consensus in case\n // the winner is the only validator left\n ds.currentClaim = winningClaim;\n updateClaimAgreementMask(ds, winner);\n return\n isConsensus(ds)\n ? emitDisputeEndedAndReturn(\n Result.Consensus,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n )\n : emitDisputeEndedAndReturn(\n Result.NoConflict,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n );\n }\n\n /// @notice called when a new epoch starts\n /// @param ds diamond storage pointer\n /// @return current claim\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\n // reward validators who has made the correct claim by increasing their #claims\n claimFinalizedIncreaseCounts(ds);\n\n bytes32 tmpClaim = ds.currentClaim;\n\n // clear current claim\n ds.currentClaim = bytes32(0);\n // clear validator agreement bit mask\n ds.claimsMask = ds.claimsMask.clearAgreementMask();\n\n emit NewEpoch(tmpClaim);\n return tmpClaim;\n }\n\n /// @notice called when a claim is received by rollups\n /// @param ds diamond storage pointer\n /// @param sender address of sender of that claim\n /// @param claim claim received by rollups\n /// @return result of claim, Consensus | NoConflict | Conflict\n /// @return [currentClaim, conflicting claim] if there is Conflict\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\n /// @return [claimer1, claimer2] if there is Conflcit\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\n function onClaim(\n DiamondStorage storage ds,\n address payable sender,\n bytes32 claim\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n require(claim != bytes32(0), \"empty claim\");\n require(isValidator(ds, sender), \"sender not allowed\");\n\n // require the validator hasn't claimed in the same epoch before\n uint256 index = getValidatorIndex(ds, sender);\n require(\n !ds.claimsMask.alreadyClaimed(index),\n \"sender had claimed in this epoch before\"\n );\n\n // cant return because a single claim might mean consensus\n if (ds.currentClaim == bytes32(0)) {\n ds.currentClaim = claim;\n } else if (claim != ds.currentClaim) {\n return\n emitClaimReceivedAndReturn(\n Result.Conflict,\n [ds.currentClaim, claim],\n [getClaimerOfCurrentClaim(ds), sender]\n );\n }\n updateClaimAgreementMask(ds, sender);\n\n return\n isConsensus(ds)\n ? emitClaimReceivedAndReturn(\n Result.Consensus,\n [claim, bytes32(0)],\n [sender, payable(0)]\n )\n : emitClaimReceivedAndReturn(\n Result.NoConflict,\n [claim, bytes32(0)],\n [sender, payable(0)]\n );\n }\n\n /// @notice emits dispute ended event and then return\n /// @param result to be emitted and returned\n /// @param claims to be emitted and returned\n /// @param validators to be emitted and returned\n /// @dev this function existis to make code more clear/concise\n function emitDisputeEndedAndReturn(\n Result result,\n bytes32[2] memory claims,\n address payable[2] memory validators\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n emit DisputeEnded(result, claims, validators);\n return (result, claims, validators);\n }\n\n /// @notice emits claim received event and then return\n /// @param result to be emitted and returned\n /// @param claims to be emitted and returned\n /// @param validators to be emitted and returned\n /// @dev this function existis to make code more clear/concise\n function emitClaimReceivedAndReturn(\n Result result,\n bytes32[2] memory claims,\n address payable[2] memory validators\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n emit ClaimReceived(result, claims, validators);\n return (result, claims, validators);\n }\n\n /// @notice only call this function when a claim has been finalized\n /// Either a consensus has been reached or challenge period has past\n /// @param ds pointer to diamond storage\n function claimFinalizedIncreaseCounts(DiamondStorage storage ds) internal {\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\n for (uint256 i; i < ds.validators.length; i++) {\n // if a validator agrees with the current claim\n if ((agreementMask & (1 << i)) != 0) {\n // increase #claims by 1\n ds.claimsMask = ds.claimsMask.increaseNumClaims(i, 1);\n }\n }\n }\n\n /// @notice removes a validator\n /// @param ds diamond storage pointer\n /// @param validator address of validator to be removed\n function removeValidator(DiamondStorage storage ds, address validator)\n internal\n {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n for (uint256 i; i < ds.validators.length; i++) {\n if (validator == ds.validators[i]) {\n // put address(0) in validators position\n ds.validators[i] = payable(0);\n // remove the validator from ValidatorManager's claimsMask\n ds.claimsMask = ds.claimsMask.removeValidator(i);\n // remove the validator from FeeManager's claimsMask (#redeems)\n feeManagerDS.removeValidator(i);\n break;\n }\n }\n }\n\n /// @notice check if consensus has been reached\n /// @param ds pointer to diamond storage\n function isConsensus(DiamondStorage storage ds)\n internal\n view\n returns (bool)\n {\n ClaimsMask claimsMask = ds.claimsMask;\n return\n claimsMask.getAgreementMask() == claimsMask.getConsensusGoalMask();\n }\n\n /// @notice get one of the validators that agreed with current claim\n /// @param ds diamond storage pointer\n /// @return validator that agreed with current claim\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\n internal\n view\n returns (address payable)\n {\n // TODO: we are always getting the first validator\n // on the array that agrees with the current claim to enter a dispute\n // should this be random?\n uint256 agreementMask = ds.claimsMask.getAgreementMask();\n for (uint256 i; i < ds.validators.length; i++) {\n if (agreementMask & (1 << i) != 0) {\n return ds.validators[i];\n }\n }\n revert(\"Agreeing validator not found\");\n }\n\n /// @notice updates mask of validators that agreed with current claim\n /// @param ds diamond storage pointer\n /// @param sender address of validator that will be included in mask\n function updateClaimAgreementMask(\n DiamondStorage storage ds,\n address payable sender\n ) internal {\n uint256 validatorIndex = getValidatorIndex(ds, sender);\n ds.claimsMask = ds.claimsMask.setAgreementMask(validatorIndex);\n }\n\n /// @notice check if the sender is a validator\n /// @param ds pointer to diamond storage\n /// @param sender sender address\n function isValidator(DiamondStorage storage ds, address sender)\n internal\n view\n returns (bool)\n {\n require(sender != address(0), \"address 0\");\n\n for (uint256 i; i < ds.validators.length; i++) {\n if (sender == ds.validators[i]) return true;\n }\n\n return false;\n }\n\n /// @notice find the validator and return the index or revert\n /// @param ds pointer to diamond storage\n /// @param sender validator address\n /// @return validator index or revert\n function getValidatorIndex(DiamondStorage storage ds, address sender)\n internal\n view\n returns (uint256)\n {\n require(sender != address(0), \"address 0\");\n for (uint256 i; i < ds.validators.length; i++) {\n if (sender == ds.validators[i]) return i;\n }\n revert(\"validator not found\");\n }\n\n /// @notice get number of claims the sender has made\n /// @param ds pointer to diamond storage\n /// @param _sender validator address\n /// @return #claims\n function getNumberOfClaimsByAddress(\n DiamondStorage storage ds,\n address payable _sender\n ) internal view returns (uint256) {\n for (uint256 i; i < ds.validators.length; i++) {\n if (_sender == ds.validators[i]) {\n return getNumberOfClaimsByIndex(ds, i);\n }\n }\n // if validator not found\n return 0;\n }\n\n /// @notice get number of claims by the index in the validator set\n /// @param ds pointer to diamond storage\n /// @param index the index in validator set\n /// @return #claims\n function getNumberOfClaimsByIndex(DiamondStorage storage ds, uint256 index)\n internal\n view\n returns (uint256)\n {\n return ds.claimsMask.getNumClaims(index);\n }\n\n /// @notice get the maximum number of validators defined in validator manager\n /// @param ds pointer to diamond storage\n /// @return the maximum number of validators\n function getMaxNumValidators(DiamondStorage storage ds)\n internal\n view\n returns (uint256)\n {\n return ds.maxNumValidators;\n }\n}\n" + }, + "contracts/libraries/LibDisputeManager.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Dispute Manager library\npragma solidity ^0.8.0;\n\nimport {LibRollups} from \"../libraries/LibRollups.sol\";\n\nlibrary LibDisputeManager {\n using LibRollups for LibRollups.DiamondStorage;\n\n /// @notice initiates a dispute betweent two players\n /// @param claims conflicting claims\n /// @param claimers addresses of senders of conflicting claim\n /// @dev this is a mock implementation that just gives the win\n /// to the address in the first posititon of claimers array\n function initiateDispute(\n bytes32[2] memory claims,\n address payable[2] memory claimers\n ) internal {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n rollupsDS.resolveDispute(claimers[0], claimers[1], claims[0]);\n }\n}\n" + }, + "contracts/libraries/LibClaimsMask.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title ClaimsMask library\npragma solidity >=0.8.8;\n\n// ClaimsMask is used to keep track of the number of claims for up to 8 validators\n// | agreement mask | consensus goal mask | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\n// | 8 bits | 8 bits | 30 bits | 30 bits | ... | 30 bits |\n// In Validator Manager, #claims_validator indicates the #claims the validator has made.\n// In Fee Manager, #claims_validator indicates the #claims the validator has redeemed. In this case,\n// agreement mask and consensus goal mask are not used.\n\ntype ClaimsMask is uint256;\n\nlibrary LibClaimsMask {\n uint256 constant claimsBitLen = 30; // #bits used for each #claims\n\n /// @notice this function creates a new ClaimsMask variable with value _value\n /// @param _value the value following the format of ClaimsMask\n function newClaimsMask(uint256 _value) internal pure returns (ClaimsMask) {\n return ClaimsMask.wrap(_value);\n }\n\n /// @notice this function creates a new ClaimsMask variable with the consensus goal mask set,\n /// according to the number of validators\n /// @param _numValidators the number of validators\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\n internal\n pure\n returns (ClaimsMask)\n {\n require(_numValidators <= 8, \"up to 8 validators\");\n uint256 consensusMask = (1 << _numValidators) - 1;\n return ClaimsMask.wrap(consensusMask << 240); // 256 - 8 - 8 = 240\n }\n\n /// @notice this function returns the #claims for the specified validator\n /// @param _claimsMask the ClaimsMask value\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\n /// this index can be obtained though `getNumberOfClaimsByIndex` function in Validator Manager\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\n internal\n pure\n returns (uint256)\n {\n require(_validatorIndex < 8, \"index out of range\");\n uint256 bitmask = (1 << claimsBitLen) - 1;\n return\n (ClaimsMask.unwrap(_claimsMask) >>\n (claimsBitLen * _validatorIndex)) & bitmask;\n }\n\n /// @notice this function increases the #claims for the specified validator\n /// @param _claimsMask the ClaimsMask value\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\n /// @param _value the increase amount\n function increaseNumClaims(\n ClaimsMask _claimsMask,\n uint256 _validatorIndex,\n uint256 _value\n ) internal pure returns (ClaimsMask) {\n require(_validatorIndex < 8, \"index out of range\");\n uint256 currentNum = getNumClaims(_claimsMask, _validatorIndex);\n uint256 newNum = currentNum + _value; // overflows checked by default with sol0.8\n return setNumClaims(_claimsMask, _validatorIndex, newNum);\n }\n\n /// @notice this function sets the #claims for the specified validator\n /// @param _claimsMask the ClaimsMask value\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\n /// @param _value the set value\n function setNumClaims(\n ClaimsMask _claimsMask,\n uint256 _validatorIndex,\n uint256 _value\n ) internal pure returns (ClaimsMask) {\n require(_validatorIndex < 8, \"index out of range\");\n require(_value <= ((1 << claimsBitLen) - 1), \"ClaimsMask Overflow\");\n uint256 bitmask = ~(((1 << claimsBitLen) - 1) <<\n (claimsBitLen * _validatorIndex));\n uint256 clearedClaimsMask = ClaimsMask.unwrap(_claimsMask) & bitmask;\n _claimsMask = ClaimsMask.wrap(\n clearedClaimsMask | (_value << (claimsBitLen * _validatorIndex))\n );\n return _claimsMask;\n }\n\n /// @notice get consensus goal mask\n /// @param _claimsMask the ClaimsMask value\n function clearAgreementMask(ClaimsMask _claimsMask)\n internal\n pure\n returns (ClaimsMask)\n {\n uint256 clearedMask = ClaimsMask.unwrap(_claimsMask) & ((1 << 248) - 1); // 256 - 8 = 248\n return ClaimsMask.wrap(clearedMask);\n }\n\n /// @notice get the entire agreement mask\n /// @param _claimsMask the ClaimsMask value\n function getAgreementMask(ClaimsMask _claimsMask)\n internal\n pure\n returns (uint256)\n {\n return (ClaimsMask.unwrap(_claimsMask) >> 248); // get the first 8 bits\n }\n\n /// @notice check if a validator has already claimed\n /// @param _claimsMask the ClaimsMask value\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\n internal\n pure\n returns (bool)\n {\n // get the first 8 bits. Then & operation on the validator's bit to see if it's set\n return\n (((ClaimsMask.unwrap(_claimsMask) >> 248) >> _validatorIndex) &\n 1) != 0;\n }\n\n /// @notice set agreement mask for the specified validator\n /// @param _claimsMask the ClaimsMask value\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\n internal\n pure\n returns (ClaimsMask)\n {\n require(_validatorIndex < 8, \"index out of range\");\n uint256 setMask = (ClaimsMask.unwrap(_claimsMask) |\n (1 << (248 + _validatorIndex))); // 256 - 8 = 248\n return ClaimsMask.wrap(setMask);\n }\n\n /// @notice get the entire consensus goal mask\n /// @param _claimsMask the ClaimsMask value\n function getConsensusGoalMask(ClaimsMask _claimsMask)\n internal\n pure\n returns (uint256)\n {\n return ((ClaimsMask.unwrap(_claimsMask) << 8) >> 248); // get the second 8 bits\n }\n\n /// @notice remove validator from the ClaimsMask\n /// @param _claimsMask the ClaimsMask value\n /// @param _validatorIndex index of the validator in the validator array, starting from 0\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\n internal\n pure\n returns (ClaimsMask)\n {\n require(_validatorIndex < 8, \"index out of range\");\n uint256 claimsMaskValue = ClaimsMask.unwrap(_claimsMask);\n // remove validator from agreement bitmask\n uint256 zeroMask = ~(1 << (_validatorIndex + 248)); // 256 - 8 = 248\n claimsMaskValue = (claimsMaskValue & zeroMask);\n // remove validator from consensus goal mask\n zeroMask = ~(1 << (_validatorIndex + 240)); // 256 - 8 - 8 = 240\n claimsMaskValue = (claimsMaskValue & zeroMask);\n // remove validator from #claims\n return\n setNumClaims(ClaimsMask.wrap(claimsMaskValue), _validatorIndex, 0);\n }\n}\n" + }, + "contracts/libraries/LibFeeManager.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Fee Manager library\npragma solidity ^0.8.0;\n\nimport {LibValidatorManager} from \"../libraries/LibValidatorManager.sol\";\nimport {LibClaimsMask, ClaimsMask} from \"../libraries/LibClaimsMask.sol\";\nimport {IBank} from \"../IBank.sol\";\n\nlibrary LibFeeManager {\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\n using LibFeeManager for LibFeeManager.DiamondStorage;\n using LibClaimsMask for ClaimsMask;\n\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"FeeManager.diamond.storage\");\n\n struct DiamondStorage {\n address owner; // owner of Fee Manager\n uint256 feePerClaim;\n IBank bank; // bank that holds the tokens to pay validators\n bool lock; // reentrancy lock\n // A bit set used for up to 8 validators.\n // The first 16 bits are not used to keep compatibility with the validator manager contract.\n // The following every 30 bits are used to indicate the number of total claims each validator has made\n // | not used | #claims_validator7 | #claims_validator6 | ... | #claims_validator0 |\n // | 16 bits | 30 bits | 30 bits | ... | 30 bits |\n ClaimsMask numClaimsRedeemed;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n function onlyOwner(DiamondStorage storage ds) internal view {\n require(ds.owner == msg.sender, \"caller is not the owner\");\n }\n\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\n /// @param ds pointer to FeeManager's diamond storage\n /// @param _validator address of the validator\n function numClaimsRedeemable(DiamondStorage storage ds, address _validator)\n internal\n view\n returns (uint256)\n {\n require(_validator != address(0), \"address should not be 0\");\n\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\n uint256 totalClaims = validatorManagerDS.claimsMask.getNumClaims(\n valIndex\n );\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\n\n // underflow checked by default with sol0.8\n // which means if the validator is removed, calling this function will\n // either return 0 or revert\n return totalClaims - redeemedClaims;\n }\n\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\n /// @param ds pointer to FeeManager's diamond storage\n /// @param _validator address of the validator\n function getNumClaimsRedeemed(DiamondStorage storage ds, address _validator)\n internal\n view\n returns (uint256)\n {\n require(_validator != address(0), \"address should not be 0\");\n\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\n uint256 redeemedClaims = ds.numClaimsRedeemed.getNumClaims(valIndex);\n\n return redeemedClaims;\n }\n\n /// @notice contract owner can reset the value of fee per claim\n /// @param ds pointer to FeeManager's diamond storage\n /// @param _value the new value of fee per claim\n function resetFeePerClaim(DiamondStorage storage ds, uint256 _value)\n internal\n {\n // before resetting the feePerClaim, pay fees for all validators as per current rates\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n for (\n uint256 valIndex;\n valIndex < validatorManagerDS.maxNumValidators;\n valIndex++\n ) {\n address validator = validatorManagerDS.validators[valIndex];\n if (validator != address(0)) {\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(validator);\n if (nowRedeemingClaims > 0) {\n ds.numClaimsRedeemed = ds\n .numClaimsRedeemed\n .increaseNumClaims(valIndex, nowRedeemingClaims);\n\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\n ds.bank.transferTokens(validator, feesToSend); // will revert if transfer fails\n // emit the number of claimed being redeemed, instead of the amount of tokens\n emit FeeRedeemed(validator, nowRedeemingClaims);\n }\n }\n }\n ds.feePerClaim = _value;\n emit FeePerClaimReset(_value);\n }\n\n /// @notice this function can be called to redeem fees for validators\n /// @param ds pointer to FeeManager's diamond storage\n /// @param _validator address of the validator that is redeeming\n function redeemFee(DiamondStorage storage ds, address _validator) internal {\n // follow the Checks-Effects-Interactions pattern for security\n\n // ** checks **\n uint256 nowRedeemingClaims = ds.numClaimsRedeemable(_validator);\n require(nowRedeemingClaims > 0, \"nothing to redeem yet\");\n\n // ** effects **\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n uint256 valIndex = validatorManagerDS.getValidatorIndex(_validator); // will revert if not found\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.increaseNumClaims(\n valIndex,\n nowRedeemingClaims\n );\n\n // ** interactions **\n uint256 feesToSend = nowRedeemingClaims * ds.feePerClaim; // number of erc20 tokens to send\n ds.bank.transferTokens(_validator, feesToSend); // will revert if transfer fails\n // emit the number of claimed being redeemed, instead of the amount of tokens\n emit FeeRedeemed(_validator, nowRedeemingClaims);\n }\n\n /// @notice removes a validator\n /// @param ds diamond storage pointer\n /// @param index index of validator to be removed\n function removeValidator(DiamondStorage storage ds, uint256 index)\n internal\n {\n ds.numClaimsRedeemed = ds.numClaimsRedeemed.setNumClaims(index, 0);\n }\n\n /// @notice emitted on resetting feePerClaim\n event FeePerClaimReset(uint256 value);\n\n /// @notice emitted on ERC20 funds redeemed by validator\n event FeeRedeemed(address validator, uint256 claims);\n}\n" + }, + "contracts/facets/RollupsFacet.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Rollups facet\npragma solidity ^0.8.0;\n\nimport {IRollups, Phase} from \"../interfaces/IRollups.sol\";\nimport {Result} from \"../interfaces/IValidatorManager.sol\";\n\nimport {LibRollups} from \"../libraries/LibRollups.sol\";\nimport {LibInput} from \"../libraries/LibInput.sol\";\nimport {LibOutput} from \"../libraries/LibOutput.sol\";\nimport {LibValidatorManager} from \"../libraries/LibValidatorManager.sol\";\n\ncontract RollupsFacet is IRollups {\n ////\n // All claims agreed OR challenge period ended\n // functions: claim() or finalizeEpoch()\n // +--------------------------------------------------+\n // | |\n // +--------v-----------+ new input after IPAD +---------+----------+\n // | +--------------------------->+ |\n // START ---> | Input Accumulation | firt claim after IPAD | Awaiting Consensus |\n // | +--------------------------->+ |\n // +-+------------------+ +-----------------+--+\n // ^ ^ |\n // | dispute resolved | |\n // | dispute resolved before challenge | |\n // | after challenge +--------------------+ period ended | |\n // | period ended | +---------------------+ |\n // +----------------------+ Awaiting Dispute | |\n // | +<-----------------------+\n // +--------------------+ conflicting claim\n ///\n\n using LibRollups for LibRollups.DiamondStorage;\n using LibInput for LibInput.DiamondStorage;\n using LibOutput for LibOutput.DiamondStorage;\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\n\n /// @notice claim the result of current epoch\n /// @param _epochHash hash of epoch\n /// @dev ValidatorManager makes sure that msg.sender is allowed\n /// and that claim != bytes32(0)\n /// TODO: add signatures for aggregated claims\n function claim(bytes32 _epochHash) public override {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n\n Result result;\n bytes32[2] memory claims;\n address payable[2] memory claimers;\n\n Phase currentPhase = Phase(rollupsDS.currentPhase_int);\n uint256 inputAccumulationStart = rollupsDS.inputAccumulationStart;\n uint256 inputDuration = rollupsDS.inputDuration;\n\n if (\n currentPhase == Phase.InputAccumulation &&\n block.timestamp > inputAccumulationStart + inputDuration\n ) {\n currentPhase = Phase.AwaitingConsensus;\n rollupsDS.currentPhase_int = uint32(Phase.AwaitingConsensus);\n emit PhaseChange(Phase.AwaitingConsensus);\n\n // warns input of new epoch\n inputDS.onNewInputAccumulation();\n // update timestamp of sealing epoch proposal\n rollupsDS.sealingEpochTimestamp = uint32(block.timestamp);\n }\n\n require(\n currentPhase == Phase.AwaitingConsensus,\n \"Phase != AwaitingConsensus\"\n );\n (result, claims, claimers) = validatorManagerDS.onClaim(\n payable(msg.sender),\n _epochHash\n );\n\n // emit the claim event before processing it\n // so if the epoch is finalized in this claim (consensus)\n // the number of final epochs doesnt gets contaminated\n emit Claim(\n outputDS.getNumberOfFinalizedEpochs(),\n msg.sender,\n _epochHash\n );\n\n rollupsDS.resolveValidatorResult(result, claims, claimers);\n }\n\n /// @notice finalize epoch after timeout\n /// @dev can only be called if challenge period is over\n function finalizeEpoch() public override {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n\n Phase currentPhase = Phase(rollupsDS.currentPhase_int);\n require(\n currentPhase == Phase.AwaitingConsensus,\n \"Phase != Awaiting Consensus\"\n );\n\n uint256 sealingEpochTimestamp = rollupsDS.sealingEpochTimestamp;\n uint256 challengePeriod = rollupsDS.challengePeriod;\n require(\n block.timestamp > sealingEpochTimestamp + challengePeriod,\n \"Challenge period not over\"\n );\n\n require(\n validatorManagerDS.currentClaim != bytes32(0),\n \"No Claim to be finalized\"\n );\n\n rollupsDS.startNewEpoch();\n }\n\n /// @notice returns index of current (accumulating) epoch\n /// @return index of current epoch\n /// @dev if phase is input accumulation, then the epoch number is length\n /// of finalized epochs array, else there are two non finalized epochs,\n /// one awaiting consensus/dispute and another accumulating input\n function getCurrentEpoch() public view override returns (uint256) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return rollupsDS.getCurrentEpoch();\n }\n\n /// @notice returns the current phase\n function getCurrentPhase() public view returns (Phase) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return Phase(rollupsDS.currentPhase_int);\n }\n\n /// @notice returns the input accumulation start timestamp\n function getInputAccumulationStart() public view returns (uint256) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return uint256(rollupsDS.inputAccumulationStart);\n }\n\n /// @notice returns the sealing epoch timestamp\n function getSealingEpochTimestamp() public view returns (uint256) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return uint256(rollupsDS.sealingEpochTimestamp);\n }\n\n /// @notice returns the input duration in seconds\n function getInputDuration() public view returns (uint256) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return uint256(rollupsDS.inputDuration);\n }\n\n /// @notice returns the challenge period in seconds\n function getChallengePeriod() public view returns (uint256) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return uint256(rollupsDS.challengePeriod);\n }\n\n /// @notice returns the machine's template hash\n function getTemplateHash() public view returns (bytes32) {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n return rollupsDS.templateHash;\n }\n}\n" + }, + "contracts/facets/ValidatorManagerFacet.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Validator Manager facet\npragma solidity ^0.8.0;\n\nimport {IValidatorManager} from \"../interfaces/IValidatorManager.sol\";\n\nimport {LibValidatorManager} from \"../libraries/LibValidatorManager.sol\";\n\nimport {LibClaimsMask, ClaimsMask} from \"../libraries/LibClaimsMask.sol\";\n\ncontract ValidatorManagerFacet is IValidatorManager {\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\n using LibClaimsMask for ClaimsMask;\n\n /// @notice get agreement mask\n /// @return current state of agreement mask\n function getAgreementMask() public view returns (uint256) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.claimsMask.getAgreementMask();\n }\n\n /// @notice get consensus goal mask\n /// @return current consensus goal mask\n function getConsensusGoalMask() public view returns (uint256) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.claimsMask.getConsensusGoalMask();\n }\n\n /// @notice get current claim\n /// @return current claim\n function getCurrentClaim() public view override returns (bytes32) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.currentClaim;\n }\n\n /// @notice get number of claims the sender has made\n /// @param _sender validator address\n /// @return #claims\n function getNumberOfClaimsByAddress(address payable _sender)\n public\n view\n returns (uint256)\n {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.getNumberOfClaimsByAddress(_sender);\n }\n\n /// @notice find the validator and return the index or revert\n /// @param _sender validator address\n /// @return validator index or revert\n function getValidatorIndex(address _sender) public view returns (uint256) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.getValidatorIndex(_sender);\n }\n\n /// @notice get number of claims by the index in the validator set\n /// @param _index the index in validator set\n /// @return #claims\n function getNumberOfClaimsByIndex(uint256 _index)\n public\n view\n returns (uint256)\n {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.getNumberOfClaimsByIndex(_index);\n }\n\n /// @notice get the maximum number of validators defined in validator manager\n /// @return the maximum number of validators\n function getMaxNumValidators() public view returns (uint256) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.getMaxNumValidators();\n }\n}\n" + }, + "contracts/test_helper/TestLibClaimsMask.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Test ClaimsMask library\npragma solidity >=0.8.8;\n\nimport \"../libraries/LibClaimsMask.sol\";\n\ncontract TestLibClaimsMask {\n function newClaimsMask(uint256 _value) public pure returns (ClaimsMask) {\n return LibClaimsMask.newClaimsMask(_value);\n }\n\n function newClaimsMaskWithConsensusGoalSet(uint256 _numValidators)\n public\n pure\n returns (ClaimsMask)\n {\n return LibClaimsMask.newClaimsMaskWithConsensusGoalSet(_numValidators);\n }\n\n function getNumClaims(ClaimsMask _claimsMask, uint256 _validatorIndex)\n public\n pure\n returns (uint256)\n {\n return LibClaimsMask.getNumClaims(_claimsMask, _validatorIndex);\n }\n\n function increaseNumClaims(\n ClaimsMask _claimsMask,\n uint256 _validatorIndex,\n uint256 _value\n ) public pure returns (ClaimsMask) {\n return\n LibClaimsMask.increaseNumClaims(\n _claimsMask,\n _validatorIndex,\n _value\n );\n }\n\n function setNumClaims(\n ClaimsMask _claimsMask,\n uint256 _validatorIndex,\n uint256 _value\n ) public pure returns (ClaimsMask) {\n return LibClaimsMask.setNumClaims(_claimsMask, _validatorIndex, _value);\n }\n\n function clearAgreementMask(ClaimsMask _claimsMask)\n public\n pure\n returns (ClaimsMask)\n {\n return LibClaimsMask.clearAgreementMask(_claimsMask);\n }\n\n function getAgreementMask(ClaimsMask _claimsMask)\n public\n pure\n returns (uint256)\n {\n return LibClaimsMask.getAgreementMask(_claimsMask);\n }\n\n function alreadyClaimed(ClaimsMask _claimsMask, uint256 _validatorIndex)\n public\n pure\n returns (bool)\n {\n return LibClaimsMask.alreadyClaimed(_claimsMask, _validatorIndex);\n }\n\n function setAgreementMask(ClaimsMask _claimsMask, uint256 _validatorIndex)\n public\n pure\n returns (ClaimsMask)\n {\n return LibClaimsMask.setAgreementMask(_claimsMask, _validatorIndex);\n }\n\n function getConsensusGoalMask(ClaimsMask _claimsMask)\n public\n pure\n returns (uint256)\n {\n return LibClaimsMask.getConsensusGoalMask(_claimsMask);\n }\n\n function removeValidator(ClaimsMask _claimsMask, uint256 _validatorIndex)\n public\n pure\n returns (ClaimsMask)\n {\n return LibClaimsMask.removeValidator(_claimsMask, _validatorIndex);\n }\n}\n" + }, + "contracts/facets/DebugFacet.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Debug facet\npragma solidity ^0.8.0;\n\nimport {Result} from \"../interfaces/IValidatorManager.sol\";\nimport {Phase} from \"../interfaces/IRollups.sol\";\nimport {IEtherPortal} from \"../interfaces/IEtherPortal.sol\";\nimport {IERC20Portal} from \"../interfaces/IERC20Portal.sol\";\nimport {IERC721Portal} from \"../interfaces/IERC721Portal.sol\";\n\nimport {LibRollups} from \"../libraries/LibRollups.sol\";\nimport {LibInput} from \"../libraries/LibInput.sol\";\nimport {LibOutput} from \"../libraries/LibOutput.sol\";\nimport {LibValidatorManager} from \"../libraries/LibValidatorManager.sol\";\nimport {LibFeeManager} from \"../libraries/LibFeeManager.sol\";\nimport {LibClaimsMask, ClaimsMask} from \"../libraries/LibClaimsMask.sol\";\n\ncontract DebugFacet {\n using LibRollups for LibRollups.DiamondStorage;\n using LibInput for LibInput.DiamondStorage;\n using LibOutput for LibOutput.DiamondStorage;\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\n using LibFeeManager for LibFeeManager.DiamondStorage;\n using LibClaimsMask for ClaimsMask;\n\n function _setCurrentPhase(Phase _phase) public {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n rollupsDS.currentPhase_int = uint32(_phase);\n }\n\n function _getValidators() public view returns (address payable[] memory) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.validators;\n }\n\n function _onClaim(address payable _sender, bytes32 _claim)\n public\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.onClaim(_sender, _claim);\n }\n\n /// @notice called when a dispute ends in rollups\n /// @param _winner address of dispute winner\n /// @param _loser address of dispute loser\n /// @param _winningClaim the winning claim\n /// @return result of dispute being finished\n function _onDisputeEnd(\n address payable _winner,\n address payable _loser,\n bytes32 _winningClaim\n )\n public\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.onDisputeEnd(_winner, _loser, _winningClaim);\n }\n\n /// @notice called when a new epoch starts\n /// @return current claim\n function _onNewEpochVM() public returns (bytes32) {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n return validatorManagerDS.onNewEpoch();\n }\n\n function _getInputDriveSize() public view returns (uint256) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n return inputDS.inputDriveSize;\n }\n\n function _etherWithdrawal(bytes calldata _data) public returns (bool) {\n IEtherPortal etherPortal = IEtherPortal(address(this));\n return etherPortal.etherWithdrawal(_data);\n }\n\n function _onNewEpochOutput(bytes32 epochHash) public {\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n outputDS.onNewEpoch(epochHash);\n }\n\n function _erc721Withdrawal(bytes calldata _data) public returns (bool) {\n IERC721Portal erc721Portal = IERC721Portal(address(this));\n return erc721Portal.erc721Withdrawal(_data);\n }\n\n function _getFeePerClaim() public view returns (uint256) {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n return feeManagerDS.feePerClaim;\n }\n\n function _setNumClaims(uint256 _validatorIndex, uint256 _value) public {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n validatorManagerDS.claimsMask = validatorManagerDS\n .claimsMask\n .setNumClaims(_validatorIndex, _value);\n }\n\n function _getNumRedeems(uint256 _validatorIndex)\n public\n view\n returns (uint256)\n {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n return feeManagerDS.numClaimsRedeemed.getNumClaims(_validatorIndex);\n }\n\n /// @notice emitted on Claim received\n event ClaimReceived(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on Dispute end\n event DisputeEnded(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on new Epoch\n event NewEpoch(bytes32 claim);\n}\n" + }, + "contracts/interfaces/IEtherPortal.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Ether Portal interface\npragma solidity >=0.7.0;\n\ninterface IEtherPortal {\n /// @notice deposit an amount of Ether in the portal and create Ether in L2\n /// @param _data information to be interpreted by L2\n /// @return hash of input generated by deposit\n function etherDeposit(bytes calldata _data)\n external\n payable\n returns (bytes32);\n\n /// @notice withdraw an amount of Ether from the portal\n /// @param _data data with withdrawal information\n /// @dev can only be called by the Rollups contract\n function etherWithdrawal(bytes calldata _data) external returns (bool);\n\n /// @notice emitted on Ether deposited\n event EtherDeposited(address sender, uint256 amount, bytes data);\n\n /// @notice emitted on Ether withdrawal\n event EtherWithdrawn(address payable receiver, uint256 amount);\n}\n" + }, + "contracts/interfaces/IERC20Portal.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Generic ERC20 Portal interface\npragma solidity >=0.7.0;\n\ninterface IERC20Portal {\n /// @notice deposit an amount of a generic ERC20 token in the portal and create tokens in L2\n /// @param _ERC20 address of the ERC20 token contract\n /// @param _amount amount of the ERC20 token to be deposited\n /// @param _data information to be interpreted by L2\n /// @return hash of input generated by deposit\n function erc20Deposit(\n address _ERC20,\n uint256 _amount,\n bytes calldata _data\n ) external returns (bytes32);\n\n /// @notice emitted on ERC20 deposited\n event ERC20Deposited(\n address ERC20,\n address sender,\n uint256 amount,\n bytes data\n );\n}\n" + }, + "contracts/facets/OutputFacet.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Output facet\npragma solidity ^0.8.0;\n\nimport {Bitmask} from \"@cartesi/util/contracts/Bitmask.sol\";\nimport {Merkle} from \"@cartesi/util/contracts/Merkle.sol\";\n\nimport {IOutput, OutputValidityProof} from \"../interfaces/IOutput.sol\";\n\nimport {LibOutput} from \"../libraries/LibOutput.sol\";\nimport {LibFeeManager} from \"../libraries/LibFeeManager.sol\";\n\ncontract OutputFacet is IOutput {\n using LibOutput for LibOutput.DiamondStorage;\n\n // Here we only need 248 bits as keys in the mapping, but we use 256 bits for gas optimization\n using Bitmask for mapping(uint256 => uint256);\n\n uint256 constant KECCAK_LOG2_SIZE = 5; // keccak log2 size\n\n // max size of voucher metadata memory range 32 * (2^16) bytes\n uint256 constant VOUCHER_METADATA_LOG2_SIZE = 21;\n // max size of epoch voucher memory range 32 * (2^32) bytes\n uint256 constant EPOCH_VOUCHER_LOG2_SIZE = 37;\n\n // max size of notice metadata memory range 32 * (2^16) bytes\n uint256 constant NOTICE_METADATA_LOG2_SIZE = 21;\n // max size of epoch notice memory range 32 * (2^32) bytes\n uint256 constant EPOCH_NOTICE_LOG2_SIZE = 37;\n\n /// @notice functions modified by noReentrancy are not subject to recursion\n modifier noReentrancy() {\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n\n require(!outputDS.lock, \"reentrancy not allowed\");\n outputDS.lock = true;\n _;\n outputDS.lock = false;\n }\n\n /// @notice executes voucher\n /// @param _destination address that will execute the payload\n /// @param _payload payload to be executed by destination\n /// @param _v validity proof for this encoded voucher\n /// @return true if voucher was executed successfully\n /// @dev vouchers can only be executed once\n function executeVoucher(\n address _destination,\n bytes calldata _payload,\n OutputValidityProof calldata _v\n ) public override noReentrancy returns (bool) {\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n\n // avoid a malicious DApp developer from draining the Fee Manager's bank account\n require(_destination != address(feeManagerDS.bank), \"bad destination\");\n\n bytes memory encodedVoucher = abi.encode(_destination, _payload);\n\n // check if validity proof matches the voucher provided\n isValidVoucherProof(\n encodedVoucher,\n outputDS.epochHashes[_v.epochIndex],\n _v\n );\n\n uint256 voucherPosition = getBitMaskPosition(\n _v.outputIndex,\n _v.inputIndex,\n _v.epochIndex\n );\n\n // check if voucher has been executed\n require(\n !outputDS.voucherBitmask.getBit(voucherPosition),\n \"re-execution not allowed\"\n );\n\n // execute voucher\n (bool succ, ) = _destination.call(_payload);\n\n // if properly executed, mark it as executed and emit event\n if (succ) {\n outputDS.voucherBitmask.setBit(voucherPosition, true);\n emit VoucherExecuted(voucherPosition);\n }\n\n return succ;\n }\n\n /// @notice isValidProof reverts if the proof is invalid\n /// @dev _outputsEpochRootHash must be _v.vouchersEpochRootHash or\n /// or _v.noticesEpochRootHash\n function isValidProof(\n bytes memory _encodedOutput,\n bytes32 _epochHash,\n bytes32 _outputsEpochRootHash,\n uint256 _outputEpochLog2Size,\n uint256 _outputHashesLog2Size,\n OutputValidityProof calldata _v\n ) internal pure {\n // prove that outputs hash is represented in a finalized epoch\n require(\n keccak256(\n abi.encodePacked(\n _v.vouchersEpochRootHash,\n _v.noticesEpochRootHash,\n _v.machineStateHash\n )\n ) == _epochHash,\n \"epochHash incorrect\"\n );\n\n // prove that output metadata memory range is contained in epoch's output memory range\n require(\n Merkle.getRootAfterReplacementInDrive(\n getIntraDrivePosition(_v.inputIndex, KECCAK_LOG2_SIZE),\n KECCAK_LOG2_SIZE,\n _outputEpochLog2Size,\n keccak256(abi.encodePacked(_v.outputHashesRootHash)),\n _v.outputHashesInEpochSiblings\n ) == _outputsEpochRootHash,\n \"outputsEpochRootHash incorrect\"\n );\n\n // The hash of the output is converted to bytes (abi.encode) and\n // treated as data. The metadata output memory range stores that data while\n // being indifferent to its contents. To prove that the received\n // output is contained in the metadata output memory range we need to\n // prove that x, where:\n // x = keccak(\n // keccak(\n // keccak(hashOfOutput[0:7]),\n // keccak(hashOfOutput[8:15])\n // ),\n // keccak(\n // keccak(hashOfOutput[16:23]),\n // keccak(hashOfOutput[24:31])\n // )\n // )\n // is contained in it. We can't simply use hashOfOutput because the\n // log2size of the leaf is three (8 bytes) not five (32 bytes)\n bytes32 merkleRootOfHashOfOutput = Merkle.getMerkleRootFromBytes(\n abi.encodePacked(keccak256(_encodedOutput)),\n KECCAK_LOG2_SIZE\n );\n\n // prove that merkle root hash of bytes(hashOfOutput) is contained\n // in the output metadata array memory range\n require(\n Merkle.getRootAfterReplacementInDrive(\n getIntraDrivePosition(_v.outputIndex, KECCAK_LOG2_SIZE),\n KECCAK_LOG2_SIZE,\n _outputHashesLog2Size,\n merkleRootOfHashOfOutput,\n _v.keccakInHashesSiblings\n ) == _v.outputHashesRootHash,\n \"outputHashesRootHash incorrect\"\n );\n }\n\n /// @notice isValidVoucherProof reverts if the proof is invalid\n function isValidVoucherProof(\n bytes memory _encodedVoucher,\n bytes32 _epochHash,\n OutputValidityProof calldata _v\n ) public pure {\n isValidProof(\n _encodedVoucher,\n _epochHash,\n _v.vouchersEpochRootHash,\n EPOCH_VOUCHER_LOG2_SIZE,\n VOUCHER_METADATA_LOG2_SIZE,\n _v\n );\n }\n\n /// @notice isValidNoticeProof reverts if the proof is invalid\n function isValidNoticeProof(\n bytes memory _encodedNotice,\n bytes32 _epochHash,\n OutputValidityProof calldata _v\n ) public pure {\n isValidProof(\n _encodedNotice,\n _epochHash,\n _v.noticesEpochRootHash,\n EPOCH_NOTICE_LOG2_SIZE,\n NOTICE_METADATA_LOG2_SIZE,\n _v\n );\n }\n\n /// @notice get voucher position on bitmask\n /// @param _voucher of voucher inside the input\n /// @param _input which input, inside the epoch, the voucher belongs to\n /// @param _epoch which epoch the voucher belongs to\n /// @return position of that voucher on bitmask\n function getBitMaskPosition(\n uint256 _voucher,\n uint256 _input,\n uint256 _epoch\n ) public pure returns (uint256) {\n // voucher * 2 ** 128 + input * 2 ** 64 + epoch\n // this can't overflow because its impossible to have > 2**128 vouchers\n return (((_voucher << 128) | (_input << 64)) | _epoch);\n }\n\n /// @notice returns the position of a intra memory range on a memory range\n // with contents with the same size\n /// @param _index index of intra memory range\n /// @param _log2Size of intra memory range\n function getIntraDrivePosition(uint256 _index, uint256 _log2Size)\n public\n pure\n returns (uint256)\n {\n return (_index << _log2Size);\n }\n\n /// @notice get number of finalized epochs\n function getNumberOfFinalizedEpochs()\n public\n view\n override\n returns (uint256)\n {\n LibOutput.DiamondStorage storage outputDS = LibOutput.diamondStorage();\n return outputDS.getNumberOfFinalizedEpochs();\n }\n\n /// @notice get log2 size of voucher metadata memory range\n function getVoucherMetadataLog2Size()\n public\n pure\n override\n returns (uint256)\n {\n return VOUCHER_METADATA_LOG2_SIZE;\n }\n\n /// @notice get log2 size of epoch voucher memory range\n function getEpochVoucherLog2Size() public pure override returns (uint256) {\n return EPOCH_VOUCHER_LOG2_SIZE;\n }\n\n /// @notice get log2 size of notice metadata memory range\n function getNoticeMetadataLog2Size()\n public\n pure\n override\n returns (uint256)\n {\n return NOTICE_METADATA_LOG2_SIZE;\n }\n\n /// @notice get log2 size of epoch notice memory range\n function getEpochNoticeLog2Size() public pure override returns (uint256) {\n return EPOCH_NOTICE_LOG2_SIZE;\n }\n}\n" + }, + "@cartesi/util/contracts/Bitmask.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\npragma solidity ^0.8.0;\n\n/// @title Bit Mask Library\n/// @author Stephen Chen\n/// @notice Implements bit mask with dynamic array\nlibrary Bitmask {\n /// @notice Set a bit in the bit mask\n function setBit(\n mapping(uint256 => uint256) storage bitmask,\n uint256 _bit,\n bool _value\n ) public {\n // calculate the number of bits has been store in bitmask now\n uint256 positionOfMask = uint256(_bit / 256);\n uint256 positionOfBit = _bit % 256;\n\n if (_value) {\n bitmask[positionOfMask] =\n bitmask[positionOfMask] |\n (1 << positionOfBit);\n } else {\n bitmask[positionOfMask] =\n bitmask[positionOfMask] &\n ~(1 << positionOfBit);\n }\n }\n\n /// @notice Get a bit in the bit mask\n function getBit(mapping(uint256 => uint256) storage bitmask, uint256 _bit)\n public\n view\n returns (bool)\n {\n // calculate the number of bits has been store in bitmask now\n uint256 positionOfMask = uint256(_bit / 256);\n uint256 positionOfBit = _bit % 256;\n\n return ((bitmask[positionOfMask] & (1 << positionOfBit)) != 0);\n }\n}\n" + }, + "@cartesi/util/contracts/Merkle.sol": { + "content": "// Copyright 2020 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Library for Merkle proofs\npragma solidity ^0.8.0;\n\nimport \"./CartesiMath.sol\";\n\nlibrary Merkle {\n using CartesiMath for uint256;\n\n uint128 constant L_WORD_SIZE = 3; // word = 8 bytes, log = 3\n // number of hashes in EMPTY_TREE_HASHES\n uint128 constant EMPTY_TREE_SIZE = 1952; // 61*32=1952. 32 bytes per 61 indexes (64 words)\n\n // merkle root hashes of trees of zero concatenated\n // 32 bytes for each root, first one is keccak(0), second one is\n // keccak(keccack(0), keccak(0)) and so on\n\n bytes constant EMPTY_TREE_HASHES =\n hex\"011b4d03dd8c01f1049143cf9c4c817e4b167f1d1b83e5c6f0f10d89ba1e7bce4d9470a821fbe90117ec357e30bad9305732fb19ddf54a07dd3e29f440619254ae39ce8537aca75e2eff3e38c98011dfe934e700a0967732fc07b430dd656a233fc9a15f5b4869c872f81087bb6104b7d63e6f9ab47f2c43f3535eae7172aa7f17d2dd614cddaa4d879276b11e0672c9560033d3e8453a1d045339d34ba601b9c37b8b13ca95166fb7af16988a70fcc90f38bf9126fd833da710a47fb37a55e68e7a427fa943d9966b389f4f257173676090c6e95f43e2cb6d65f8758111e30930b0b9deb73e155c59740bacf14a6ff04b64bb8e201a506409c3fe381ca4ea90cd5deac729d0fdaccc441d09d7325f41586ba13c801b7eccae0f95d8f3933efed8b96e5b7f6f459e9cb6a2f41bf276c7b85c10cd4662c04cbbb365434726c0a0c9695393027fb106a8153109ac516288a88b28a93817899460d6310b71cf1e6163e8806fa0d4b197a259e8c3ac28864268159d0ac85f8581ca28fa7d2c0c03eb91e3eee5ca7a3da2b3053c9770db73599fb149f620e3facef95e947c0ee860b72122e31e4bbd2b7c783d79cc30f60c6238651da7f0726f767d22747264fdb046f7549f26cc70ed5e18baeb6c81bb0625cb95bb4019aeecd40774ee87ae29ec517a71f6ee264c5d761379b3d7d617ca83677374b49d10aec50505ac087408ca892b573c267a712a52e1d06421fe276a03efb1889f337201110fdc32a81f8e152499af665835aabfdc6740c7e2c3791a31c3cdc9f5ab962f681b12fc092816a62f27d86025599a41233848702f0cfc0437b445682df51147a632a0a083d2d38b5e13e466a8935afff58bb533b3ef5d27fba63ee6b0fd9e67ff20af9d50deee3f8bf065ec220c1fd4ba57e341261d55997f85d66d32152526736872693d2b437a233e2337b715f6ac9a6a272622fdc2d67fcfe1da3459f8dab4ed7e40a657a54c36766c5e8ac9a88b35b05c34747e6507f6b044ab66180dc76ac1a696de03189593fedc0d0dbbd855c8ead673544899b0960e4a5a7ca43b4ef90afe607de7698caefdc242788f654b57a4fb32a71b335ef6ff9a4cc118b282b53bdd6d6192b7a82c3c5126b9c7e33c8e5a5ac9738b8bd31247fb7402054f97b573e8abb9faad219f4fd085aceaa7f542d787ee4196d365f3cc566e7bbcfbfd451230c48d804c017d21e2d8fa914e2559bb72bf0ab78c8ab92f00ef0d0d576eccdd486b64138a4172674857e543d1d5b639058dd908186597e366ad5f3d9c7ceaff44d04d1550b8d33abc751df07437834ba5acb32328a396994aebb3c40f759c2d6d7a3cb5377e55d5d218ef5a296dda8ddc355f3f50c3d0b660a51dfa4d98a6a5a33564556cf83c1373a814641d6a1dcef97b883fee61bb84fe60a3409340217e629cc7e4dcc93b85d8820921ff5826148b60e6939acd7838e1d7f20562bff8ee4b5ec4a05ad997a57b9796fdcb2eda87883c2640b072b140b946bfdf6575cacc066fdae04f6951e63624cbd316a677cad529bbe4e97b9144e4bc06c4afd1de55dd3e1175f90423847a230d34dfb71ed56f2965a7f6c72e6aa33c24c303fd67745d632656c5ef90bec80f4f5d1daa251988826cef375c81c36bf457e09687056f924677cb0bccf98dff81e014ce25f2d132497923e267363963cdf4302c5049d63131dc03fd95f65d8b6aa5934f817252c028c90f56d413b9d5d10d89790707dae2fabb249f649929927c21dd71e3f656826de5451c5da375aadecbd59d5ebf3a31fae65ac1b316a1611f1b276b26530f58d7247df459ce1f86db1d734f6f811932f042cee45d0e455306d01081bc3384f82c5fb2aacaa19d89cdfa46cc916eac61121475ba2e6191b4feecbe1789717021a158ace5d06744b40f551076b67cd63af60007f8c99876e1424883a45ec49d497ddaf808a5521ca74a999ab0b3c7aa9c80f85e93977ec61ce68b20307a1a81f71ca645b568fcd319ccbb5f651e87b707d37c39e15f945ea69e2f7c7d2ccc85b7e654c07e96f0636ae4044fe0e38590b431795ad0f8647bdd613713ada493cc17efd313206380e6a685b8198475bbd021c6e9d94daab2214947127506073e44d5408ba166c512a0b86805d07f5a44d3c41706be2bc15e712e55805248b92e8677d90f6d284d1d6ffaff2c430657042a0e82624fa3717b06cc0a6fd12230ea586dae83019fb9e06034ed2803c98d554b93c9a52348cafff75c40174a91f9ae6b8647854a156029f0b88b83316663ce574a4978277bb6bb27a31085634b6ec78864b6d8201c7e93903d75815067e378289a3d072ae172dafa6a452470f8d645bebfad9779594fc0784bb764a22e3a8181d93db7bf97893c414217a618ccb14caa9e92e8c61673afc9583662e812adba1f87a9c68202d60e909efab43c42c0cb00695fc7f1ffe67c75ca894c3c51e1e5e731360199e600f6ced9a87b2a6a87e70bf251bb5075ab222138288164b2eda727515ea7de12e2496d4fe42ea8d1a120c03cf9c50622c2afe4acb0dad98fd62d07ab4e828a94495f6d1ab973982c7ccbe6c1fae02788e4422ae22282fa49cbdb04ba54a7a238c6fc41187451383460762c06d1c8a72b9cd718866ad4b689e10c9a8c38fe5ef045bd785b01e980fc82c7e3532ce81876b778dd9f1ceeba4478e86411fb6fdd790683916ca832592485093644e8760cd7b4c01dba1ccc82b661bf13f0e3f34acd6b88\";\n\n /// @notice Gets merkle root hash of drive with a replacement\n /// @param _position position of _drive\n /// @param _logSizeOfReplacement log2 of size the replacement\n /// @param _logSizeOfFullDrive log2 of size the full drive, which can be the entire machine\n /// @param _replacement hash of the replacement\n /// @param siblings of replacement that merkle root can be calculated\n function getRootAfterReplacementInDrive(\n uint256 _position,\n uint256 _logSizeOfReplacement,\n uint256 _logSizeOfFullDrive,\n bytes32 _replacement,\n bytes32[] calldata siblings\n ) public pure returns (bytes32) {\n require(\n _logSizeOfFullDrive >= _logSizeOfReplacement &&\n _logSizeOfReplacement >= 3 &&\n _logSizeOfFullDrive <= 64,\n \"3 <= logSizeOfReplacement <= logSizeOfFullDrive <= 64\"\n );\n\n uint256 size = 1 << _logSizeOfReplacement;\n\n require(((size - 1) & _position) == 0, \"Position is not aligned\");\n require(\n siblings.length == _logSizeOfFullDrive - _logSizeOfReplacement,\n \"Proof length does not match\"\n );\n\n for (uint256 i; i < siblings.length; i++) {\n if ((_position & (size << i)) == 0) {\n _replacement = keccak256(\n abi.encodePacked(_replacement, siblings[i])\n );\n } else {\n _replacement = keccak256(\n abi.encodePacked(siblings[i], _replacement)\n );\n }\n }\n\n return _replacement;\n }\n\n /// @notice Gets precomputed hash of zero in empty tree hashes\n /// @param _index of hash wanted\n /// @dev first index is keccak(0), second index is keccak(keccak(0), keccak(0))\n function getEmptyTreeHashAtIndex(uint256 _index)\n public\n pure\n returns (bytes32)\n {\n uint256 start = _index * 32;\n require(EMPTY_TREE_SIZE >= start + 32, \"index out of bounds\");\n bytes32 hashedZeros;\n bytes memory zeroTree = EMPTY_TREE_HASHES;\n\n // first word is length, then skip index words\n assembly {\n hashedZeros := mload(add(add(zeroTree, 0x20), start))\n }\n return hashedZeros;\n }\n\n /// @notice get merkle root of generic array of bytes\n /// @param _data array of bytes to be merklelized\n /// @param _log2Size log2 of total size of the drive\n /// @dev _data is padded with zeroes until is multiple of 8\n /// @dev root is completed with zero tree until log2size is complete\n /// @dev hashes are taken word by word (8 bytes by 8 bytes)\n function getMerkleRootFromBytes(bytes calldata _data, uint256 _log2Size)\n public\n pure\n returns (bytes32)\n {\n require(_log2Size >= 3 && _log2Size <= 64, \"range of log2Size: [3,64]\");\n\n // if _data is empty return pristine drive of size log2size\n if (_data.length == 0) return getEmptyTreeHashAtIndex(_log2Size - 3);\n\n // total size of the drive in words\n uint256 size = 1 << (_log2Size - 3);\n require(\n size << L_WORD_SIZE >= _data.length,\n \"data is bigger than drive\"\n );\n // the stack depth is log2(_data.length / 8) + 2\n uint256 stack_depth = 2 +\n ((_data.length) >> L_WORD_SIZE).getLog2Floor();\n bytes32[] memory stack = new bytes32[](stack_depth);\n\n uint256 numOfHashes; // total number of hashes on stack (counting levels)\n uint256 stackLength; // total length of stack\n uint256 numOfJoins; // number of hashes of the same level on stack\n uint256 topStackLevel; // hash level of the top of the stack\n\n while (numOfHashes < size) {\n if ((numOfHashes << L_WORD_SIZE) < _data.length) {\n // we still have words to hash\n stack[stackLength] = getHashOfWordAtIndex(_data, numOfHashes);\n numOfHashes++;\n\n numOfJoins = numOfHashes;\n } else {\n // since padding happens in hashOfWordAtIndex function\n // we only need to complete the stack with pre-computed\n // hash(0), hash(hash(0),hash(0)) and so on\n topStackLevel = numOfHashes.ctz();\n\n stack[stackLength] = getEmptyTreeHashAtIndex(topStackLevel);\n\n //Empty Tree Hash summarizes many hashes\n numOfHashes = numOfHashes + (1 << topStackLevel);\n numOfJoins = numOfHashes >> topStackLevel;\n }\n\n stackLength++;\n\n // while there are joins, hash top of stack together\n while (numOfJoins & 1 == 0) {\n bytes32 h2 = stack[stackLength - 1];\n bytes32 h1 = stack[stackLength - 2];\n\n stack[stackLength - 2] = keccak256(abi.encodePacked(h1, h2));\n stackLength = stackLength - 1; // remove hashes from stack\n\n numOfJoins = numOfJoins >> 1;\n }\n }\n require(stackLength == 1, \"stack error\");\n\n return stack[0];\n }\n\n /// @notice Get the hash of a word in an array of bytes\n /// @param _data array of bytes\n /// @param _wordIndex index of word inside the bytes to get the hash of\n /// @dev if word is incomplete (< 8 bytes) it gets padded with zeroes\n function getHashOfWordAtIndex(bytes calldata _data, uint256 _wordIndex)\n public\n pure\n returns (bytes32)\n {\n uint256 start = _wordIndex << L_WORD_SIZE;\n uint256 end = start + (1 << L_WORD_SIZE);\n\n // TODO: in .lua this just returns zero, but this might be more consistent\n require(start <= _data.length, \"word out of bounds\");\n\n if (end <= _data.length) {\n return keccak256(abi.encodePacked(_data[start:end]));\n }\n\n // word is incomplete\n // fill paddedSlice with incomplete words - the rest is going to be bytes(0)\n bytes memory paddedSlice = new bytes(8);\n uint256 remaining = _data.length - start;\n\n for (uint256 i; i < remaining; i++) {\n paddedSlice[i] = _data[start + i];\n }\n\n return keccak256(paddedSlice);\n }\n\n /// @notice Calculate the root of Merkle tree from an array of power of 2 elements\n /// @param hashes The array containing power of 2 elements\n /// @return byte32 the root hash being calculated\n function calculateRootFromPowerOfTwo(bytes32[] memory hashes)\n public\n pure\n returns (bytes32)\n {\n // revert when the input is not of power of 2\n require((hashes.length).isPowerOf2(), \"array len not power of 2\");\n\n if (hashes.length == 1) {\n return hashes[0];\n } else {\n bytes32[] memory newHashes = new bytes32[](hashes.length >> 1);\n\n for (uint256 i; i < hashes.length; i += 2) {\n newHashes[i >> 1] = keccak256(\n abi.encodePacked(hashes[i], hashes[i + 1])\n );\n }\n\n return calculateRootFromPowerOfTwo(newHashes);\n }\n }\n}\n" + }, + "contracts/interfaces/IOutput.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Output interface\npragma solidity >=0.7.0;\n\n/// @param epochIndex which epoch the output belongs to\n/// @param inputIndex which input, inside the epoch, the output belongs to\n/// @param outputIndex index of output inside the input\n/// @param outputHashesRootHash merkle root of all epoch's output metadata hashes\n/// @param vouchersEpochRootHash merkle root of all epoch's voucher metadata hashes\n/// @param noticesEpochRootHash merkle root of all epoch's notice metadata hashes\n/// @param machineStateHash hash of the machine state claimed this epoch\n/// @param keccakInHashesSiblings proof that this output metadata is in metadata memory range\n/// @param outputHashesInEpochSiblings proof that this output metadata is in epoch's output memory range\nstruct OutputValidityProof {\n uint256 epochIndex;\n uint256 inputIndex;\n uint256 outputIndex;\n bytes32 outputHashesRootHash;\n bytes32 vouchersEpochRootHash;\n bytes32 noticesEpochRootHash;\n bytes32 machineStateHash;\n bytes32[] keccakInHashesSiblings;\n bytes32[] outputHashesInEpochSiblings;\n}\n\ninterface IOutput {\n /// @notice executes voucher\n /// @param _destination address that will execute the payload\n /// @param _payload payload to be executed by destination\n /// @param _v validity proof for this encoded voucher\n /// @return true if voucher was executed successfully\n /// @dev vouchers can only be executed once\n function executeVoucher(\n address _destination,\n bytes calldata _payload,\n OutputValidityProof calldata _v\n ) external returns (bool);\n\n /// @notice get number of finalized epochs\n function getNumberOfFinalizedEpochs() external view returns (uint256);\n\n /// @notice get log2 size of voucher metadata memory range\n function getVoucherMetadataLog2Size() external pure returns (uint256);\n\n /// @notice get log2 size of epoch voucher memory range\n function getEpochVoucherLog2Size() external pure returns (uint256);\n\n /// @notice get log2 size of notice metadata memory range\n function getNoticeMetadataLog2Size() external pure returns (uint256);\n\n /// @notice get log2 size of epoch notice memory range\n function getEpochNoticeLog2Size() external pure returns (uint256);\n\n event VoucherExecuted(uint256 voucherPosition);\n}\n" + }, + "@cartesi/util/contracts/CartesiMath.sol": { + "content": "// Copyright 2020 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title CartesiMath\n/// @author Felipe Argento\npragma solidity ^0.8.0;\n\nlibrary CartesiMath {\n // mapping values are packed as bytes3 each\n // see test/TestCartesiMath.ts for decimal values\n bytes constant log2tableTimes1M =\n hex\"0000000F4240182F421E8480236E082771822AD63A2DC6C0305E8532B04834C96736B3C23876D73A187A3B9D4A3D09003E5EA63FA0C540D17741F28843057D440BA745062945F60246DC1047B917488DC7495ABA4A207C4ADF8A4B98544C4B404CF8AA4DA0E64E44434EE3054F7D6D5013B750A61A5134C851BFF05247BD52CC58534DE753CC8D54486954C19C55384255AC75561E50568DE956FB575766B057D00758376F589CFA5900BA5962BC59C3135A21CA5A7EF15ADA945B34BF5B8D805BE4DF5C3AEA5C8FA95CE3265D356C5D86835DD6735E25455E73005EBFAD5F0B525F55F75F9FA25FE85A60302460770860BD0A61023061467F6189FD61CCAE620E98624FBF62902762CFD5630ECD634D12638AA963C7966403DC643F7F647A8264B4E864EEB56527EC6560906598A365D029660724663D9766738566A8F066DDDA6712476746386779AF67ACAF67DF3A6811526842FA68743268A4FC68D55C6905536934E169640A6992CF69C13169EF326A1CD46A4A186A76FF6AA38C6ACFC0\";\n\n /// @notice Approximates log2 * 1M\n /// @param _num number to take log2 * 1M of\n /// @return approximate log2 times 1M\n function log2ApproxTimes1M(uint256 _num) public pure returns (uint256) {\n require(_num > 0, \"Number cannot be zero\");\n uint256 leading = 0;\n\n if (_num == 1) return 0;\n\n while (_num > 128) {\n _num = _num >> 1;\n leading += 1;\n }\n return (leading * uint256(1000000)) + (getLog2TableTimes1M(_num));\n }\n\n /// @notice navigates log2tableTimes1M\n /// @param _num number to take log2 of\n /// @return result after table look-up\n function getLog2TableTimes1M(uint256 _num) public pure returns (uint256) {\n bytes3 result = 0;\n for (uint8 i = 0; i < 3; i++) {\n bytes3 tempResult = log2tableTimes1M[(_num - 1) * 3 + i];\n result = result | (tempResult >> (i * 8));\n }\n\n return uint256(uint24(result));\n }\n\n /// @notice get floor of log2 of number\n /// @param _num number to take floor(log2) of\n /// @return floor(log2) of _num\n function getLog2Floor(uint256 _num) public pure returns (uint8) {\n require(_num != 0, \"log of zero is undefined\");\n\n return uint8(255 - clz(_num));\n }\n\n /// @notice checks if a number is Power of 2\n /// @param _num number to check\n /// @return true if number is power of 2, false if not\n function isPowerOf2(uint256 _num) public pure returns (bool) {\n if (_num == 0) return false;\n\n return _num & (_num - 1) == 0;\n }\n\n /// @notice count trailing zeros\n /// @param _num number you want the ctz of\n /// @dev this a binary search implementation\n function ctz(uint256 _num) public pure returns (uint256) {\n if (_num == 0) return 256;\n\n uint256 n = 0;\n if (_num & 0x00000000000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF == 0) { n = n + 128; _num = _num >> 128; }\n if (_num & 0x000000000000000000000000000000000000000000000000FFFFFFFFFFFFFFFF == 0) { n = n + 64; _num = _num >> 64; }\n if (_num & 0x00000000000000000000000000000000000000000000000000000000FFFFFFFF == 0) { n = n + 32; _num = _num >> 32; }\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000FFFF == 0) { n = n + 16; _num = _num >> 16; }\n if (_num & 0x00000000000000000000000000000000000000000000000000000000000000FF == 0) { n = n + 8; _num = _num >> 8; }\n if (_num & 0x000000000000000000000000000000000000000000000000000000000000000F == 0) { n = n + 4; _num = _num >> 4; }\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000003 == 0) { n = n + 2; _num = _num >> 2; }\n if (_num & 0x0000000000000000000000000000000000000000000000000000000000000001 == 0) { n = n + 1; }\n\n return n;\n }\n\n /// @notice count leading zeros\n /// @param _num number you want the clz of\n /// @dev this a binary search implementation\n function clz(uint256 _num) public pure returns (uint256) {\n if (_num == 0) return 256;\n\n uint256 n = 0;\n if (_num & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000000000000000000000000000 == 0) { n = n + 128; _num = _num << 128; }\n if (_num & 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000 == 0) { n = n + 64; _num = _num << 64; }\n if (_num & 0xFFFFFFFF00000000000000000000000000000000000000000000000000000000 == 0) { n = n + 32; _num = _num << 32; }\n if (_num & 0xFFFF000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 16; _num = _num << 16; }\n if (_num & 0xFF00000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 8; _num = _num << 8; }\n if (_num & 0xF000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 4; _num = _num << 4; }\n if (_num & 0xC000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 2; _num = _num << 2; }\n if (_num & 0x8000000000000000000000000000000000000000000000000000000000000000 == 0) { n = n + 1; }\n\n return n;\n }\n}\n" + }, + "contracts/libraries/alternatives/LibValidatorManager1.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Validator Manager library (alternative version)\npragma solidity ^0.8.0;\n\nimport {Result} from \"../../interfaces/IValidatorManager.sol\";\n\n// TODO: this libray seems to be very unsafe, need to think about security implications\nlibrary LibValidatorManager1 {\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"ValidatorManager.diamond.storage\");\n\n struct DiamondStorage {\n bytes32 currentClaim; // current claim - first claim of this epoch\n address payable[] validators; // current validators\n // A bit set for each validator that agrees with current claim,\n // on their respective positions\n uint32 claimAgreementMask;\n // Every validator who should approve (in order to reach consensus) will have a one set on this mask\n // This mask is updated if a validator is added or removed\n uint32 consensusGoalMask;\n }\n\n /// @notice emitted on Claim received\n event ClaimReceived(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on Dispute end\n event DisputeEnded(\n Result result,\n bytes32[2] claims,\n address payable[2] validators\n );\n\n /// @notice emitted on new Epoch\n event NewEpoch(bytes32 claim);\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n /// @notice called when a dispute ends in rollups\n /// @param ds diamond storage pointer\n /// @param winner address of dispute winner\n /// @param loser address of dispute loser\n /// @param winningClaim the winning claim\n /// @return result of dispute being finished\n function onDisputeEnd(\n DiamondStorage storage ds,\n address payable winner,\n address payable loser,\n bytes32 winningClaim\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n // remove validator also removes validator from both bitmask\n removeFromValidatorSetAndBothBitmasks(ds, loser);\n\n if (winningClaim == ds.currentClaim) {\n // first claim stood, dont need to update the bitmask\n return\n isConsensus(ds.claimAgreementMask, ds.consensusGoalMask)\n ? emitDisputeEndedAndReturn(\n Result.Consensus,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n )\n : emitDisputeEndedAndReturn(\n Result.NoConflict,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n );\n }\n\n // if first claim lost, and other validators have agreed with it\n // there is a new dispute to be played\n if (ds.claimAgreementMask != 0) {\n return\n emitDisputeEndedAndReturn(\n Result.Conflict,\n [ds.currentClaim, winningClaim],\n [getClaimerOfCurrentClaim(ds), winner]\n );\n }\n // else there are no valdiators that agree with losing claim\n // we can update current claim and check for consensus in case\n // the winner is the only validator left\n ds.currentClaim = winningClaim;\n ds.claimAgreementMask = updateClaimAgreementMask(ds, winner);\n return\n isConsensus(ds.claimAgreementMask, ds.consensusGoalMask)\n ? emitDisputeEndedAndReturn(\n Result.Consensus,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n )\n : emitDisputeEndedAndReturn(\n Result.NoConflict,\n [winningClaim, bytes32(0)],\n [winner, payable(0)]\n );\n }\n\n /// @notice called when a new epoch starts\n /// @param ds diamond storage pointer\n /// @return current claim\n function onNewEpoch(DiamondStorage storage ds) internal returns (bytes32) {\n bytes32 tmpClaim = ds.currentClaim;\n\n // clear current claim\n ds.currentClaim = bytes32(0);\n // clear validator agreement bit mask\n ds.claimAgreementMask = 0;\n\n emit NewEpoch(tmpClaim);\n return tmpClaim;\n }\n\n /// @notice called when a claim is received by rollups\n /// @param ds diamond storage pointer\n /// @param sender address of sender of that claim\n /// @param claim claim received by rollups\n /// @return result of claim, Consensus | NoConflict | Conflict\n /// @return [currentClaim, conflicting claim] if there is Conflict\n /// [currentClaim, bytes32(0)] if there is Consensus or NoConflcit\n /// @return [claimer1, claimer2] if there is Conflcit\n /// [claimer1, address(0)] if there is Consensus or NoConflcit\n function onClaim(\n DiamondStorage storage ds,\n address payable sender,\n bytes32 claim\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n require(claim != bytes32(0), \"empty claim\");\n require(isValidator(ds, sender), \"sender not allowed\");\n\n // cant return because a single claim might mean consensus\n if (ds.currentClaim == bytes32(0)) {\n ds.currentClaim = claim;\n }\n\n if (claim != ds.currentClaim) {\n return\n emitClaimReceivedAndReturn(\n Result.Conflict,\n [ds.currentClaim, claim],\n [getClaimerOfCurrentClaim(ds), sender]\n );\n }\n ds.claimAgreementMask = updateClaimAgreementMask(ds, sender);\n\n return\n isConsensus(ds.claimAgreementMask, ds.consensusGoalMask)\n ? emitClaimReceivedAndReturn(\n Result.Consensus,\n [claim, bytes32(0)],\n [sender, payable(0)]\n )\n : emitClaimReceivedAndReturn(\n Result.NoConflict,\n [claim, bytes32(0)],\n [sender, payable(0)]\n );\n }\n\n /// @notice emits dispute ended event and then return\n /// @param result to be emitted and returned\n /// @param claims to be emitted and returned\n /// @param validators to be emitted and returned\n /// @dev this function existis to make code more clear/concise\n function emitDisputeEndedAndReturn(\n Result result,\n bytes32[2] memory claims,\n address payable[2] memory validators\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n emit DisputeEnded(result, claims, validators);\n return (result, claims, validators);\n }\n\n /// @notice emits claim received event and then return\n /// @param result to be emitted and returned\n /// @param claims to be emitted and returned\n /// @param validators to be emitted and returned\n /// @dev this function existis to make code more clear/concise\n function emitClaimReceivedAndReturn(\n Result result,\n bytes32[2] memory claims,\n address payable[2] memory validators\n )\n internal\n returns (\n Result,\n bytes32[2] memory,\n address payable[2] memory\n )\n {\n emit ClaimReceived(result, claims, validators);\n return (result, claims, validators);\n }\n\n /// @notice get one of the validators that agreed with current claim\n /// @param ds diamond storage pointer\n /// @return validator that agreed with current claim\n function getClaimerOfCurrentClaim(DiamondStorage storage ds)\n internal\n view\n returns (address payable)\n {\n // TODO: we are always getting the first validator\n // on the array that agrees with the current claim to enter a dispute\n // should this be random?\n for (uint256 i; i < ds.validators.length; i++) {\n if (ds.claimAgreementMask & (1 << i) != 0) {\n return ds.validators[i];\n }\n }\n revert(\"Agreeing validator not found\");\n }\n\n /// @notice updates the consensus goal mask\n /// @param ds diamond storage pointer\n /// @return new consensus goal mask\n function updateConsensusGoalMask(DiamondStorage storage ds)\n internal\n view\n returns (uint32)\n {\n // consensus goal is a number where\n // all bits related to validators are turned on\n uint256 consensusMask = (1 << ds.validators.length) - 1;\n return uint32(consensusMask);\n }\n\n /// @notice updates mask of validators that agreed with current claim\n /// @param ds diamond storage pointer\n /// @param sender address that of validator that will be included in mask\n /// @return new claim agreement mask\n function updateClaimAgreementMask(\n DiamondStorage storage ds,\n address payable sender\n ) internal view returns (uint32) {\n uint256 tmpClaimAgreement = ds.claimAgreementMask;\n for (uint256 i; i < ds.validators.length; i++) {\n if (sender == ds.validators[i]) {\n tmpClaimAgreement = (tmpClaimAgreement | (1 << i));\n break;\n }\n }\n\n return uint32(tmpClaimAgreement);\n }\n\n /// @notice removes a validator\n /// @param ds diamond storage pointer\n /// @param validator address of validator to be removed\n function removeFromValidatorSetAndBothBitmasks(\n DiamondStorage storage ds,\n address validator\n ) internal {\n // put address(0) in validators position\n // removes validator from claim agreement bitmask\n // removes validator from consensus goal mask\n for (uint256 i; i < ds.validators.length; i++) {\n if (validator == ds.validators[i]) {\n ds.validators[i] = payable(0);\n uint32 zeroMask = ~(uint32(1) << uint32(i));\n ds.claimAgreementMask = ds.claimAgreementMask & zeroMask;\n ds.consensusGoalMask = ds.consensusGoalMask & zeroMask;\n break;\n }\n }\n }\n\n function isValidator(DiamondStorage storage ds, address sender)\n internal\n view\n returns (bool)\n {\n for (uint256 i; i < ds.validators.length; i++) {\n if (sender == ds.validators[i]) return true;\n }\n\n return false;\n }\n\n function isConsensus(uint256 claimAgreementMask, uint256 consensusGoalMask)\n internal\n pure\n returns (bool)\n {\n return claimAgreementMask == consensusGoalMask;\n }\n}\n" + }, + "contracts/facets/alternatives/ValidatorManagerFacet1.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Validator Manager facet (alternative version)\npragma solidity ^0.8.0;\n\nimport {IValidatorManager} from \"../../interfaces/IValidatorManager.sol\";\n\nimport {LibValidatorManager1} from \"../../libraries/alternatives/LibValidatorManager1.sol\";\n\ncontract ValidatorManagerFacet1 is IValidatorManager {\n /// @notice get agreement mask\n /// @return current state of agreement mask\n function getCurrentAgreementMask() public view returns (uint32) {\n LibValidatorManager1.DiamondStorage\n storage validatorManagerDS = LibValidatorManager1.diamondStorage();\n return validatorManagerDS.claimAgreementMask;\n }\n\n /// @notice get consensus goal mask\n /// @return current consensus goal mask\n function getConsensusGoalMask() public view returns (uint32) {\n LibValidatorManager1.DiamondStorage\n storage validatorManagerDS = LibValidatorManager1.diamondStorage();\n return validatorManagerDS.consensusGoalMask;\n }\n\n /// @notice get current claim\n /// @return current claim\n function getCurrentClaim() public view override returns (bytes32) {\n LibValidatorManager1.DiamondStorage\n storage validatorManagerDS = LibValidatorManager1.diamondStorage();\n return validatorManagerDS.currentClaim;\n }\n}\n" + }, + "contracts/upgrade_initializers/DiamondInit.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n// @title Diamond Initialization Contract\npragma solidity ^0.8.0;\n\n// Rollups-related dependencies\nimport {Phase} from \"../interfaces/IRollups.sol\";\nimport {LibRollups} from \"../libraries/LibRollups.sol\";\nimport {LibInput} from \"../libraries/LibInput.sol\";\nimport {LibValidatorManager} from \"../libraries/LibValidatorManager.sol\";\nimport {LibClaimsMask} from \"../libraries/LibClaimsMask.sol\";\nimport {LibFeeManager} from \"../libraries/LibFeeManager.sol\";\nimport {IBank} from \"../IBank.sol\";\n\n// Diamond-related dependencies\nimport {LibDiamond} from \"../libraries/LibDiamond.sol\";\nimport {IDiamondLoupe} from \"../interfaces/IDiamondLoupe.sol\";\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\nimport {IERC173} from \"../interfaces/IERC173.sol\"; // not in openzeppelin-contracts yet\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\n/// @notice diamond configurations\n/// @param templateHash state hash of the cartesi machine at t0\n/// @param inputDuration duration of input accumulation phase in seconds\n/// @param challengePeriod duration of challenge period in seconds\n/// @param inputLog2Size size of the input memory range in this machine\n/// @param feePerClaim fee per claim to reward the validators\n/// @param feeManagerBank fee manager bank address\n/// @param feeManagerOwner fee manager owner address\n/// @param validators initial validator set\n/// @dev validators have to be unique, if the same validator is added twice\n/// consensus will never be reached\nstruct DiamondConfig {\n // RollupsFacet\n bytes32 templateHash;\n uint256 inputDuration;\n uint256 challengePeriod;\n // InputFacet\n uint256 inputLog2Size;\n // FeeManagerFacet\n uint256 feePerClaim;\n address feeManagerBank;\n address feeManagerOwner;\n // ValidatorManagerFacet\n address payable[] validators;\n}\n\ncontract DiamondInit {\n using LibValidatorManager for LibValidatorManager.DiamondStorage;\n using LibInput for LibInput.DiamondStorage;\n\n /// @notice initialize the diamond\n /// @param _dConfig diamond configurations\n function init(DiamondConfig calldata _dConfig) external {\n initERC165();\n initValidatorManager(_dConfig.validators);\n initRollups(\n _dConfig.templateHash,\n _dConfig.inputDuration,\n _dConfig.challengePeriod\n );\n initFeeManager(\n _dConfig.feePerClaim,\n _dConfig.feeManagerBank,\n _dConfig.feeManagerOwner\n );\n initInput(_dConfig.inputLog2Size);\n }\n\n /// @notice initialize ERC165 data\n function initERC165() private {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n ds.supportedInterfaces[type(IERC165).interfaceId] = true;\n ds.supportedInterfaces[type(IDiamondCut).interfaceId] = true;\n ds.supportedInterfaces[type(IDiamondLoupe).interfaceId] = true;\n ds.supportedInterfaces[type(IERC173).interfaceId] = true;\n }\n\n /// @notice initalize the Input facet\n /// @param _inputLog2Size size of the input memory range in this machine\n function initInput(uint256 _inputLog2Size) private {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n\n require(\n _inputLog2Size >= 3 && _inputLog2Size <= 64,\n \"Log of input size: [3,64]\"\n );\n\n inputDS.inputDriveSize = (1 << _inputLog2Size);\n\n // input box gets initialized with one empty input\n // so that the L2 DApp knows it's own address\n inputDS.addInternalInput(\"\");\n }\n\n /// @notice initialize the Validator Manager facet\n /// @param _validators initial validator set\n function initValidatorManager(address payable[] memory _validators)\n private\n {\n LibValidatorManager.DiamondStorage\n storage validatorManagerDS = LibValidatorManager.diamondStorage();\n\n uint256 maxNumValidators = _validators.length;\n\n require(maxNumValidators <= 8, \"up to 8 validators\");\n\n validatorManagerDS.validators = _validators;\n validatorManagerDS.maxNumValidators = maxNumValidators;\n\n // create a new ClaimsMask, with only the consensus goal set,\n // according to the number of validators\n validatorManagerDS.claimsMask = LibClaimsMask\n .newClaimsMaskWithConsensusGoalSet(maxNumValidators);\n }\n\n /// @notice rollups contract initialized\n /// @param inputDuration duration of input accumulation phase in seconds\n /// @param challengePeriod duration of challenge period in seconds\n event RollupsInitialized(uint256 inputDuration, uint256 challengePeriod);\n\n /// @notice initialize the Rollups facet\n /// @param _templateHash state hash of the cartesi machine at t0\n /// @param _inputDuration duration of input accumulation phase in seconds\n /// @param _challengePeriod duration of challenge period in seconds\n function initRollups(\n bytes32 _templateHash,\n uint256 _inputDuration,\n uint256 _challengePeriod\n ) private {\n LibRollups.DiamondStorage storage rollupsDS = LibRollups\n .diamondStorage();\n\n rollupsDS.templateHash = _templateHash;\n rollupsDS.inputDuration = uint32(_inputDuration);\n rollupsDS.challengePeriod = uint32(_challengePeriod);\n rollupsDS.inputAccumulationStart = uint32(block.timestamp);\n rollupsDS.currentPhase_int = uint32(Phase.InputAccumulation);\n\n emit RollupsInitialized(_inputDuration, _challengePeriod);\n }\n\n /// @notice FeeManagerImpl contract initialized\n /// @param feePerClaim fee per claim to reward the validators\n /// @param feeManagerBank fee manager bank address\n /// @param feeManagerOwner fee manager owner address\n event FeeManagerInitialized(\n uint256 feePerClaim,\n address feeManagerBank,\n address feeManagerOwner\n );\n\n /// @notice initalize the Fee Manager facet\n /// @param _feePerClaim fee per claim to reward the validators\n /// @param _feeManagerBank fee manager bank address\n /// @param _feeManagerOwner fee manager owner address\n function initFeeManager(\n uint256 _feePerClaim,\n address _feeManagerBank,\n address _feeManagerOwner\n ) private {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n\n feeManagerDS.feePerClaim = _feePerClaim;\n feeManagerDS.bank = IBank(_feeManagerBank);\n feeManagerDS.owner = _feeManagerOwner;\n\n emit FeeManagerInitialized(\n _feePerClaim,\n _feeManagerBank,\n _feeManagerOwner\n );\n }\n}\n" + }, + "contracts/libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\n\nlibrary LibDiamond {\n bytes32 constant DIAMOND_STORAGE_POSITION =\n keccak256(\"diamond.standard.diamond.storage\");\n\n struct DiamondStorage {\n // maps function selectors to the facets that execute the functions.\n // and maps the selectors to their position in the selectorSlots array.\n // func selector => address facet, selector position\n mapping(bytes4 => bytes32) facets;\n // array of slots of function selectors.\n // each slot holds 8 function selectors.\n mapping(uint256 => bytes32) selectorSlots;\n // The number of function selectors in selectorSlots\n uint16 selectorCount;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage()\n internal\n pure\n returns (DiamondStorage storage ds)\n {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n require(\n msg.sender == diamondStorage().contractOwner,\n \"LibDiamond: Must be contract owner\"\n );\n }\n\n event DiamondCut(\n IDiamondCut.FacetCut[] diamondCut,\n address init,\n bytes callData\n );\n\n bytes32 constant CLEAR_ADDRESS_MASK =\n bytes32(uint256(0xffffffffffffffffffffffff));\n bytes32 constant CLEAR_SELECTOR_MASK = bytes32(uint256(0xffffffff << 224));\n\n // Internal function version of diamondCut\n // This code is almost the same as the external diamondCut,\n // except it is using 'Facet[] memory _diamondCut' instead of\n // 'Facet[] calldata _diamondCut'.\n // The code is duplicated to prevent copying calldata to memory which\n // causes an error for a two dimensional array.\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n DiamondStorage storage ds = diamondStorage();\n uint256 originalSelectorCount = ds.selectorCount;\n uint256 selectorCount = originalSelectorCount;\n bytes32 selectorSlot;\n // Check if last selector slot is not full\n // \"selectorCount & 7\" is a gas efficient modulo by eight \"selectorCount % 8\"\n if (selectorCount & 7 > 0) {\n // get last selectorSlot\n // \"selectorSlot >> 3\" is a gas efficient division by 8 \"selectorSlot / 8\"\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\n }\n // loop through diamond cut\n for (\n uint256 facetIndex;\n facetIndex < _diamondCut.length;\n facetIndex++\n ) {\n (selectorCount, selectorSlot) = addReplaceRemoveFacetSelectors(\n selectorCount,\n selectorSlot,\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].action,\n _diamondCut[facetIndex].functionSelectors\n );\n }\n if (selectorCount != originalSelectorCount) {\n ds.selectorCount = uint16(selectorCount);\n }\n // If last selector slot is not full\n // \"selectorCount & 7\" is a gas efficient modulo by eight \"selectorCount % 8\"\n if (selectorCount & 7 > 0) {\n // \"selectorSlot >> 3\" is a gas efficient division by 8 \"selectorSlot / 8\"\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addReplaceRemoveFacetSelectors(\n uint256 _selectorCount,\n bytes32 _selectorSlot,\n address _newFacetAddress,\n IDiamondCut.FacetCutAction _action,\n bytes4[] memory _selectors\n ) internal returns (uint256, bytes32) {\n DiamondStorage storage ds = diamondStorage();\n require(\n _selectors.length > 0,\n \"LibDiamondCut: No selectors in facet to cut\"\n );\n if (_action == IDiamondCut.FacetCutAction.Add) {\n enforceHasContractCode(\n _newFacetAddress,\n \"LibDiamondCut: Add facet has no code\"\n );\n for (\n uint256 selectorIndex;\n selectorIndex < _selectors.length;\n selectorIndex++\n ) {\n bytes4 selector = _selectors[selectorIndex];\n bytes32 oldFacet = ds.facets[selector];\n require(\n address(bytes20(oldFacet)) == address(0),\n \"LibDiamondCut: Can't add function that already exists\"\n );\n // add facet for selector\n ds.facets[selector] =\n bytes20(_newFacetAddress) |\n bytes32(_selectorCount);\n // \"_selectorCount & 7\" is a gas efficient modulo by eight \"_selectorCount % 8\"\n uint256 selectorInSlotPosition = (_selectorCount & 7) << 5;\n // clear selector position in slot and add selector\n _selectorSlot =\n (_selectorSlot &\n ~(CLEAR_SELECTOR_MASK >> selectorInSlotPosition)) |\n (bytes32(selector) >> selectorInSlotPosition);\n // if slot is full then write it to storage\n if (selectorInSlotPosition == 224) {\n // \"_selectorSlot >> 3\" is a gas efficient division by 8 \"_selectorSlot / 8\"\n ds.selectorSlots[_selectorCount >> 3] = _selectorSlot;\n _selectorSlot = 0;\n }\n _selectorCount++;\n }\n } else if (_action == IDiamondCut.FacetCutAction.Replace) {\n enforceHasContractCode(\n _newFacetAddress,\n \"LibDiamondCut: Replace facet has no code\"\n );\n for (\n uint256 selectorIndex;\n selectorIndex < _selectors.length;\n selectorIndex++\n ) {\n bytes4 selector = _selectors[selectorIndex];\n bytes32 oldFacet = ds.facets[selector];\n address oldFacetAddress = address(bytes20(oldFacet));\n // only useful if immutable functions exist\n require(\n oldFacetAddress != address(this),\n \"LibDiamondCut: Can't replace immutable function\"\n );\n require(\n oldFacetAddress != _newFacetAddress,\n \"LibDiamondCut: Can't replace function with same function\"\n );\n require(\n oldFacetAddress != address(0),\n \"LibDiamondCut: Can't replace function that doesn't exist\"\n );\n // replace old facet address\n ds.facets[selector] =\n (oldFacet & CLEAR_ADDRESS_MASK) |\n bytes20(_newFacetAddress);\n }\n } else if (_action == IDiamondCut.FacetCutAction.Remove) {\n require(\n _newFacetAddress == address(0),\n \"LibDiamondCut: Remove facet address must be address(0)\"\n );\n // \"_selectorCount >> 3\" is a gas efficient division by 8 \"_selectorCount / 8\"\n uint256 selectorSlotCount = _selectorCount >> 3;\n // \"_selectorCount & 7\" is a gas efficient modulo by eight \"_selectorCount % 8\"\n uint256 selectorInSlotIndex = _selectorCount & 7;\n for (\n uint256 selectorIndex;\n selectorIndex < _selectors.length;\n selectorIndex++\n ) {\n if (_selectorSlot == 0) {\n // get last selectorSlot\n selectorSlotCount--;\n _selectorSlot = ds.selectorSlots[selectorSlotCount];\n selectorInSlotIndex = 7;\n } else {\n selectorInSlotIndex--;\n }\n bytes4 lastSelector;\n uint256 oldSelectorsSlotCount;\n uint256 oldSelectorInSlotPosition;\n // adding a block here prevents stack too deep error\n {\n bytes4 selector = _selectors[selectorIndex];\n bytes32 oldFacet = ds.facets[selector];\n require(\n address(bytes20(oldFacet)) != address(0),\n \"LibDiamondCut: Can't remove function that doesn't exist\"\n );\n // only useful if immutable functions exist\n require(\n address(bytes20(oldFacet)) != address(this),\n \"LibDiamondCut: Can't remove immutable function\"\n );\n // replace selector with last selector in ds.facets\n // gets the last selector\n lastSelector = bytes4(\n _selectorSlot << (selectorInSlotIndex << 5)\n );\n if (lastSelector != selector) {\n // update last selector slot position info\n ds.facets[lastSelector] =\n (oldFacet & CLEAR_ADDRESS_MASK) |\n bytes20(ds.facets[lastSelector]);\n }\n delete ds.facets[selector];\n uint256 oldSelectorCount = uint16(uint256(oldFacet));\n // \"oldSelectorCount >> 3\" is a gas efficient division by 8 \"oldSelectorCount / 8\"\n oldSelectorsSlotCount = oldSelectorCount >> 3;\n // \"oldSelectorCount & 7\" is a gas efficient modulo by eight \"oldSelectorCount % 8\"\n oldSelectorInSlotPosition = (oldSelectorCount & 7) << 5;\n }\n if (oldSelectorsSlotCount != selectorSlotCount) {\n bytes32 oldSelectorSlot = ds.selectorSlots[\n oldSelectorsSlotCount\n ];\n // clears the selector we are deleting and puts the last selector in its place.\n oldSelectorSlot =\n (oldSelectorSlot &\n ~(CLEAR_SELECTOR_MASK >>\n oldSelectorInSlotPosition)) |\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\n // update storage with the modified slot\n ds.selectorSlots[oldSelectorsSlotCount] = oldSelectorSlot;\n } else {\n // clears the selector we are deleting and puts the last selector in its place.\n _selectorSlot =\n (_selectorSlot &\n ~(CLEAR_SELECTOR_MASK >>\n oldSelectorInSlotPosition)) |\n (bytes32(lastSelector) >> oldSelectorInSlotPosition);\n }\n if (selectorInSlotIndex == 0) {\n delete ds.selectorSlots[selectorSlotCount];\n _selectorSlot = 0;\n }\n }\n _selectorCount = selectorSlotCount * 8 + selectorInSlotIndex;\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n return (_selectorCount, _selectorSlot);\n }\n\n function initializeDiamondCut(address _init, bytes memory _calldata)\n internal\n {\n if (_init == address(0)) {\n require(\n _calldata.length == 0,\n \"LibDiamondCut: _init is address(0) but_calldata is not empty\"\n );\n } else {\n require(\n _calldata.length > 0,\n \"LibDiamondCut: _calldata is empty but _init is not address(0)\"\n );\n if (_init != address(this)) {\n enforceHasContractCode(\n _init,\n \"LibDiamondCut: _init address has no code\"\n );\n }\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert(\"LibDiamondCut: _init function reverted\");\n }\n }\n }\n }\n\n function enforceHasContractCode(\n address _contract,\n string memory _errorMessage\n ) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize > 0, _errorMessage);\n }\n}\n" + }, + "contracts/interfaces/IDiamondLoupe.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\n// A loupe is a small magnifying glass used to look at diamonds.\n// These functions look at diamonds\ninterface IDiamondLoupe {\n /// These functions are expected to be called frequently\n /// by tools.\n\n struct Facet {\n address facetAddress;\n bytes4[] functionSelectors;\n }\n\n /// @notice Gets all facet addresses and their four byte function selectors.\n /// @return facets_ Facet\n function facets() external view returns (Facet[] memory facets_);\n\n /// @notice Gets all the function selectors supported by a specific facet.\n /// @param _facet The facet address.\n /// @return facetFunctionSelectors_\n function facetFunctionSelectors(address _facet)\n external\n view\n returns (bytes4[] memory facetFunctionSelectors_);\n\n /// @notice Get all the facet addresses used by a diamond.\n /// @return facetAddresses_\n function facetAddresses()\n external\n view\n returns (address[] memory facetAddresses_);\n\n /// @notice Gets the facet that supports the given selector.\n /// @dev If facet is not found return address(0).\n /// @param _functionSelector The function selector.\n /// @return facetAddress_ The facet address.\n function facetAddress(bytes4 _functionSelector)\n external\n view\n returns (address facetAddress_);\n}\n" + }, + "contracts/interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\ninterface IDiamondCut {\n enum FacetCutAction {\n Add,\n Replace,\n Remove\n }\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] diamondCut, address init, bytes callData);\n}\n" + }, + "contracts/interfaces/IERC173.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/// @title ERC-173 Contract Ownership Standard\n/// Note: the ERC-165 identifier for this interface is 0x7f5828d0\n/* is ERC165 */\ninterface IERC173 {\n /// @dev This emits when ownership of a contract changes.\n event OwnershipTransferred(\n address indexed previousOwner,\n address indexed newOwner\n );\n\n /// @notice Get the address of the owner\n /// @return owner_ The address of the owner.\n function owner() external view returns (address owner_);\n\n /// @notice Set the address of the new owner of the contract\n /// @dev Set _newOwner to address(0) to renounce any ownership.\n /// @param _newOwner The address of the new owner of the contract\n function transferOwnership(address _newOwner) external;\n}\n" + }, + "contracts/facets/OwnershipFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\nimport {LibDiamond} from \"../libraries/LibDiamond.sol\";\nimport {IERC173} from \"../interfaces/IERC173.sol\";\n\ncontract OwnershipFacet is IERC173 {\n function transferOwnership(address _newOwner) external override {\n LibDiamond.enforceIsContractOwner();\n LibDiamond.setContractOwner(_newOwner);\n }\n\n function owner() external view override returns (address owner_) {\n owner_ = LibDiamond.contractOwner();\n }\n}\n" + }, + "contracts/facets/DiamondLoupeFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\nimport {LibDiamond} from \"../libraries/LibDiamond.sol\";\nimport {IDiamondLoupe} from \"../interfaces/IDiamondLoupe.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\n\ncontract DiamondLoupeFacet is IDiamondLoupe, IERC165 {\n // Diamond Loupe Functions\n ////////////////////////////////////////////////////////////////////\n /// These functions are expected to be called frequently by tools.\n //\n // struct Facet {\n // address facetAddress;\n // bytes4[] functionSelectors;\n // }\n\n /// @notice Gets all facets and their selectors.\n /// @return facets_ Facet\n function facets() external view override returns (Facet[] memory facets_) {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n facets_ = new Facet[](ds.selectorCount);\n uint8[] memory numFacetSelectors = new uint8[](ds.selectorCount);\n uint256 numFacets;\n uint256 selectorIndex;\n // loop through function selectors\n for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) {\n bytes32 slot = ds.selectorSlots[slotIndex];\n for (\n uint256 selectorSlotIndex;\n selectorSlotIndex < 8;\n selectorSlotIndex++\n ) {\n selectorIndex++;\n if (selectorIndex > ds.selectorCount) {\n break;\n }\n bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));\n address facetAddress_ = address(bytes20(ds.facets[selector]));\n bool continueLoop;\n for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {\n if (facets_[facetIndex].facetAddress == facetAddress_) {\n facets_[facetIndex].functionSelectors[\n numFacetSelectors[facetIndex]\n ] = selector;\n // probably will never have more than 256 functions from one facet contract\n require(numFacetSelectors[facetIndex] < 255);\n numFacetSelectors[facetIndex]++;\n continueLoop = true;\n break;\n }\n }\n if (continueLoop) {\n continue;\n }\n facets_[numFacets].facetAddress = facetAddress_;\n facets_[numFacets].functionSelectors = new bytes4[](\n ds.selectorCount\n );\n facets_[numFacets].functionSelectors[0] = selector;\n numFacetSelectors[numFacets] = 1;\n numFacets++;\n }\n }\n for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {\n uint256 numSelectors = numFacetSelectors[facetIndex];\n bytes4[] memory selectors = facets_[facetIndex].functionSelectors;\n // setting the number of selectors\n assembly {\n mstore(selectors, numSelectors)\n }\n }\n // setting the number of facets\n assembly {\n mstore(facets_, numFacets)\n }\n }\n\n /// @notice Gets all the function selectors supported by a specific facet.\n /// @param _facet The facet address.\n /// @return facetFunctionSelectors_ The selectors associated with a facet address.\n function facetFunctionSelectors(address _facet)\n external\n view\n override\n returns (bytes4[] memory facetFunctionSelectors_)\n {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n uint256 numSelectors;\n facetFunctionSelectors_ = new bytes4[](ds.selectorCount);\n uint256 selectorIndex;\n // loop through function selectors\n for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) {\n bytes32 slot = ds.selectorSlots[slotIndex];\n for (\n uint256 selectorSlotIndex;\n selectorSlotIndex < 8;\n selectorSlotIndex++\n ) {\n selectorIndex++;\n if (selectorIndex > ds.selectorCount) {\n break;\n }\n bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));\n address facet = address(bytes20(ds.facets[selector]));\n if (_facet == facet) {\n facetFunctionSelectors_[numSelectors] = selector;\n numSelectors++;\n }\n }\n }\n // Set the number of selectors in the array\n assembly {\n mstore(facetFunctionSelectors_, numSelectors)\n }\n }\n\n /// @notice Get all the facet addresses used by a diamond.\n /// @return facetAddresses_\n function facetAddresses()\n external\n view\n override\n returns (address[] memory facetAddresses_)\n {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n facetAddresses_ = new address[](ds.selectorCount);\n uint256 numFacets;\n uint256 selectorIndex;\n // loop through function selectors\n for (uint256 slotIndex; selectorIndex < ds.selectorCount; slotIndex++) {\n bytes32 slot = ds.selectorSlots[slotIndex];\n for (\n uint256 selectorSlotIndex;\n selectorSlotIndex < 8;\n selectorSlotIndex++\n ) {\n selectorIndex++;\n if (selectorIndex > ds.selectorCount) {\n break;\n }\n bytes4 selector = bytes4(slot << (selectorSlotIndex << 5));\n address facetAddress_ = address(bytes20(ds.facets[selector]));\n bool continueLoop;\n for (uint256 facetIndex; facetIndex < numFacets; facetIndex++) {\n if (facetAddress_ == facetAddresses_[facetIndex]) {\n continueLoop = true;\n break;\n }\n }\n if (continueLoop) {\n continue;\n }\n facetAddresses_[numFacets] = facetAddress_;\n numFacets++;\n }\n }\n // Set the number of facet addresses in the array\n assembly {\n mstore(facetAddresses_, numFacets)\n }\n }\n\n /// @notice Gets the facet that supports the given selector.\n /// @dev If facet is not found return address(0).\n /// @param _functionSelector The function selector.\n /// @return facetAddress_ The facet address.\n function facetAddress(bytes4 _functionSelector)\n external\n view\n override\n returns (address facetAddress_)\n {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n facetAddress_ = address(bytes20(ds.facets[_functionSelector]));\n }\n\n // This implements ERC-165.\n function supportsInterface(bytes4 _interfaceId)\n external\n view\n override\n returns (bool)\n {\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n return ds.supportedInterfaces[_interfaceId];\n }\n}\n" + }, + "contracts/facets/DiamondCutFacet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\nimport {IDiamondCut} from \"../interfaces/IDiamondCut.sol\";\nimport {LibDiamond} from \"../libraries/LibDiamond.sol\";\n\ncontract DiamondCutFacet is IDiamondCut {\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external override {\n LibDiamond.enforceIsContractOwner();\n LibDiamond.DiamondStorage storage ds = LibDiamond.diamondStorage();\n uint256 originalSelectorCount = ds.selectorCount;\n uint256 selectorCount = originalSelectorCount;\n bytes32 selectorSlot;\n // Check if last selector slot is not full\n // \"selectorCount & 7\" is a gas efficient modulo by eight \"selectorCount % 8\"\n if (selectorCount & 7 > 0) {\n // get last selectorSlot\n // \"selectorCount >> 3\" is a gas efficient division by 8 \"selectorCount / 8\"\n selectorSlot = ds.selectorSlots[selectorCount >> 3];\n }\n // loop through diamond cut\n for (\n uint256 facetIndex;\n facetIndex < _diamondCut.length;\n facetIndex++\n ) {\n (selectorCount, selectorSlot) = LibDiamond\n .addReplaceRemoveFacetSelectors(\n selectorCount,\n selectorSlot,\n _diamondCut[facetIndex].facetAddress,\n _diamondCut[facetIndex].action,\n _diamondCut[facetIndex].functionSelectors\n );\n }\n if (selectorCount != originalSelectorCount) {\n ds.selectorCount = uint16(selectorCount);\n }\n // If last selector slot is not full\n // \"selectorCount & 7\" is a gas efficient modulo by eight \"selectorCount % 8\"\n if (selectorCount & 7 > 0) {\n // \"selectorCount >> 3\" is a gas efficient division by 8 \"selectorCount / 8\"\n ds.selectorSlots[selectorCount >> 3] = selectorSlot;\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n LibDiamond.initializeDiamondCut(_init, _calldata);\n }\n}\n" + }, + "contracts/CartesiDAppFactory.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n// @title Cartesi DApp Factory\npragma solidity ^0.8.0;\n\nimport {ICartesiDAppFactory} from \"./ICartesiDAppFactory.sol\";\nimport {CartesiDApp} from \"./CartesiDApp.sol\";\nimport {IDiamondCut} from \"./interfaces/IDiamondCut.sol\";\nimport {IERC173} from \"./interfaces/IERC173.sol\";\nimport {DiamondInit, DiamondConfig} from \"./upgrade_initializers/DiamondInit.sol\";\nimport {IBank} from \"./IBank.sol\";\n\ncontract CartesiDAppFactory is ICartesiDAppFactory {\n IDiamondCut public immutable diamondCutFacet;\n DiamondInit public immutable diamondInit;\n IBank public immutable feeManagerBank;\n IDiamondCut.FacetCut[] public diamondCut;\n\n struct FactoryConfig {\n IDiamondCut diamondCutFacet;\n DiamondInit diamondInit;\n IBank feeManagerBank;\n IDiamondCut.FacetCut[] diamondCut;\n }\n\n constructor(FactoryConfig memory _fConfig) {\n diamondCutFacet = _fConfig.diamondCutFacet;\n diamondInit = _fConfig.diamondInit;\n feeManagerBank = _fConfig.feeManagerBank;\n for (uint256 i; i < _fConfig.diamondCut.length; ++i) {\n diamondCut.push(_fConfig.diamondCut[i]);\n }\n }\n\n function newApplication(AppConfig calldata _appConfig)\n public\n returns (CartesiDApp)\n {\n CartesiDApp application = new CartesiDApp(\n address(this),\n address(diamondCutFacet)\n );\n DiamondConfig memory dConfig = DiamondConfig({\n templateHash: _appConfig.templateHash,\n inputDuration: _appConfig.inputDuration,\n challengePeriod: _appConfig.challengePeriod,\n inputLog2Size: _appConfig.inputLog2Size,\n feePerClaim: _appConfig.feePerClaim,\n feeManagerBank: address(feeManagerBank),\n feeManagerOwner: _appConfig.feeManagerOwner,\n validators: _appConfig.validators\n });\n IDiamondCut(address(application)).diamondCut(\n diamondCut,\n address(diamondInit),\n abi.encodeWithSelector(DiamondInit.init.selector, dConfig)\n );\n IERC173(address(application)).transferOwnership(\n _appConfig.diamondOwner\n );\n emit ApplicationCreated(application, _appConfig);\n return application;\n }\n}\n" + }, + "contracts/ICartesiDAppFactory.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n// @title Cartesi DApp Factory interface\npragma solidity ^0.8.0;\n\nimport {CartesiDApp} from \"./CartesiDApp.sol\";\n\ninterface ICartesiDAppFactory {\n /// @notice application configurations\n /// @param diamondOwner diamond owner\n /// @param templateHash state hash of the cartesi machine at t0\n /// @param inputDuration duration of input accumulation phase in seconds\n /// @param challengePeriod duration of challenge period in seconds\n /// @param inputLog2Size size of the input memory range in this machine\n /// @param feePerClaim fee per claim to reward the validators\n /// @param feeManagerOwner fee manager owner address\n /// @param validators initial validator set\n /// @dev validators have to be unique, if the same validator is added twice\n /// consensus will never be reached\n struct AppConfig {\n // DiamondCutFacet\n address diamondOwner;\n // RollupsFacet\n bytes32 templateHash;\n uint256 inputDuration;\n uint256 challengePeriod;\n // InputFacet\n uint256 inputLog2Size;\n // FeeManagerFacet\n uint256 feePerClaim;\n address feeManagerOwner;\n // ValidatorManagerFacet\n address payable[] validators;\n }\n\n /// @notice Deploy a new application\n /// @param _appConfig application configurations\n /// @return application address\n function newApplication(AppConfig calldata _appConfig)\n external\n returns (CartesiDApp);\n\n /// @notice Event emitted when a new application is deployed\n /// @param application application address\n /// @param config application configurations\n event ApplicationCreated(CartesiDApp indexed application, AppConfig config);\n}\n" + }, + "contracts/CartesiDApp.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n*\n* Implementation of a diamond.\n/******************************************************************************/\n\nimport {LibDiamond} from \"./libraries/LibDiamond.sol\";\nimport {IDiamondCut} from \"./interfaces/IDiamondCut.sol\";\n\ncontract CartesiDApp {\n constructor(address _contractOwner, address _diamondCutFacet) payable {\n LibDiamond.setContractOwner(_contractOwner);\n\n // Add the diamondCut external function from the diamondCutFacet\n IDiamondCut.FacetCut[] memory cut = new IDiamondCut.FacetCut[](1);\n bytes4[] memory functionSelectors = new bytes4[](1);\n functionSelectors[0] = IDiamondCut.diamondCut.selector;\n cut[0] = IDiamondCut.FacetCut({\n facetAddress: _diamondCutFacet,\n action: IDiamondCut.FacetCutAction.Add,\n functionSelectors: functionSelectors\n });\n LibDiamond.diamondCut(cut, address(0), \"\");\n }\n\n // Find facet for function that is called and execute the\n // function if a facet is found and return any value.\n fallback() external payable {\n LibDiamond.DiamondStorage storage ds;\n bytes32 position = LibDiamond.DIAMOND_STORAGE_POSITION;\n // get diamond storage\n assembly {\n ds.slot := position\n }\n // get facet from function selector\n address facet = address(bytes20(ds.facets[msg.sig]));\n require(facet != address(0), \"Diamond: Function does not exist\");\n // Execute external function from facet using delegatecall and return any value.\n assembly {\n // copy function selector and any arguments\n calldatacopy(0, 0, calldatasize())\n // execute function call using the facet\n let result := delegatecall(gas(), facet, 0, calldatasize(), 0, 0)\n // get any return value\n returndatacopy(0, 0, returndatasize())\n // return any return value or error back to the caller\n switch result\n case 0 {\n revert(0, returndatasize())\n }\n default {\n return(0, returndatasize())\n }\n }\n }\n\n receive() external payable {}\n}\n" + }, + "contracts/interfaces/IFeeManager.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Fee Manager interface\npragma solidity >=0.7.0;\n\nimport {IBank} from \"../IBank.sol\";\n\ninterface IFeeManager {\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\n /// @param _validator address of the validator\n function numClaimsRedeemable(address _validator)\n external\n view\n returns (uint256);\n\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\n /// @param _validator address of the validator\n function getNumClaimsRedeemed(address _validator)\n external\n view\n returns (uint256);\n\n /// @notice contract owner can set/reset the value of fee per claim\n /// @param _value the new value of fee per claim\n function resetFeePerClaim(uint256 _value) external;\n\n /// @notice this function can be called to redeem fees for validators\n /// @param _validator address of the validator that is redeeming\n function redeemFee(address _validator) external;\n\n /// @notice returns the bank used to manage fees\n function getFeeManagerBank() external view returns (IBank);\n\n /// @notice emitted on resetting feePerClaim\n event FeePerClaimReset(uint256 value);\n\n /// @notice emitted on ERC20 funds redeemed by validator\n event FeeRedeemed(address validator, uint256 claims);\n}\n" + }, + "contracts/facets/FeeManagerFacet.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Fee Manager facet\npragma solidity >=0.8.8;\n\nimport {IBank} from \"../IBank.sol\";\nimport {IFeeManager} from \"../interfaces/IFeeManager.sol\";\nimport {LibFeeManager} from \"../libraries/LibFeeManager.sol\";\n\ncontract FeeManagerFacet is IFeeManager {\n using LibFeeManager for LibFeeManager.DiamondStorage;\n\n /// @notice functions modified by noReentrancy are not subject to recursion\n modifier noReentrancy() {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n require(!feeManagerDS.lock, \"reentrancy not allowed\");\n feeManagerDS.lock = true;\n _;\n feeManagerDS.lock = false;\n }\n\n /// @notice this function can be called to check the number of claims that's redeemable for the validator\n /// @param _validator address of the validator\n function numClaimsRedeemable(address _validator)\n public\n view\n override\n returns (uint256)\n {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n return feeManagerDS.numClaimsRedeemable(_validator);\n }\n\n /// @notice this function can be called to check the number of claims that has been redeemed for the validator\n /// @param _validator address of the validator\n function getNumClaimsRedeemed(address _validator)\n public\n view\n override\n returns (uint256)\n {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n return feeManagerDS.getNumClaimsRedeemed(_validator);\n }\n\n /// @notice contract owner can reset the value of fee per claim\n /// @param _value the new value of fee per claim\n function resetFeePerClaim(uint256 _value) public override {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n feeManagerDS.onlyOwner();\n feeManagerDS.resetFeePerClaim(_value);\n }\n\n /// @notice this function can be called to redeem fees for validators\n /// @param _validator address of the validator that is redeeming\n function redeemFee(address _validator) public override noReentrancy {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n feeManagerDS.redeemFee(_validator);\n }\n\n /// @notice returns the bank used to manage fees\n function getFeeManagerBank() public view override returns (IBank) {\n LibFeeManager.DiamondStorage storage feeManagerDS = LibFeeManager\n .diamondStorage();\n return feeManagerDS.bank;\n }\n}\n" + }, + "contracts/facets/ERC20PortalFacet.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Generic ERC20 Portal facet\npragma solidity ^0.8.0;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nimport {IERC20Portal} from \"../interfaces/IERC20Portal.sol\";\n\nimport {LibInput} from \"../libraries/LibInput.sol\";\n\ncontract ERC20PortalFacet is IERC20Portal {\n using LibInput for LibInput.DiamondStorage;\n\n bytes32 constant INPUT_HEADER = keccak256(\"ERC20_Transfer\");\n\n /// @notice deposit an amount of a generic ERC20 in the portal and create tokens in L2\n /// @param _ERC20 address of the ERC20 token contract\n /// @param _amount amount of the ERC20 token to be deposited\n /// @param _data information to be interpreted by L2\n /// @return hash of input generated by deposit\n function erc20Deposit(\n address _ERC20,\n uint256 _amount,\n bytes calldata _data\n ) public override returns (bytes32) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n IERC20 token = IERC20(_ERC20);\n\n require(\n token.transferFrom(msg.sender, address(this), _amount),\n \"ERC20 transferFrom failed\"\n );\n\n bytes memory input = abi.encode(\n INPUT_HEADER,\n msg.sender,\n _ERC20,\n _amount,\n _data\n );\n\n emit ERC20Deposited(_ERC20, msg.sender, _amount, _data);\n return inputDS.addInternalInput(input);\n }\n}\n" + }, + "contracts/facets/EtherPortalFacet.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Ether Portal facet\npragma solidity ^0.8.0;\n\nimport {IEtherPortal} from \"../interfaces/IEtherPortal.sol\";\n\nimport {LibInput} from \"../libraries/LibInput.sol\";\n\ncontract EtherPortalFacet is IEtherPortal {\n using LibInput for LibInput.DiamondStorage;\n\n bytes32 constant INPUT_HEADER = keccak256(\"Ether_Transfer\");\n\n /// @notice deposit an amount of Ether in the portal and create Ether in L2\n /// @param _data information to be interpreted by L2\n /// @return hash of input generated by deposit\n function etherDeposit(bytes calldata _data)\n public\n payable\n override\n returns (bytes32)\n {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n bytes memory input = abi.encode(\n INPUT_HEADER,\n msg.sender,\n msg.value,\n _data\n );\n\n emit EtherDeposited(msg.sender, msg.value, _data);\n return inputDS.addInternalInput(input);\n }\n\n /// @notice withdraw an amount of Ether from the portal\n /// @param _data data with withdrawal information\n /// @dev can only be called by the Rollups contract\n function etherWithdrawal(bytes calldata _data)\n public\n override\n returns (bool)\n {\n // Delegate calls preserve msg.sender, msg.value and address(this)\n require(msg.sender == address(this), \"only itself\");\n\n (address payable receiver, uint256 value) = abi.decode(\n _data,\n (address, uint256)\n );\n\n // We used to call receiver.transfer(value) but it's no\n // longer considered safe, as it assumes gas costs are\n // immutable, while in fact they are not.\n (bool success, ) = receiver.call{value: value}(\"\");\n require(success, \"transfer failed\");\n\n emit EtherWithdrawn(receiver, value);\n\n return true;\n }\n}\n" + }, + "contracts/facets/InputFacet.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Input facet\npragma solidity ^0.8.0;\n\nimport {IInput} from \"../interfaces/IInput.sol\";\n\nimport {LibInput} from \"../libraries/LibInput.sol\";\n\ncontract InputFacet is IInput {\n using LibInput for LibInput.DiamondStorage;\n\n /// @notice add input to processed by next epoch\n /// @param _input input to be understood by offchain machine\n /// @dev offchain code is responsible for making sure\n /// that input size is power of 2 and multiple of 8 since\n // the offchain machine has a 8 byte word\n function addInput(bytes calldata _input) public override returns (bytes32) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n return inputDS.addInput(_input);\n }\n\n /// @notice get input inside inbox of currently proposed claim\n /// @param _index index of input inside that inbox\n /// @return hash of input at index _index\n /// @dev currentInputBox being zero means that the inputs for\n /// the claimed epoch are on input box one\n function getInput(uint256 _index) public view override returns (bytes32) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n return inputDS.getInput(_index);\n }\n\n /// @notice get number of inputs inside inbox of currently proposed claim\n /// @return number of inputs on that input box\n /// @dev currentInputBox being zero means that the inputs for\n /// the claimed epoch are on input box one\n function getNumberOfInputs() public view override returns (uint256) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n return inputDS.getNumberOfInputs();\n }\n\n /// @notice get inbox currently receiveing inputs\n /// @return input inbox currently receiveing inputs\n function getCurrentInbox() public view override returns (uint256) {\n LibInput.DiamondStorage storage inputDS = LibInput.diamondStorage();\n return inputDS.currentInputBox;\n }\n}\n" + }, + "contracts/interfaces/IInput.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title Input interface\npragma solidity >=0.7.0;\n\ninterface IInput {\n /// @notice adds input to correct inbox\n /// @param _input bytes array of input\n /// @return merkle root hash of input\n /// @dev msg.sender and timestamp are preppended log2 size\n /// has to be calculated offchain taking that into account\n function addInput(bytes calldata _input) external returns (bytes32);\n\n /// @notice returns input from correct input inbox\n /// @param _index position of the input on inbox\n /// @return root hash of input\n function getInput(uint256 _index) external view returns (bytes32);\n\n /// @notice returns number of inputs on correct inbox\n /// @return number of inputs of non active inbox\n function getNumberOfInputs() external view returns (uint256);\n\n /// @notice returns active current inbox index\n /// @return index of current active inbox\n function getCurrentInbox() external view returns (uint256);\n\n /// @notice input added\n /// @param epochNumber which epoch this input belongs to\n /// @param inputIndex index of the input just added\n /// @param sender msg.sender\n /// @param timestamp block.timestamp\n /// @param input input data\n event InputAdded(\n uint256 indexed epochNumber,\n uint256 indexed inputIndex,\n address sender,\n uint256 timestamp,\n bytes input\n );\n}\n" + }, + "contracts/test_helper/SimpleNFT.sol": { + "content": "// Copyright 2022 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title A Simple NFT Contract\npragma solidity ^0.8.0;\n\nimport {ERC721} from \"@openzeppelin/contracts/token/ERC721/ERC721.sol\";\n\ncontract SimpleNFT is ERC721 {\n // name: SimpleNFT\n // symbol: SIM\n constructor(uint256[] memory tokenIds) ERC721(\"SimpleNFT\", \"SIM\") {\n for (uint256 i; i < tokenIds.length; i++) {\n _safeMint(msg.sender, tokenIds[i]);\n }\n }\n}\n" + }, + "contracts/test_helper/SimpleToken.sol": { + "content": "// Copyright 2021 Cartesi Pte. Ltd.\n\n// SPDX-License-Identifier: Apache-2.0\n// Licensed under the Apache License, Version 2.0 (the \"License\"); you may not use\n// this file except in compliance with the License. You may obtain a copy of the\n// License at http://www.apache.org/licenses/LICENSE-2.0\n\n// Unless required by applicable law or agreed to in writing, software distributed\n// under the License is distributed on an \"AS IS\" BASIS, WITHOUT WARRANTIES OR\n// CONDITIONS OF ANY KIND, either express or implied. See the License for the\n// specific language governing permissions and limitations under the License.\n\n/// @title A Simple Token\npragma solidity ^0.8.0;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract SimpleToken is ERC20 {\n // name: SimpleToken\n // symbol: SIM\n constructor(uint256 initialSupply) ERC20(\"SimpleToken\", \"SIM\") {\n // on Hardhat network, 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 should be the address of signers[0]\n // generated from default mnemonic \"test test test test test test test test test test test junk\"\n _mint(0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266, initialSupply);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/echo-js/docker-bake.hcl b/echo-js/docker-bake.hcl new file mode 100644 index 00000000..285e8a62 --- /dev/null +++ b/echo-js/docker-bake.hcl @@ -0,0 +1,43 @@ + +group "default" { + targets = ["dapp", "server", "console"] +} + +# crossenv toolchain for js dapps +target "toolchain-js" { + context = "./docker" + target = "toolchain-js" + tags = ["cartesi/toolchain-js"] +} + +target "fs" { + context = "./docker" + target = "dapp-fs-build" + contexts = { + dapp-build = "target:dapp" + } +} + +target "server" { + context = "./docker" + target = "machine-server" + contexts = { + dapp-build = "target:dapp" + } +} + +target "console" { + context = "./docker" + target = "machine-console" + contexts = { + dapp-build = "target:dapp" + } +} + +target "machine" { + context = "./docker" + target = "machine-standalone" + contexts = { + dapp-build = "target:dapp" + } +} diff --git a/echo-js/docker-bake.override.hcl b/echo-js/docker-bake.override.hcl new file mode 100644 index 00000000..347bc1d3 --- /dev/null +++ b/echo-js/docker-bake.override.hcl @@ -0,0 +1,15 @@ + +target "dapp" { +} + +target "server" { + tags = ["cartesi/dapp:echo-js-devel-server"] +} + +target "console" { + tags = ["cartesi/dapp:echo-js-devel-console"] +} + +target "machine" { + tags = ["cartesi/dapp:echo-js-devel-machine"] +} diff --git a/echo-js/docker-compose.override.yml b/echo-js/docker-compose.override.yml new file mode 100644 index 00000000..2f21a433 --- /dev/null +++ b/echo-js/docker-compose.override.yml @@ -0,0 +1,5 @@ +version: "3" + +services: + server_manager: + image: cartesi/dapp:echo-js-devel-server diff --git a/echo-js/docker/Dockerfile b/echo-js/docker/Dockerfile new file mode 100644 index 00000000..80584c23 --- /dev/null +++ b/echo-js/docker/Dockerfile @@ -0,0 +1,134 @@ +# syntax=docker.io/docker/dockerfile:1.4 +# layers for caching and versioning +FROM cartesi/toolchain:0.10.0 as toolchain +FROM cartesi/rootfs:0.12.0 as rootfs +FROM cartesi/server-manager:0.3.0 as server-manager + +FROM rootfs as toolchain-js + +ENV DEBIAN_FRONTEND=noninteractive +RUN apt update \ + && apt install -y \ + libncurses-dev \ + libgdbm-dev \ + libz-dev \ + tk-dev \ + libsqlite3-dev \ + libreadline-dev \ + liblzma-dev \ + libffi-dev \ + libssl-dev + +ENV PYTHON_VERSION=3.10 +ENV PYTHON_VERSION_FULL=3.10.1 +ENV BUILD_PYTHON_PREFIX=/opt/build-python +ENV HOST_PYTHON_PREFIX=/mnt/python-dapp + +# Download Python source +WORKDIR /tmp +RUN wget https://www.python.org/ftp/python/$PYTHON_VERSION_FULL/Python-$PYTHON_VERSION_FULL.tgz +RUN tar zxfv Python-$PYTHON_VERSION_FULL.tgz + +# Build build-python from source +RUN cp -r Python-$PYTHON_VERSION_FULL build-python +WORKDIR /tmp/build-python +RUN ./configure --prefix=$BUILD_PYTHON_PREFIX +RUN make -j$(nproc) +RUN make install + +ENV PATH=$BUILD_PYTHON_PREFIX/bin:$PATH + +# Build host-python +WORKDIR /tmp +RUN cp -r Python-$PYTHON_VERSION_FULL host-python +WORKDIR /tmp/host-python +RUN CPPFLAGS="-I/opt/riscv/rootfs/buildroot/work/staging/usr/include" \ + LDFLAGS="-L/opt/riscv/rootfs/buildroot/work/staging/usr/lib" \ + ./configure \ + --enable-shared \ + --enable-optimizations \ + --prefix=$HOST_PYTHON_PREFIX \ + --host=riscv64-cartesi-linux-gnu \ + --build=x86_64-linux-gnu \ + --without-ensurepip \ + --disable-test-modules \ + ac_cv_buggy_getaddrinfo=no \ + ac_cv_file__dev_ptmx=yes \ + ac_cv_file__dev_ptc=no +WORKDIR /tmp/host-python +RUN make -j$(nproc) +RUN make install + +WORKDIR /tmp +RUN pip3 install crossenv +RUN rm -rf Python-$PYTHON_VERSION_FULL* + +# download standard machine drives +FROM busybox as machine-core + +WORKDIR /opt/cartesi/share + +# download dependencies +COPY dependencies . +COPY shasumfile . +RUN cat dependencies | xargs wget +RUN sha1sum -c shasumfile + +# stage to build the dapp ext2 filesystem +FROM toolchain as dapp-fs-build + +# install jq +RUN < $FILES +rsync -r --files-from=$FILES . $FS_DIR + +# create tar +tar --sort=name --mtime="2022-01-01" --owner=0 --group=0 --numeric-owner -cf $TAR --directory=$FS_DIR . + +# generate ext2 filesystem +FS_SIZE=$(jq -rs '.[0] * .[1] | .fs.size // 4096' $CONFIG_DEFAULT $CONFIG_DAPP) +genext2fs -f -i 512 -b $FS_SIZE -a $TAR $EXT2 + +# truncate to multiple of 4k +truncate -s %4096 $EXT2 diff --git a/echo-js/docker/build-machine.sh b/echo-js/docker/build-machine.sh new file mode 100755 index 00000000..3a205ab9 --- /dev/null +++ b/echo-js/docker/build-machine.sh @@ -0,0 +1,29 @@ +#!/bin/bash +# Copyright 2022 Cartesi Pte. Ltd. +# +# 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. + +set -e + +MACHINE_DIR=$1 +ROLLUP_HTTP_SERVER_PORT=5004 + +cartesi-machine \ + --ram-length=128Mi \ + --rollup \ + --flash-drive=label:dapp,filename:dapp.ext2 \ + --flash-drive=label:root,filename:rootfs.ext2 \ + --ram-image=linux-5.5.19-ctsi-5.bin \ + --rom-image=rom.bin \ + --store=$MACHINE_DIR \ + -- "cd /mnt/dapp; \ + ROLLUP_HTTP_SERVER_URL=\"http://127.0.0.1:$ROLLUP_HTTP_SERVER_PORT\" \ + ./entrypoint.sh" diff --git a/echo-js/docker/default.json b/echo-js/docker/default.json new file mode 100644 index 00000000..6b5013ba --- /dev/null +++ b/echo-js/docker/default.json @@ -0,0 +1,17 @@ +{ + "fs": { + "files": ["entrypoint.sh"], + "size": 4096 + }, + "machine": { + "entrypoint": "entrypoint.sh", + "ramLength": "128Mi" + }, + "contract": { + "inputDuration": 86400, + "challengePeriod": 604800, + "inputLog2Size": 25, + "feePerClaim": "1000000000000000000", + "validators": "0,1,2" + } +} diff --git a/echo-js/docker/dependencies b/echo-js/docker/dependencies new file mode 100644 index 00000000..b0ba67a2 --- /dev/null +++ b/echo-js/docker/dependencies @@ -0,0 +1,3 @@ +https://wchfs-media.fra1.digitaloceanspaces.com/cartesi/fs/example-js/0.12.0/rootfs.ext2 +https://github.com/cartesi/image-kernel/releases/download/v0.12.0/linux-5.5.19-ctsi-5.bin +https://github.com/cartesi/machine-emulator-rom/releases/download/v0.11.0/rom.bin diff --git a/echo-js/docker/run-machine-console.sh b/echo-js/docker/run-machine-console.sh new file mode 100755 index 00000000..2c595c16 --- /dev/null +++ b/echo-js/docker/run-machine-console.sh @@ -0,0 +1,22 @@ +#!/bin/bash +# Copyright 2022 Cartesi Pte. Ltd. +# +# 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. + +cartesi-machine \ + --ram-length=128Mi \ + --rollup \ + --flash-drive=label:dapp,filename:dapp.ext2 \ + --flash-drive=label:root,filename:rootfs.ext2 \ + --ram-image=linux-5.5.19-ctsi-5.bin \ + --rom-image=rom.bin \ + -i \ + -- "/bin/sh" diff --git a/echo-js/docker/shasumfile b/echo-js/docker/shasumfile new file mode 100644 index 00000000..527836b1 --- /dev/null +++ b/echo-js/docker/shasumfile @@ -0,0 +1,3 @@ +88ec5b0a8c4f29c1f64189c07d222628b838078d *rom.bin +f2febaa5f9296d42756e6fe74e062fdb334f7d84 *rootfs.ext2 +c8c986e0890b624fe52a556a5a817c502f0bb2f0 *linux-5.5.19-ctsi-5.bin diff --git a/echo-js/entrypoint.sh b/echo-js/entrypoint.sh new file mode 100755 index 00000000..9f949ccc --- /dev/null +++ b/echo-js/entrypoint.sh @@ -0,0 +1,15 @@ +#!/bin/sh +# Copyright 2022 Cartesi Pte. Ltd. +# +# 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. +# +set -e +rollup-init qjs server/src/echo-server.js diff --git a/echo-js/server/src/echo-server.js b/echo-js/server/src/echo-server.js new file mode 100644 index 00000000..74edd8f6 --- /dev/null +++ b/echo-js/server/src/echo-server.js @@ -0,0 +1,81 @@ +import fetch from './modules/fetch.js'; +import {getenv} from 'std'; + +const ROLLUP_ADDRESS = getenv('ROLLUP_HTTP_SERVER_URL'); + +async function handle_advance(data) { + print(`Received advance request data ${JSON.stringify(data)}`); + print('Adding notice'); + const response = await fetch(`${ROLLUP_ADDRESS}/notice`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: { + payload: data.payload, + }, + }); + print(`Received notice status ${response.status} body ${JSON.stringify(response.json())}`); + return 'accept'; +} + +async function handle_inspect(data) { + print('Received inspect request data ', data); + print('Adding report'); + const response = await fetch(`${ROLLUP_ADDRESS}/report`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body: { + payload: data.payload, + }, + }); + print(`Received report status ${response.status}`); + return 'accept'; +} + +async function main() { + print(`HTTP rollup_server url is ${ROLLUP_ADDRESS}`) + let body = { + status: 'accept' + }; + while (true) { + print('Sending finish'); + const response = await fetch(`${ROLLUP_ADDRESS}/finish`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'Accept': 'application/json', + }, + body, + }); + print(`Received finish status ${response.status}`); + if (response.status === 202) { + print('No pending rollup request, trying again'); + } else { + let rollup_request = response.json(); + let metadata = rollup_request.data.metadata; + + if (metadata.epoch_index === 0 && metadata.input_index === 0) { + let rollup_address = metadata.msg_sender; + print(`Captured rollup address: ${rollup_address}`) + } else { + switch (rollup_request.request_type) { + case 'advance_state': + body.status = await handle_advance(rollup_request.data); + break; + case 'inspect_state': + body.status = await handle_inspect(rollup_request.data); + break; + } + } + } + } +} + +main(); + + diff --git a/echo-js/server/src/modules/fetch.js b/echo-js/server/src/modules/fetch.js new file mode 100644 index 00000000..dd8dc24e --- /dev/null +++ b/echo-js/server/src/modules/fetch.js @@ -0,0 +1,150 @@ +/** + * FetchToCurl Strongly inspired by https://github.com/leoek/fetch-to-curl + */ + +import * as std from "std"; +import * as os from "os"; + +function generateMethod(options) { + const method = options.method; + if (!method) return ''; + const type = { + GET: ' -X "GET"', + POST: ' -X "POST"', + PUT: ' -X "PUT"', + PATCH: ' -X "PATCH"', + DELETE: ' -X "DELETE"', + HEAD: ' -X "HEAD"', + OPTIONS: ' -X "OPTIONS"' + }; + return type[method.toUpperCase()] || ''; +} + +function isInstanceOfHeaders(val) { + if (typeof Headers !== "function") { + /** + * Environment does not support the Headers constructor + * old internet explorer? + */ + return false; + } + return val instanceof Headers; +} + +function getHeaderString(name, val) { + return ` -H "${name}: ${`${val}`.replace(/(\\|")/g, '\\$1')}"`; +} + +function generateHeader(options = {}) { + const {headers} = options; + let isEncode = false; + let headerParam = ''; + if (isInstanceOfHeaders(headers)) { + headers.forEach((val, name) => { + if (name.toLocaleLowerCase() !== 'content-length') { + headerParam += getHeaderString(name, val); + } + if (name.toLocaleLowerCase() === 'accept-encoding') { + isEncode = true; + } + }) + } else if (headers) { + Object.keys(headers).map(name => { + if (name.toLocaleLowerCase() !== 'content-length') { + headerParam += getHeaderString(name, headers[name]); + } + if (name.toLocaleLowerCase() === 'accept-encoding') { + isEncode = true; + } + }); + } + return { + params: headerParam, + isEncode, + }; +} + +function generateBody(body) { + if (!body) return ''; + if (typeof body === "object") { + return ` -d '${JSON.stringify(body)}'`; + } + return ` -d '${body}'`; +} + +function generateCompress(isEncode) { + return isEncode ? ' --compressed' : ''; +} + +function fetchToCurl(requestInfo, requestInit) { + let url, options; + /** + * initialization with an empty object is done here to + * keep everything backwards compatible to 0.4.0 and below + */ + if (typeof requestInfo === "string" || requestInfo instanceof URL) { + url = requestInfo; + options = requestInit || {}; + } else { + url = (requestInfo || {}).url + options = requestInfo || {} + } + const {body} = options; + const headers = generateHeader(options); + return `curl -s --connect-timeout 99999 -w '%{json}' '${url}'${generateMethod(options)}${headers.params || ''}${generateBody(body)}${generateCompress(headers.isEncode)}`; +} + +export default (resource, init) => { + // curl command + let curlCmd = fetchToCurl(resource, init); + // exec curl command in subprocess + let spErr = {}; + let curlOutputFile = std.popen(curlCmd, 'r', spErr); + let curlOutput = curlOutputFile.readAsString(); + curlOutputFile.close(); + + if (curlOutput.indexOf('}{') > -1) { + curlOutput = curlOutput.replace('}{', '},{'); + } + + if (curlOutput.indexOf('[]') === 0) { + curlOutput = '{},' + curlOutput.substring(2); + } + + if (curlOutput.indexOf(']{') > -1) { + curlOutput = curlOutput.replace(']{', '],{'); + } + + if (curlOutput.charAt(0) !== '{' && curlOutput.charAt(0) !== '[') { + curlOutput = '{},' + curlOutput.substring(curlOutput.indexOf("{")); + } + + let data, meta; + + [ + data, + meta, + ] = JSON.parse(`[${curlOutput}]`); + + const responseUrl = resource; + let responseStatus = meta.http_code; + let responseOk = responseStatus >= 200 && responseStatus < 300; + + return new Promise((resolve, reject) => { + const response = { // TODO fill properties (https://developer.mozilla.org/en-US/docs/Web/API/Response) + headers: {}, // TODO + ok: responseOk, + url: responseUrl, + status: responseStatus, + type: 'json', + text: () => JSON.stringify(data), + json: () => data, + }; + + if (responseOk) { + resolve(response); + } else { + reject(response); + } + }); +};