From c3e4fdd321cf324ac2cc0ea56e5433d209ae2dc6 Mon Sep 17 00:00:00 2001 From: Slava <20563034+veaceslavdoina@users.noreply.github.com> Date: Mon, 21 Oct 2024 11:00:46 +0300 Subject: [PATCH] Add codex_testnet deployment artifacts (#197) https://github.com/codex-storage/infra-codex/issues/248 --- deployments/codex_testnet/Marketplace.json | 206 +++++++++--------- .../73497e5b46b1a1eec0c64f9cd6de8fb8.json | 102 +++++++++ 2 files changed, 205 insertions(+), 103 deletions(-) create mode 100644 deployments/codex_testnet/solcInputs/73497e5b46b1a1eec0c64f9cd6de8fb8.json diff --git a/deployments/codex_testnet/Marketplace.json b/deployments/codex_testnet/Marketplace.json index ce65d4c..2c1d5d1 100644 --- a/deployments/codex_testnet/Marketplace.json +++ b/deployments/codex_testnet/Marketplace.json @@ -1,5 +1,5 @@ { - "address": "0xfE822Df439d987849a90B64a4C0e26a297DBD47F", + "address": "0x3F9Cf3F40F0e87d804B776D8403e3d29F85211f4", "abi": [ { "inputs": [ @@ -1195,19 +1195,19 @@ "type": "function" } ], - "transactionHash": "0x9b8fa732174122641656b7159eb82f7bc5bf80541bae4bfc9fea0e7568210558", + "transactionHash": "0x71b1fae1d7476617658ce9edefb4e5e1764bbcab50aee59c9d62602af96b0c60", "receipt": { "to": null, "from": "0x3A39904B71595608524274BFD8c20FCfd9e77236", - "contractAddress": "0xfE822Df439d987849a90B64a4C0e26a297DBD47F", + "contractAddress": "0x3F9Cf3F40F0e87d804B776D8403e3d29F85211f4", "transactionIndex": 0, - "gasUsed": "3755625", + "gasUsed": "3833220", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x55a49f2607662aebd06ed6a4ecacfe2edf528b2aa3db396a512890104b672d91", - "transactionHash": "0x9b8fa732174122641656b7159eb82f7bc5bf80541bae4bfc9fea0e7568210558", + "blockHash": "0x2b898ea9323f71207616b01bffca92b9b4fb9d5128a0d3a7c6a0467b794bf6e4", + "transactionHash": "0x71b1fae1d7476617658ce9edefb4e5e1764bbcab50aee59c9d62602af96b0c60", "logs": [], - "blockNumber": 1804141, - "cumulativeGasUsed": "3755625", + "blockNumber": 1916275, + "cumulativeGasUsed": "3833220", "status": 1, "byzantium": true }, @@ -1233,11 +1233,11 @@ "0x34a22f3911De437307c6f4485931779670f78764", "0x02dd582726F7507D7d0F8bD8bf8053d3006F9092" ], - "numDeployments": 3, - "solcInputHash": "449a9ef8325abda653eb59796f71b45e", - "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"repairRewardPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"maxNumberOfSlashes\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"slashCriterion\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"slashPercentage\",\"type\":\"uint8\"}],\"internalType\":\"struct CollateralConfig\",\"name\":\"collateral\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"period\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timeout\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"downtime\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"zkeyHash\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"downtimeProduct\",\"type\":\"uint8\"}],\"internalType\":\"struct ProofConfig\",\"name\":\"proofs\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"maxReservations\",\"type\":\"uint8\"}],\"internalType\":\"struct SlotReservationsConfig\",\"name\":\"reservations\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketplaceConfig\",\"name\":\"configuration\",\"type\":\"tuple\"},{\"internalType\":\"contract IERC20\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"contract IGroth16Verifier\",\"name\":\"verifier\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"ProofSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"RequestCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"RequestFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"SlotFilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"SlotFreed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"SlotReservationsFull\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"StorageRequested\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"canReserveSlot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"config\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"repairRewardPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"maxNumberOfSlashes\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"slashCriterion\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"slashPercentage\",\"type\":\"uint8\"}],\"internalType\":\"struct CollateralConfig\",\"name\":\"collateral\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"period\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timeout\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"downtime\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"zkeyHash\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"downtimeProduct\",\"type\":\"uint8\"}],\"internalType\":\"struct ProofConfig\",\"name\":\"proofs\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"maxReservations\",\"type\":\"uint8\"}],\"internalType\":\"struct SlotReservationsConfig\",\"name\":\"reservations\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketplaceConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"a\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"x\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"y\",\"type\":\"tuple\"}],\"internalType\":\"struct G2Point\",\"name\":\"b\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"c\",\"type\":\"tuple\"}],\"internalType\":\"struct Groth16Proof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"fillSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralRecipient\",\"type\":\"address\"}],\"name\":\"freeSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"freeSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"getActiveSlot\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"cid\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"struct Content\",\"name\":\"content\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct Request\",\"name\":\"request\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"internalType\":\"struct Marketplace.ActiveSlot\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getChallenge\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"getHost\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getPointer\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"getRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"cid\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"struct Content\",\"name\":\"content\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct Request\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isProofRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"},{\"internalType\":\"Periods.Period\",\"name\":\"period\",\"type\":\"uint256\"}],\"name\":\"markProofAsMissing\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"missingProofs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"myRequests\",\"outputs\":[{\"internalType\":\"RequestId[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mySlots\",\"outputs\":[{\"internalType\":\"SlotId[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"requestEnd\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"requestExpiry\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"requestState\",\"outputs\":[{\"internalType\":\"enum RequestState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"cid\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"struct Content\",\"name\":\"content\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct Request\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"requestStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"reserveSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"slotState\",\"outputs\":[{\"internalType\":\"enum SlotState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"a\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"x\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"y\",\"type\":\"tuple\"}],\"internalType\":\"struct G2Point\",\"name\":\"b\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"c\",\"type\":\"tuple\"}],\"internalType\":\"struct Groth16Proof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"submitProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"willProofBeRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"withdrawRecipient\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"fillSlot(bytes32,uint256,((uint256,uint256),((uint256,uint256),(uint256,uint256)),(uint256,uint256)))\":{\"params\":{\"proof\":\"Groth16 proof procing possession of the slot data.\",\"requestId\":\"RequestId identifying the request containing the slot to fill.\",\"slotIndex\":\"Index of the slot in the request.\"}},\"freeSlot(bytes32)\":{\"details\":\"The host that filled the slot must have initiated the transaction (msg.sender). This overload allows `rewardRecipient` and `collateralRecipient` to be optional.\",\"params\":{\"slotId\":\"id of the slot to free\"}},\"freeSlot(bytes32,address,address)\":{\"params\":{\"collateralRecipient\":\"address to refund collateral to\",\"rewardRecipient\":\"address to send rewards to\",\"slotId\":\"id of the slot to free\"}},\"getChallenge(bytes32)\":{\"params\":{\"id\":\"Slot's ID for which the challenge should be calculated\"},\"returns\":{\"_0\":\"Challenge for current Period that should be used for generation of proofs\"}},\"getPointer(bytes32)\":{\"details\":\"For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\",\"params\":{\"id\":\"Slot's ID for which the pointer should be calculated\"},\"returns\":{\"_0\":\"Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\"}},\"isProofRequired(bytes32)\":{\"params\":{\"id\":\"Slot's ID for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\"},\"returns\":{\"_0\":\"bool indicating if proof is required for current period\"}},\"missingProofs(bytes32)\":{\"returns\":{\"_0\":\"Number of missed proofs since Slot was Filled\"}},\"willProofBeRequired(bytes32)\":{\"details\":\"for more info about downtime see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime)\",\"params\":{\"id\":\"SlotId for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\"},\"returns\":{\"_0\":\"bool\"}},\"withdrawFunds(bytes32)\":{\"details\":\"Request must be expired, must be in RequestStat e.New, and the transaction must originate from the depositer address.\",\"params\":{\"requestId\":\"the id of the request\"}},\"withdrawFunds(bytes32,address)\":{\"details\":\"Request must be expired, must be in RequestState.New, and the transaction must originate from the depositer address.\",\"params\":{\"requestId\":\"the id of the request\",\"withdrawRecipient\":\"address to return the remaining funds to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"fillSlot(bytes32,uint256,((uint256,uint256),((uint256,uint256),(uint256,uint256)),(uint256,uint256)))\":{\"notice\":\"Fills a slot. Reverts if an invalid proof of the slot data is provided.\"},\"freeSlot(bytes32)\":{\"notice\":\"Frees a slot, paying out rewards and returning collateral for finished or cancelled requests to the host that has filled the slot.\"},\"freeSlot(bytes32,address,address)\":{\"notice\":\"Frees a slot, paying out rewards and returning collateral for finished or cancelled requests.\"},\"willProofBeRequired(bytes32)\":{\"notice\":\"Proof Downtime specifies part of the Period when the proof is not required even if the proof should be required. This function returns true if the pointer is in downtime (hence no proof required now) and at the same time the proof will be required later on in the Period.\"},\"withdrawFunds(bytes32)\":{\"notice\":\"Withdraws remaining storage request funds back to the client that deposited them.\"},\"withdrawFunds(bytes32,address)\":{\"notice\":\"Withdraws storage request funds to the provided address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Marketplace.sol\":\"Marketplace\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"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/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc3ff3f5c4584e1d9a483ad7ced51ab64523201f4e3d3c65293e4ca8aeb77a961\",\"license\":\"MIT\"},\"contracts/Configuration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nstruct MarketplaceConfig {\\n CollateralConfig collateral;\\n ProofConfig proofs;\\n SlotReservationsConfig reservations;\\n}\\n\\nstruct CollateralConfig {\\n /// @dev percentage of remaining collateral slot after it has been freed\\n /// (equivalent to `collateral - (collateral*maxNumberOfSlashes*slashPercentage)/100`)\\n /// TODO: to be aligned more closely with actual cost of repair once bandwidth incentives are known,\\n /// see https://github.com/codex-storage/codex-contracts-eth/pull/47#issuecomment-1465511949.\\n uint8 repairRewardPercentage;\\n uint8 maxNumberOfSlashes; // frees slot when the number of slashing reaches this value\\n uint16 slashCriterion; // amount of proofs missed that lead to slashing\\n uint8 slashPercentage; // percentage of the collateral that is slashed\\n}\\n\\nstruct ProofConfig {\\n uint256 period; // proofs requirements are calculated per period (in seconds)\\n uint256 timeout; // mark proofs as missing before the timeout (in seconds)\\n uint8 downtime; // ignore this much recent blocks for proof requirements\\n string zkeyHash; // hash of the zkey file which is linked to the verifier\\n // Ensures the pointer does not remain in downtime for many consecutive\\n // periods. For each period increase, move the pointer `pointerProduct`\\n // blocks. Should be a prime number to ensure there are no cycles.\\n uint8 downtimeProduct;\\n}\\n\\nstruct SlotReservationsConfig {\\n // Number of allowed reservations per slot\\n uint8 maxReservations;\\n}\\n\",\"keccak256\":\"0x76c7a6183e1031680ffc3e3a0bd52d257d43ee7311aebdd542949894dfddf9ac\",\"license\":\"MIT\"},\"contracts/Endian.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\ncontract Endian {\\n /// reverses byte order to allow conversion between little endian and big\\n /// endian integers\\n function _byteSwap(bytes32 input) internal pure returns (bytes32 output) {\\n output = output | bytes1(input);\\n for (uint i = 1; i < 32; i++) {\\n output = output >> 8;\\n output = output | bytes1(input << (i * 8));\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd6acc2a19aaedc1b903681fedf6e302aabdd33695dee215e21b5190a83d0769e\",\"license\":\"MIT\"},\"contracts/Groth16.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nstruct G1Point {\\n uint256 x;\\n uint256 y;\\n}\\n\\n// A field element F_{p^2} encoded as `real + i * imag`.\\n// We chose to not represent this as an array of 2 numbers, because both Circom\\n// and Ethereum EIP-197 encode to an array, but with conflicting encodings.\\nstruct Fp2Element {\\n uint256 real;\\n uint256 imag;\\n}\\n\\nstruct G2Point {\\n Fp2Element x;\\n Fp2Element y;\\n}\\n\\nstruct Groth16Proof {\\n G1Point a;\\n G2Point b;\\n G1Point c;\\n}\\n\\ninterface IGroth16Verifier {\\n function verify(\\n Groth16Proof calldata proof,\\n uint256[] calldata pubSignals\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xe1c7a8730cf718c9b69052c81ca3241d7f61c25f3d7944962077d768bf601baf\",\"license\":\"MIT\"},\"contracts/Marketplace.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"./Configuration.sol\\\";\\nimport \\\"./Requests.sol\\\";\\nimport \\\"./Proofs.sol\\\";\\nimport \\\"./SlotReservations.sol\\\";\\nimport \\\"./StateRetrieval.sol\\\";\\nimport \\\"./Endian.sol\\\";\\nimport \\\"./Groth16.sol\\\";\\n\\ncontract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using Requests for Request;\\n\\n IERC20 private immutable _token;\\n MarketplaceConfig private _config;\\n\\n mapping(RequestId => Request) private _requests;\\n mapping(RequestId => RequestContext) internal _requestContexts;\\n mapping(SlotId => Slot) internal _slots;\\n\\n MarketplaceTotals internal _marketplaceTotals;\\n\\n struct RequestContext {\\n RequestState state;\\n uint256 slotsFilled;\\n /// @notice Tracks how much funds should be returned when Request expires to the Request creator\\n /// @dev The sum is deducted every time a host fills a Slot by precalculated amount that he should receive if the Request expires\\n uint256 expiryFundsWithdraw;\\n uint256 startedAt;\\n uint256 endsAt;\\n uint256 expiresAt;\\n }\\n\\n struct Slot {\\n SlotState state;\\n RequestId requestId;\\n /// @notice Timestamp that signals when slot was filled\\n /// @dev Used for partial payouts when Requests expires and Hosts are paid out only the time they host the content.\\n uint256 filledAt;\\n uint256 slotIndex;\\n /// @notice Tracks the current amount of host's collateral that is to be payed out at the end of Slot's lifespan.\\n /// @dev When Slot is filled, the collateral is collected in amount of request.ask.collateral\\n /// @dev When Host is slashed for missing a proof the slashed amount is reflected in this variable\\n uint256 currentCollateral;\\n address host; // address used for collateral interactions and identifying hosts\\n }\\n\\n struct ActiveSlot {\\n Request request;\\n uint256 slotIndex;\\n }\\n\\n constructor(\\n MarketplaceConfig memory configuration,\\n IERC20 token_,\\n IGroth16Verifier verifier\\n )\\n SlotReservations(configuration.reservations)\\n Proofs(configuration.proofs, verifier)\\n {\\n _token = token_;\\n\\n require(\\n configuration.collateral.repairRewardPercentage <= 100,\\n \\\"Must be less than 100\\\"\\n );\\n require(\\n configuration.collateral.slashPercentage <= 100,\\n \\\"Must be less than 100\\\"\\n );\\n require(\\n configuration.collateral.maxNumberOfSlashes *\\n configuration.collateral.slashPercentage <=\\n 100,\\n \\\"Maximum slashing exceeds 100%\\\"\\n );\\n _config = configuration;\\n }\\n\\n function config() public view returns (MarketplaceConfig memory) {\\n return _config;\\n }\\n\\n function token() public view returns (IERC20) {\\n return _token;\\n }\\n\\n function requestStorage(Request calldata request) public {\\n require(request.client == msg.sender, \\\"Invalid client address\\\");\\n\\n RequestId id = request.id();\\n require(_requests[id].client == address(0), \\\"Request already exists\\\");\\n require(\\n request.expiry > 0 && request.expiry < request.ask.duration,\\n \\\"Expiry not in range\\\"\\n );\\n require(request.ask.slots > 0, \\\"Insufficient slots\\\");\\n require(\\n request.ask.maxSlotLoss <= request.ask.slots,\\n \\\"maxSlotLoss exceeds slots\\\"\\n );\\n\\n _requests[id] = request;\\n _requestContexts[id].endsAt = block.timestamp + request.ask.duration;\\n _requestContexts[id].expiresAt = block.timestamp + request.expiry;\\n\\n _addToMyRequests(request.client, id);\\n\\n uint256 amount = request.price();\\n _requestContexts[id].expiryFundsWithdraw = amount;\\n _marketplaceTotals.received += amount;\\n _transferFrom(msg.sender, amount);\\n\\n emit StorageRequested(id, request.ask, _requestContexts[id].expiresAt);\\n }\\n\\n /**\\n * @notice Fills a slot. Reverts if an invalid proof of the slot data is\\n provided.\\n * @param requestId RequestId identifying the request containing the slot to\\n fill.\\n * @param slotIndex Index of the slot in the request.\\n * @param proof Groth16 proof procing possession of the slot data.\\n */\\n function fillSlot(\\n RequestId requestId,\\n uint256 slotIndex,\\n Groth16Proof calldata proof\\n ) public requestIsKnown(requestId) {\\n Request storage request = _requests[requestId];\\n require(slotIndex < request.ask.slots, \\\"Invalid slot\\\");\\n\\n SlotId slotId = Requests.slotId(requestId, slotIndex);\\n Slot storage slot = _slots[slotId];\\n slot.requestId = requestId;\\n slot.slotIndex = slotIndex;\\n\\n require(slotState(slotId) == SlotState.Free, \\\"Slot is not free\\\");\\n\\n _startRequiringProofs(slotId, request.ask.proofProbability);\\n submitProof(slotId, proof);\\n\\n slot.host = msg.sender;\\n slot.state = SlotState.Filled;\\n slot.filledAt = block.timestamp;\\n RequestContext storage context = _requestContexts[requestId];\\n context.slotsFilled += 1;\\n context.expiryFundsWithdraw -= _expiryPayoutAmount(\\n requestId,\\n block.timestamp\\n );\\n\\n // Collect collateral\\n uint256 collateralAmount = request.ask.collateral;\\n _transferFrom(msg.sender, collateralAmount);\\n _marketplaceTotals.received += collateralAmount;\\n slot.currentCollateral = collateralAmount;\\n\\n _addToMySlots(slot.host, slotId);\\n\\n emit SlotFilled(requestId, slotIndex);\\n if (context.slotsFilled == request.ask.slots) {\\n context.state = RequestState.Started;\\n context.startedAt = block.timestamp;\\n emit RequestFulfilled(requestId);\\n }\\n }\\n\\n /**\\n * @notice Frees a slot, paying out rewards and returning collateral for\\n finished or cancelled requests to the host that has filled the slot.\\n * @param slotId id of the slot to free\\n * @dev The host that filled the slot must have initiated the transaction\\n (msg.sender). This overload allows `rewardRecipient` and\\n `collateralRecipient` to be optional.\\n */\\n function freeSlot(SlotId slotId) public slotIsNotFree(slotId) {\\n return freeSlot(slotId, msg.sender, msg.sender);\\n }\\n\\n /**\\n * @notice Frees a slot, paying out rewards and returning collateral for\\n finished or cancelled requests.\\n * @param slotId id of the slot to free\\n * @param rewardRecipient address to send rewards to\\n * @param collateralRecipient address to refund collateral to\\n */\\n function freeSlot(\\n SlotId slotId,\\n address rewardRecipient,\\n address collateralRecipient\\n ) public slotIsNotFree(slotId) {\\n Slot storage slot = _slots[slotId];\\n require(slot.host == msg.sender, \\\"Slot filled by other host\\\");\\n SlotState state = slotState(slotId);\\n require(state != SlotState.Paid, \\\"Already paid\\\");\\n\\n if (state == SlotState.Finished) {\\n _payoutSlot(slot.requestId, slotId, rewardRecipient, collateralRecipient);\\n } else if (state == SlotState.Cancelled) {\\n _payoutCancelledSlot(\\n slot.requestId,\\n slotId,\\n rewardRecipient,\\n collateralRecipient\\n );\\n } else if (state == SlotState.Failed) {\\n _removeFromMySlots(msg.sender, slotId);\\n } else if (state == SlotState.Filled) {\\n // free slot without returning collateral, effectively a 100% slash\\n _forciblyFreeSlot(slotId);\\n }\\n }\\n\\n function _challengeToFieldElement(\\n bytes32 challenge\\n ) internal pure returns (uint256) {\\n // use only 31 bytes of the challenge to ensure that it fits into the field\\n bytes32 truncated = bytes32(bytes31(challenge));\\n // convert from little endian to big endian\\n bytes32 bigEndian = _byteSwap(truncated);\\n // convert bytes to integer\\n return uint256(bigEndian);\\n }\\n\\n function _merkleRootToFieldElement(\\n bytes32 merkleRoot\\n ) internal pure returns (uint256) {\\n // convert from little endian to big endian\\n bytes32 bigEndian = _byteSwap(merkleRoot);\\n // convert bytes to integer\\n return uint256(bigEndian);\\n }\\n\\n function submitProof(\\n SlotId id,\\n Groth16Proof calldata proof\\n ) public requestIsKnown(_slots[id].requestId) {\\n Slot storage slot = _slots[id];\\n Request storage request = _requests[slot.requestId];\\n uint256[] memory pubSignals = new uint256[](3);\\n pubSignals[0] = _challengeToFieldElement(getChallenge(id));\\n pubSignals[1] = _merkleRootToFieldElement(request.content.merkleRoot);\\n pubSignals[2] = slot.slotIndex;\\n _proofReceived(id, proof, pubSignals);\\n }\\n\\n function markProofAsMissing(SlotId slotId, Period period) public {\\n require(slotState(slotId) == SlotState.Filled, \\\"Slot not accepting proofs\\\");\\n _markProofAsMissing(slotId, period);\\n Slot storage slot = _slots[slotId];\\n Request storage request = _requests[slot.requestId];\\n\\n // TODO: Reward for validator that calls this function\\n\\n if (missingProofs(slotId) % _config.collateral.slashCriterion == 0) {\\n uint256 slashedAmount = (request.ask.collateral *\\n _config.collateral.slashPercentage) / 100;\\n slot.currentCollateral -= slashedAmount;\\n if (\\n missingProofs(slotId) / _config.collateral.slashCriterion >=\\n _config.collateral.maxNumberOfSlashes\\n ) {\\n // When the number of slashings is at or above the allowed amount,\\n // free the slot.\\n _forciblyFreeSlot(slotId);\\n }\\n }\\n }\\n\\n /**\\n * @notice Abandons the slot without returning collateral, effectively slashing the\\n entire collateral.\\n * @param slotId SlotId of the slot to free.\\n * @dev _slots[slotId] is deleted, resetting _slots[slotId].currentCollateral\\n to 0.\\n */\\n function _forciblyFreeSlot(SlotId slotId) internal {\\n Slot storage slot = _slots[slotId];\\n RequestId requestId = slot.requestId;\\n RequestContext storage context = _requestContexts[requestId];\\n\\n _removeFromMySlots(slot.host, slotId);\\n\\n uint256 slotIndex = slot.slotIndex;\\n delete _slots[slotId];\\n context.slotsFilled -= 1;\\n emit SlotFreed(requestId, slotIndex);\\n _resetMissingProofs(slotId);\\n\\n Request storage request = _requests[requestId];\\n uint256 slotsLost = request.ask.slots - context.slotsFilled;\\n if (\\n slotsLost > request.ask.maxSlotLoss &&\\n context.state == RequestState.Started\\n ) {\\n context.state = RequestState.Failed;\\n context.endsAt = block.timestamp - 1;\\n emit RequestFailed(requestId);\\n\\n // TODO: send client remaining funds\\n }\\n }\\n\\n function _payoutSlot(\\n RequestId requestId,\\n SlotId slotId,\\n address rewardRecipient,\\n address collateralRecipient\\n ) private requestIsKnown(requestId) {\\n RequestContext storage context = _requestContexts[requestId];\\n Request storage request = _requests[requestId];\\n context.state = RequestState.Finished;\\n _removeFromMyRequests(request.client, requestId);\\n Slot storage slot = _slots[slotId];\\n\\n _removeFromMySlots(slot.host, slotId);\\n\\n uint256 payoutAmount = _requests[requestId].pricePerSlot();\\n uint256 collateralAmount = slot.currentCollateral;\\n _marketplaceTotals.sent += (payoutAmount + collateralAmount);\\n slot.state = SlotState.Paid;\\n assert(_token.transfer(rewardRecipient, payoutAmount));\\n assert(_token.transfer(collateralRecipient, collateralAmount));\\n }\\n\\n /**\\n * @notice Pays out a host for duration of time that the slot was filled, and\\n returns the collateral.\\n * @dev The payouts are sent to the rewardRecipient, and collateral is returned\\n to the host address.\\n * @param requestId RequestId of the request that contains the slot to be paid\\n out.\\n * @param slotId SlotId of the slot to be paid out.\\n */\\n function _payoutCancelledSlot(\\n RequestId requestId,\\n SlotId slotId,\\n address rewardRecipient,\\n address collateralRecipient\\n ) private requestIsKnown(requestId) {\\n Slot storage slot = _slots[slotId];\\n _removeFromMySlots(slot.host, slotId);\\n\\n uint256 payoutAmount = _expiryPayoutAmount(requestId, slot.filledAt);\\n uint256 collateralAmount = slot.currentCollateral;\\n _marketplaceTotals.sent += (payoutAmount + collateralAmount);\\n slot.state = SlotState.Paid;\\n assert(_token.transfer(rewardRecipient, payoutAmount));\\n assert(_token.transfer(collateralRecipient, collateralAmount));\\n }\\n\\n /**\\n * @notice Withdraws remaining storage request funds back to the client that\\n deposited them.\\n * @dev Request must be expired, must be in RequestStat e.New, and the\\n transaction must originate from the depositer address.\\n * @param requestId the id of the request\\n */\\n function withdrawFunds(RequestId requestId) public {\\n withdrawFunds(requestId, msg.sender);\\n }\\n\\n /**\\n * @notice Withdraws storage request funds to the provided address.\\n * @dev Request must be expired, must be in RequestState.New, and the\\n transaction must originate from the depositer address.\\n * @param requestId the id of the request\\n * @param withdrawRecipient address to return the remaining funds to\\n */\\n function withdrawFunds(\\n RequestId requestId,\\n address withdrawRecipient\\n ) public {\\n Request storage request = _requests[requestId];\\n require(\\n block.timestamp > requestExpiry(requestId),\\n \\\"Request not yet timed out\\\"\\n );\\n require(request.client == msg.sender, \\\"Invalid client address\\\");\\n RequestContext storage context = _requestContexts[requestId];\\n require(context.state == RequestState.New, \\\"Invalid state\\\");\\n\\n // Update request state to Cancelled. Handle in the withdraw transaction\\n // as there needs to be someone to pay for the gas to update the state\\n context.state = RequestState.Cancelled;\\n _removeFromMyRequests(request.client, requestId);\\n\\n emit RequestCancelled(requestId);\\n\\n uint256 amount = context.expiryFundsWithdraw;\\n _marketplaceTotals.sent += amount;\\n assert(_token.transfer(withdrawRecipient, amount));\\n }\\n\\n function getActiveSlot(\\n SlotId slotId\\n ) public view slotIsNotFree(slotId) returns (ActiveSlot memory) {\\n Slot storage slot = _slots[slotId];\\n ActiveSlot memory activeSlot;\\n activeSlot.request = _requests[slot.requestId];\\n activeSlot.slotIndex = slot.slotIndex;\\n return activeSlot;\\n }\\n\\n modifier requestIsKnown(RequestId requestId) {\\n require(_requests[requestId].client != address(0), \\\"Unknown request\\\");\\n _;\\n }\\n\\n function getRequest(\\n RequestId requestId\\n ) public view requestIsKnown(requestId) returns (Request memory) {\\n return _requests[requestId];\\n }\\n\\n modifier slotIsNotFree(SlotId slotId) {\\n require(_slots[slotId].state != SlotState.Free, \\\"Slot is free\\\");\\n _;\\n }\\n\\n function requestEnd(RequestId requestId) public view returns (uint256) {\\n uint256 end = _requestContexts[requestId].endsAt;\\n RequestState state = requestState(requestId);\\n if (state == RequestState.New || state == RequestState.Started) {\\n return end;\\n } else {\\n return Math.min(end, block.timestamp - 1);\\n }\\n }\\n\\n function requestExpiry(RequestId requestId) public view returns (uint256) {\\n return _requestContexts[requestId].expiresAt;\\n }\\n\\n /**\\n * @notice Calculates the amount that should be paid out to a host if a request\\n * expires based on when the host fills the slot\\n * @param requestId RequestId of the request used to calculate the payout\\n * amount.\\n * @param startingTimestamp timestamp indicating when a host filled a slot and\\n * started providing proofs.\\n */\\n function _expiryPayoutAmount(\\n RequestId requestId,\\n uint256 startingTimestamp\\n ) private view returns (uint256) {\\n Request storage request = _requests[requestId];\\n require(\\n startingTimestamp < requestExpiry(requestId),\\n \\\"Start not before expiry\\\"\\n );\\n\\n return (requestExpiry(requestId) - startingTimestamp) * request.ask.reward;\\n }\\n\\n function getHost(SlotId slotId) public view returns (address) {\\n return _slots[slotId].host;\\n }\\n\\n function requestState(\\n RequestId requestId\\n ) public view requestIsKnown(requestId) returns (RequestState) {\\n RequestContext storage context = _requestContexts[requestId];\\n if (\\n context.state == RequestState.New &&\\n block.timestamp > requestExpiry(requestId)\\n ) {\\n return RequestState.Cancelled;\\n } else if (\\n (context.state == RequestState.Started ||\\n context.state == RequestState.New) && block.timestamp > context.endsAt\\n ) {\\n return RequestState.Finished;\\n } else {\\n return context.state;\\n }\\n }\\n\\n function slotState(SlotId slotId) public view override returns (SlotState) {\\n Slot storage slot = _slots[slotId];\\n if (RequestId.unwrap(slot.requestId) == 0) {\\n return SlotState.Free;\\n }\\n RequestState reqState = requestState(slot.requestId);\\n if (slot.state == SlotState.Paid) {\\n return SlotState.Paid;\\n }\\n if (reqState == RequestState.Cancelled) {\\n return SlotState.Cancelled;\\n }\\n if (reqState == RequestState.Finished) {\\n return SlotState.Finished;\\n }\\n if (reqState == RequestState.Failed) {\\n return SlotState.Failed;\\n }\\n return slot.state;\\n }\\n\\n function _transferFrom(address sender, uint256 amount) internal {\\n address receiver = address(this);\\n require(_token.transferFrom(sender, receiver, amount), \\\"Transfer failed\\\");\\n }\\n\\n event StorageRequested(RequestId requestId, Ask ask, uint256 expiry);\\n event RequestFulfilled(RequestId indexed requestId);\\n event RequestFailed(RequestId indexed requestId);\\n event SlotFilled(RequestId indexed requestId, uint256 slotIndex);\\n event SlotFreed(RequestId indexed requestId, uint256 slotIndex);\\n event RequestCancelled(RequestId indexed requestId);\\n\\n struct MarketplaceTotals {\\n uint256 received;\\n uint256 sent;\\n }\\n}\\n\",\"keccak256\":\"0x46180121bfac569b9e3b4ac04fc4c260900d638d66489354215d20b983a8cb59\",\"license\":\"MIT\"},\"contracts/Periods.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\ncontract Periods {\\n type Period is uint256;\\n\\n uint256 internal immutable _secondsPerPeriod;\\n\\n constructor(uint256 secondsPerPeriod) {\\n _secondsPerPeriod = secondsPerPeriod;\\n }\\n\\n function _periodOf(uint256 timestamp) internal view returns (Period) {\\n return Period.wrap(timestamp / _secondsPerPeriod);\\n }\\n\\n function _blockPeriod() internal view returns (Period) {\\n return _periodOf(block.timestamp);\\n }\\n\\n function _nextPeriod(Period period) internal pure returns (Period) {\\n return Period.wrap(Period.unwrap(period) + 1);\\n }\\n\\n function _periodStart(Period period) internal view returns (uint256) {\\n return Period.unwrap(period) * _secondsPerPeriod;\\n }\\n\\n function _periodEnd(Period period) internal view returns (uint256) {\\n return _periodStart(_nextPeriod(period));\\n }\\n\\n function _isBefore(Period a, Period b) internal pure returns (bool) {\\n return Period.unwrap(a) < Period.unwrap(b);\\n }\\n\\n function _isAfter(Period a, Period b) internal pure returns (bool) {\\n return _isBefore(b, a);\\n }\\n}\\n\",\"keccak256\":\"0xd70cb0ff823e635a1f52f39d8d32451d2d17d2588dc0a894d28432af72f878ff\",\"license\":\"MIT\"},\"contracts/Proofs.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"./Configuration.sol\\\";\\nimport \\\"./Requests.sol\\\";\\nimport \\\"./Periods.sol\\\";\\nimport \\\"./Groth16.sol\\\";\\n\\n/**\\n * @title Proofs\\n * @notice Abstract contract that handles proofs tracking, validation and reporting functionality\\n */\\nabstract contract Proofs is Periods {\\n ProofConfig private _config;\\n IGroth16Verifier private _verifier;\\n\\n /**\\n * Creation of the contract requires at least 256 mined blocks!\\n * @param config Proving configuration\\n */\\n constructor(\\n ProofConfig memory config,\\n IGroth16Verifier verifier\\n ) Periods(config.period) {\\n require(block.number > 256, \\\"Insufficient block height\\\");\\n _config = config;\\n _verifier = verifier;\\n }\\n\\n mapping(SlotId => uint256) private _slotStarts; // TODO: Should be smaller than uint256\\n mapping(SlotId => uint256) private _probabilities;\\n mapping(SlotId => uint256) private _missed; // TODO: Should be smaller than uint256\\n mapping(SlotId => mapping(Period => bool)) private _received;\\n mapping(SlotId => mapping(Period => bool)) private _missing;\\n\\n function slotState(SlotId id) public view virtual returns (SlotState);\\n\\n /**\\n * @return Number of missed proofs since Slot was Filled\\n */\\n function missingProofs(SlotId slotId) public view returns (uint256) {\\n return _missed[slotId];\\n }\\n\\n /**\\n * @param slotId Slot's ID for which the proofs should be reset\\n * @notice Resets the missing proofs counter to zero\\n */\\n function _resetMissingProofs(SlotId slotId) internal {\\n _missed[slotId] = 0;\\n }\\n\\n /**\\n * @param id Slot's ID for which the proofs should be started to require\\n * @param probability Integer which specifies the probability of how often the proofs will be required. Lower number means higher probability.\\n * @notice Notes down the block's timestamp as Slot's starting time for requiring proofs\\n * and saves the required probability.\\n */\\n function _startRequiringProofs(SlotId id, uint256 probability) internal {\\n _slotStarts[id] = block.timestamp;\\n _probabilities[id] = probability;\\n }\\n\\n /**\\n * @param id Slot's ID for which the pointer should be calculated\\n * @param period Period for which the pointer should be calculated\\n * @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\\n * @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\\n */\\n function _getPointer(SlotId id, Period period) internal view returns (uint8) {\\n uint256 blockNumber = block.number % 256;\\n uint256 periodNumber = (Period.unwrap(period) * _config.downtimeProduct) %\\n 256;\\n uint256 idOffset = uint256(SlotId.unwrap(id)) % 256;\\n uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;\\n return uint8(pointer);\\n }\\n\\n /**\\n * @param id Slot's ID for which the pointer should be calculated\\n * @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\\n * @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\\n */\\n function getPointer(SlotId id) public view returns (uint8) {\\n return _getPointer(id, _blockPeriod());\\n }\\n\\n /**\\n * @param pointer Integer [0-255] that indicates an offset of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\\n * @return Challenge that should be used for generation of proofs\\n */\\n function _getChallenge(uint8 pointer) internal view returns (bytes32) {\\n bytes32 hash = blockhash(block.number - 1 - pointer);\\n assert(uint256(hash) != 0);\\n return keccak256(abi.encode(hash));\\n }\\n\\n /**\\n * @param id Slot's ID for which the challenge should be calculated\\n * @param period Period for which the challenge should be calculated\\n * @return Challenge that should be used for generation of proofs\\n */\\n function _getChallenge(\\n SlotId id,\\n Period period\\n ) internal view returns (bytes32) {\\n return _getChallenge(_getPointer(id, period));\\n }\\n\\n /**\\n * @param id Slot's ID for which the challenge should be calculated\\n * @return Challenge for current Period that should be used for generation of proofs\\n */\\n function getChallenge(SlotId id) public view returns (bytes32) {\\n return _getChallenge(id, _blockPeriod());\\n }\\n\\n /**\\n * @param id Slot's ID for which the requirements are gathered. If the Slot's state is other than Filled, `false` is always returned.\\n * @param period Period for which the requirements are gathered.\\n */\\n function _getProofRequirement(\\n SlotId id,\\n Period period\\n ) internal view returns (bool isRequired, uint8 pointer) {\\n SlotState state = slotState(id);\\n Period start = _periodOf(_slotStarts[id]);\\n if (state != SlotState.Filled || !_isAfter(period, start)) {\\n return (false, 0);\\n }\\n pointer = _getPointer(id, period);\\n bytes32 challenge = _getChallenge(pointer);\\n\\n /// Scaling of the probability according the downtime configuration\\n /// See: https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime\\n uint256 probability = (_probabilities[id] * (256 - _config.downtime)) / 256;\\n isRequired = probability == 0 || uint256(challenge) % probability == 0;\\n }\\n\\n /**\\n * See isProofRequired\\n */\\n function _isProofRequired(\\n SlotId id,\\n Period period\\n ) internal view returns (bool) {\\n bool isRequired;\\n uint8 pointer;\\n (isRequired, pointer) = _getProofRequirement(id, period);\\n return isRequired && pointer >= _config.downtime;\\n }\\n\\n /**\\n * @param id Slot's ID for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\\n * @return bool indicating if proof is required for current period\\n */\\n function isProofRequired(SlotId id) public view returns (bool) {\\n return _isProofRequired(id, _blockPeriod());\\n }\\n\\n /**\\n * Proof Downtime specifies part of the Period when the proof is not required even\\n * if the proof should be required. This function returns true if the pointer is\\n * in downtime (hence no proof required now) and at the same time the proof\\n * will be required later on in the Period.\\n *\\n * @dev for more info about downtime see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime)\\n * @param id SlotId for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\\n * @return bool\\n */\\n function willProofBeRequired(SlotId id) public view returns (bool) {\\n bool isRequired;\\n uint8 pointer;\\n (isRequired, pointer) = _getProofRequirement(id, _blockPeriod());\\n return isRequired && pointer < _config.downtime;\\n }\\n\\n /**\\n * Function used for submitting and verification of the proofs.\\n *\\n * @dev Reverts when proof is invalid or had been already submitted.\\n * @dev Emits ProofSubmitted event.\\n * @param id Slot's ID for which the proof requirements should be checked\\n * @param proof Groth16 proof\\n * @param pubSignals Proofs public input\\n */\\n function _proofReceived(\\n SlotId id,\\n Groth16Proof calldata proof,\\n uint[] memory pubSignals\\n ) internal {\\n require(!_received[id][_blockPeriod()], \\\"Proof already submitted\\\");\\n require(_verifier.verify(proof, pubSignals), \\\"Invalid proof\\\");\\n _received[id][_blockPeriod()] = true;\\n emit ProofSubmitted(id);\\n }\\n\\n /**\\n * Function used to mark proof as missing.\\n *\\n * @param id Slot's ID for which the proof is missing\\n * @param missedPeriod Period for which the proof was missed\\n * @dev Reverts when:\\n * - missedPeriod has not ended yet ended\\n * - missing proof was time-barred\\n * - proof was submitted\\n * - proof was not required for missedPeriod period\\n * - proof was already marked as missing\\n */\\n function _markProofAsMissing(SlotId id, Period missedPeriod) internal {\\n uint256 end = _periodEnd(missedPeriod);\\n require(end < block.timestamp, \\\"Period has not ended yet\\\");\\n require(block.timestamp < end + _config.timeout, \\\"Validation timed out\\\");\\n require(!_received[id][missedPeriod], \\\"Proof was submitted, not missing\\\");\\n require(_isProofRequired(id, missedPeriod), \\\"Proof was not required\\\");\\n require(!_missing[id][missedPeriod], \\\"Proof already marked as missing\\\");\\n _missing[id][missedPeriod] = true;\\n _missed[id] += 1;\\n }\\n\\n event ProofSubmitted(SlotId id);\\n}\\n\",\"keccak256\":\"0x742a491cf61d941b39bc2694dd039917438276f881849922e51fb08360d32ef0\",\"license\":\"MIT\"},\"contracts/Requests.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\ntype RequestId is bytes32;\\ntype SlotId is bytes32;\\n\\nstruct Request {\\n address client;\\n Ask ask;\\n Content content;\\n uint256 expiry; // amount of seconds since start of the request at which this request expires\\n bytes32 nonce; // random nonce to differentiate between similar requests\\n}\\n\\nstruct Ask {\\n uint64 slots; // the number of requested slots\\n uint256 slotSize; // amount of storage per slot (in number of bytes)\\n uint256 duration; // how long content should be stored (in seconds)\\n uint256 proofProbability; // how often storage proofs are required\\n uint256 reward; // amount of tokens paid per second per slot to hosts\\n uint256 collateral; // amount of tokens required to be deposited by the hosts in order to fill the slot\\n uint64 maxSlotLoss; // Max slots that can be lost without data considered to be lost\\n}\\n\\nstruct Content {\\n string cid; // content id, used to download the dataset\\n bytes32 merkleRoot; // merkle root of the dataset, used to verify storage proofs\\n}\\n\\nenum RequestState {\\n New, // [default] waiting to fill slots\\n Started, // all slots filled, accepting regular proofs\\n Cancelled, // not enough slots filled before expiry\\n Finished, // successfully completed\\n Failed // too many nodes have failed to provide proofs, data lost\\n}\\n\\nenum SlotState {\\n Free, // [default] not filled yet, or host has vacated the slot\\n Filled, // host has filled slot\\n Finished, // successfully completed\\n Failed, // the request has failed\\n Paid, // host has been paid\\n Cancelled // when request was cancelled then slot is cancelled as well\\n}\\n\\nlibrary Requests {\\n function id(Request memory request) internal pure returns (RequestId) {\\n return RequestId.wrap(keccak256(abi.encode(request)));\\n }\\n\\n function slotId(\\n RequestId requestId,\\n uint256 slotIndex\\n ) internal pure returns (SlotId) {\\n return SlotId.wrap(keccak256(abi.encode(requestId, slotIndex)));\\n }\\n\\n function toRequestIds(\\n bytes32[] memory ids\\n ) internal pure returns (RequestId[] memory result) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := ids\\n }\\n }\\n\\n function toSlotIds(\\n bytes32[] memory ids\\n ) internal pure returns (SlotId[] memory result) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := ids\\n }\\n }\\n\\n function pricePerSlot(\\n Request memory request\\n ) internal pure returns (uint256) {\\n return request.ask.duration * request.ask.reward;\\n }\\n\\n function price(Request memory request) internal pure returns (uint256) {\\n return request.ask.slots * pricePerSlot(request);\\n }\\n}\\n\",\"keccak256\":\"0xf598ab550bb20660bfc6a937045d92534c4f8f41676337c221d593c06fe09ba1\",\"license\":\"MIT\"},\"contracts/SlotReservations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"./Requests.sol\\\";\\nimport \\\"./Configuration.sol\\\";\\n\\ncontract SlotReservations {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n mapping(SlotId => EnumerableSet.AddressSet) internal _reservations;\\n SlotReservationsConfig private _config;\\n\\n constructor(SlotReservationsConfig memory config) {\\n _config = config;\\n }\\n\\n function reserveSlot(RequestId requestId, uint256 slotIndex) public {\\n require(canReserveSlot(requestId, slotIndex), \\\"Reservation not allowed\\\");\\n\\n SlotId slotId = Requests.slotId(requestId, slotIndex);\\n _reservations[slotId].add(msg.sender);\\n\\n if (_reservations[slotId].length() == _config.maxReservations) {\\n emit SlotReservationsFull(requestId, slotIndex);\\n }\\n }\\n\\n function canReserveSlot(\\n RequestId requestId,\\n uint256 slotIndex\\n ) public view returns (bool) {\\n address host = msg.sender;\\n SlotId slotId = Requests.slotId(requestId, slotIndex);\\n return\\n // TODO: add in check for address inside of expanding window\\n (_reservations[slotId].length() < _config.maxReservations) &&\\n (!_reservations[slotId].contains(host));\\n }\\n\\n event SlotReservationsFull(RequestId indexed requestId, uint256 slotIndex);\\n}\\n\",\"keccak256\":\"0x8931bef1b8c9ed44b4f19257e2e43d91051ef8c5ed2e4e0fd82c0547451a3cf9\",\"license\":\"MIT\"},\"contracts/StateRetrieval.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"./Requests.sol\\\";\\n\\ncontract StateRetrieval {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using Requests for bytes32[];\\n\\n mapping(address => EnumerableSet.Bytes32Set) private _requestsPerClient;\\n mapping(address => EnumerableSet.Bytes32Set) private _slotsPerHost;\\n\\n function myRequests() public view returns (RequestId[] memory) {\\n return _requestsPerClient[msg.sender].values().toRequestIds();\\n }\\n\\n function mySlots() public view returns (SlotId[] memory) {\\n return _slotsPerHost[msg.sender].values().toSlotIds();\\n }\\n\\n function _hasSlots(address host) internal view returns (bool) {\\n return _slotsPerHost[host].length() > 0;\\n }\\n\\n function _addToMyRequests(address client, RequestId requestId) internal {\\n _requestsPerClient[client].add(RequestId.unwrap(requestId));\\n }\\n\\n function _addToMySlots(address host, SlotId slotId) internal {\\n _slotsPerHost[host].add(SlotId.unwrap(slotId));\\n }\\n\\n function _removeFromMyRequests(address client, RequestId requestId) internal {\\n _requestsPerClient[client].remove(RequestId.unwrap(requestId));\\n }\\n\\n function _removeFromMySlots(address host, SlotId slotId) internal {\\n _slotsPerHost[host].remove(SlotId.unwrap(slotId));\\n }\\n}\\n\",\"keccak256\":\"0x734c58b16cd1bf57aed889162708140b4a093698963c5cf688308f7d8b2d5deb\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60c06040523480156200001157600080fd5b50604051620043a8380380620043a8833981016040819052620000349162000571565b602083015180516040850151516001805460ff191660ff909216919091179055608052816101004311620000af5760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e7420626c6f636b206865696768740000000000000060448201526064015b60405180910390fd5b81516002908155602083015160035560408301516004805460ff191660ff9092169190911790556060830151839190600590620000ed908262000724565b50608091909101516004909101805460ff191660ff928316179055600780546001600160a01b0319166001600160a01b0393841617905590841660a0528451516064911611159050620001835760405162461bcd60e51b815260206004820152601560248201527f4d757374206265206c657373207468616e2031303000000000000000000000006044820152606401620000a6565b606483600001516060015160ff161115620001e15760405162461bcd60e51b815260206004820152601560248201527f4d757374206265206c657373207468616e2031303000000000000000000000006044820152606401620000a6565b82516060810151602090910151606491620001fc91620007f0565b60ff1611156200024f5760405162461bcd60e51b815260206004820152601d60248201527f4d6178696d756d20736c617368696e67206578636565647320313030250000006044820152606401620000a6565b82518051600f805460208085015160408087015160609788015160ff9081166401000000000260ff60201b1961ffff90931662010000029290921664ffffff0000199482166101000261ffff199097169882169890981795909517929092169590951717835580880151805160109081559181015160115593840151601280549190931660ff19919091161790915592820151869391929190601390620002f7908262000724565b50608091909101516004909101805460ff1990811660ff938416179091556040939093015151600692909201805490931691161790555062000822915050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171562000372576200037262000337565b60405290565b604051606081016001600160401b038111828210171562000372576200037262000337565b604051608081016001600160401b038111828210171562000372576200037262000337565b604051601f8201601f191681016001600160401b0381118282101715620003ed57620003ed62000337565b604052919050565b805160ff811681146200040757600080fd5b919050565b600060a082840312156200041f57600080fd5b620004296200034d565b905081518152602080830151818301526200044760408401620003f5565b604083015260608301516001600160401b03808211156200046757600080fd5b818501915085601f8301126200047c57600080fd5b81518181111562000491576200049162000337565b620004a5601f8201601f19168501620003c2565b91508082528684828501011115620004bc57600080fd5b60005b81811015620004dc578381018501518382018601528401620004bf565b50600084828401015250806060850152505050620004fd60808301620003f5565b608082015292915050565b6000602082840312156200051b57600080fd5b604051602081016001600160401b038111828210171562000540576200054062000337565b6040529050806200055183620003f5565b905292915050565b80516001600160a01b03811681146200040757600080fd5b6000806000606084860312156200058757600080fd5b83516001600160401b03808211156200059f57600080fd5b9085019081870360c0811215620005b557600080fd5b620005bf62000378565b6080821215620005ce57600080fd5b620005d86200039d565b9150620005e584620003f5565b8252620005f560208501620003f5565b6020830152604084015161ffff811681146200061057600080fd5b60408301526200062360608501620003f5565b6060830152908152608083015190828211156200063f57600080fd5b6200064d898386016200040c565b6020820152620006618960a0860162000508565b604082015295506200067a925050506020850162000559565b91506200068a6040850162000559565b90509250925092565b600181811c90821680620006a857607f821691505b602082108103620006c957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200071f576000816000526020600020601f850160051c81016020861015620006fa5750805b601f850160051c820191505b818110156200071b5782815560010162000706565b5050505b505050565b81516001600160401b0381111562000740576200074062000337565b620007588162000751845462000693565b84620006cf565b602080601f831160018114620007905760008415620007775750858301515b600019600386901b1c1916600185901b1785556200071b565b600085815260208120601f198616915b82811015620007c157888601518255948401946001909101908401620007a0565b5085821015620007e05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60ff81811683821602908116908181146200081b57634e487b7160e01b600052601160045260246000fd5b5092915050565b60805160a051613b2f62000879600039600081816104420152818161185b01528181612219015281816122b80152818161242d015281816124cc0152612715015260008181612bde0152612da40152613b2f6000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806379502c55116100ee578063be5cdc4811610097578063e8aa0a0711610071578063e8aa0a07146103ed578063f752196b14610400578063fb1e61ca14610420578063fc0c546a1461044057600080fd5b8063be5cdc48146103a7578063c0cc4add146103c7578063c5d43351146103da57600080fd5b8063a3a0807e116100c8578063a3a0807e14610361578063a6af384b14610374578063b396dc791461038757600080fd5b806379502c55146103315780639777b72c14610346578063a29c29a41461034e57600080fd5b80634641dce61161015b5780635da73835116101355780635da73835146102b257806362d48e13146102c75780636b00c8cf146102da5780636e2b54ee1461031e57600080fd5b80634641dce6146102575780634802f44b1461027c57806359cc89ed1461029f57600080fd5b80630aefaabe1161018c5780630aefaabe1461020e578063329b5a0b14610221578063458d2bf11461024457600080fd5b806302fa8e65146101b357806305b90773146101d957806308695fcd146101f9575b600080fd5b6101c66101c1366004612f8b565b610466565b6040519081526020015b60405180910390f35b6101ec6101e7366004612f8b565b6104dd565b6040516101d09190612fba565b61020c610207366004612fd4565b6105ef565b005b61020c61021c36600461300b565b610745565b6101c661022f366004612f8b565b60009081526017602052604090206005015490565b6101c6610252366004612f8b565b610922565b61026a610265366004612f8b565b61093b565b60405160ff90911681526020016101d0565b61028f61028a366004612fd4565b61094e565b60405190151581526020016101d0565b61020c6102ad366004613060565b6109c9565b6102ba610ccd565b6040516101d09190613097565b61020c6102d5366004612fd4565b610cf4565b6103066102e8366004612f8b565b6000908152601860205260409020600501546001600160a01b031690565b6040516001600160a01b0390911681526020016101d0565b61020c61032c366004612f8b565b610df1565b610339610dfe565b6040516101d09190613121565b6102ba610fb2565b61020c61035c366004612f8b565b610fd1565b61028f61036f366004612f8b565b611041565b61020c6103823660046131ca565b611076565b61039a610395366004612f8b565b6113cb565b6040516101d091906132d3565b6103ba6103b5366004612f8b565b6115b4565b6040516101d09190613305565b61028f6103d5366004612f8b565b611682565b61020c6103e8366004613319565b611695565b61020c6103fb366004613349565b6118d4565b6101c661040e366004612f8b565b6000908152600a602052604090205490565b61043361042e366004612f8b565b611a09565b6040516101d09190613377565b7f0000000000000000000000000000000000000000000000000000000000000000610306565b60008181526017602052604081206004015481610482846104dd565b9050600081600481111561049857610498612fa4565b14806104b5575060018160048111156104b3576104b3612fa4565b145b156104c1575092915050565b6104d5826104d06001426133a0565b611bc0565b949350505050565b60008181526016602052604081205482906001600160a01b031661053a5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b60448201526064015b60405180910390fd5b600083815260176020526040812090815460ff16600481111561055f5761055f612fa4565b14801561057c575060008481526017602052604090206005015442115b1561058b5760029250506105e9565b6001815460ff1660048111156105a3576105a3612fa4565b14806105c457506000815460ff1660048111156105c2576105c2612fa4565b145b80156105d35750806004015442115b156105e25760039250506105e9565b5460ff1691505b50919050565b60016105fa836115b4565b600581111561060b5761060b612fa4565b146106585760405162461bcd60e51b815260206004820152601960248201527f536c6f74206e6f7420616363657074696e672070726f6f6673000000000000006044820152606401610531565b6106628282611bd8565b6000828152601860209081526040808320600181015484526016909252909120600f5461ffff62010000909104166106a6856000908152600a602052604090205490565b6106b091906133c9565b60000361073f57600f5460068201546000916064916106da91640100000000900460ff16906133dd565b6106e491906133f4565b9050808360040160008282546106fa91906133a0565b9091555050600f546000868152600a6020526040902054610100820460ff169162010000900461ffff169061072f91906133f4565b1061073d5761073d85611e05565b505b50505050565b826000808281526018602052604090205460ff16600581111561076a5761076a612fa4565b036107a65760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b600084815260186020526040902060058101546001600160a01b031633146108105760405162461bcd60e51b815260206004820152601960248201527f536c6f742066696c6c6564206279206f7468657220686f7374000000000000006044820152606401610531565b600061081b866115b4565b9050600481600581111561083157610831612fa4565b0361087e5760405162461bcd60e51b815260206004820152600c60248201527f416c7265616479207061696400000000000000000000000000000000000000006044820152606401610531565b600281600581111561089257610892612fa4565b036108ac576108a78260010154878787611fab565b61091a565b60058160058111156108c0576108c0612fa4565b036108d5576108a7826001015487878761233d565b60038160058111156108e9576108e9612fa4565b036108f8576108a7338761254f565b600181600581111561090c5761090c612fa4565b0361091a5761091a86611e05565b505050505050565b600061093582610930612571565b61257c565b92915050565b600061093582610949612571565b612590565b6040805160208082018590528183018490528251808303840181526060909201909252805191012060009033908290600154600082815260208190526040902091925060ff169061099e90612604565b1080156109c0575060008181526020819052604090206109be908361260e565b155b95945050505050565b60008381526016602052604090205483906001600160a01b0316610a215760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b6000848152601660205260409020600181015467ffffffffffffffff168410610a8c5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c696420736c6f7400000000000000000000000000000000000000006044820152606401610531565b6040805160208082018890528183018790528251808303840181526060909201909252805191012060009060008181526018602052604081206001810189905560038101889055919250610adf836115b4565b6005811115610af057610af0612fa4565b14610b3d5760405162461bcd60e51b815260206004820152601060248201527f536c6f74206973206e6f742066726565000000000000000000000000000000006044820152606401610531565b600483015460008381526008602090815260408083204290556009909152902055610b6882866118d4565b60058101805473ffffffffffffffffffffffffffffffffffffffff191633179055805460ff191660019081178255426002830155600088815260176020526040812080830180549193929091610bbf908490613408565b90915550610bcf90508842612630565b816002016000828254610be291906133a0565b90915550506006840154610bf633826126cd565b8060196000016000828254610c0b9190613408565b9091555050600483018190556005830154610c2f906001600160a01b0316856127d0565b887ff530852268993f91008f1a1e0b09b5c813acd4188481f1fa83c33c7182e814b489604051610c6191815260200190565b60405180910390a26001808601549083015467ffffffffffffffff9091169003610cc257815460ff1916600117825542600383015560405189907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a25b505050505050505050565b336000908152600e60205260409020606090610cef90610cec906127f2565b90565b905090565b610cfe828261094e565b610d4a5760405162461bcd60e51b815260206004820152601760248201527f5265736572766174696f6e206e6f7420616c6c6f7765640000000000000000006044820152606401610531565b60408051602080820185905281830184905282518083038401815260609092018352815191810191909120600081815291829052919020610d8b90336127ff565b50600154600082815260208190526040902060ff90911690610dac90612604565b03610dec57827f3bef2ebab8cc92e0edda5decf18232f0606a18405ef674b51ea9d1e0e3839b4183604051610de391815260200190565b60405180910390a25b505050565b610dfb8133611695565b50565b610e726040805160e081019091526000606082018181526080830182905260a0830182905260c0830191909152819081526040805160a08101825260008082526020828101829052928201819052606080830152608082015291019081526040805160208181019092526000815291015290565b6040805160e081018252600f805460ff808216606080860191825261010084048316608087015261ffff6201000085041660a080880191909152640100000000909404831660c087015290855285519283018652601080548452601154602085810191909152601254909316968401969096526013805495969495928701949291840191610eff9061341b565b80601f0160208091040260200160405190810160405280929190818152602001828054610f2b9061341b565b8015610f785780601f10610f4d57610100808354040283529160200191610f78565b820191906000526020600020905b815481529060010190602001808311610f5b57829003601f168201915b50505091835250506004919091015460ff908116602092830152918352604080518083019091526006949094015490911683520152919050565b336000908152600d60205260409020606090610cef90610cec906127f2565b806000808281526018602052604090205460ff166005811115610ff657610ff6612fa4565b036110325760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b61103d823333610745565b5050565b600080600061105784611052612571565b612814565b90925090508180156104d5575060045460ff9081169116109392505050565b33611084602083018361344f565b6001600160a01b0316146110da5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b60006110ed6110e8836135e1565b6128f7565b6000818152601660205260409020549091506001600160a01b0316156111555760405162461bcd60e51b815260206004820152601660248201527f5265717565737420616c726561647920657869737473000000000000000000006044820152606401610531565b600082610120013511801561117257506060820135610120830135105b6111be5760405162461bcd60e51b815260206004820152601360248201527f457870697279206e6f7420696e2072616e6765000000000000000000000000006044820152606401610531565b60006111d060408401602085016136d0565b67ffffffffffffffff16116112275760405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420736c6f747300000000000000000000000000006044820152606401610531565b61123760408301602084016136d0565b67ffffffffffffffff16611252610100840160e085016136d0565b67ffffffffffffffff1611156112aa5760405162461bcd60e51b815260206004820152601960248201527f6d6178536c6f744c6f7373206578636565647320736c6f7473000000000000006044820152606401610531565b600081815260166020526040902082906112c4828261385b565b506112d59050606083013542613408565b6000828152601760205260409020600401556112f661012083013542613408565b6000828152601760209081526040909120600501919091556113249061131e9084018461344f565b82612927565b6000611337611332846135e1565b612949565b6000838152601760205260408120600201829055601980549293508392909190611362908490613408565b90915550611372905033826126cd565b7f5fdb86c365a247a4d97dcbcc5c3abde9d6e3e2de26273f3fda8eef5073b9a96c828460200160176000868152602001908152602001600020600501546040516113be93929190613953565b60405180910390a1505050565b6113d3612ec3565b816000808281526018602052604090205460ff1660058111156113f8576113f8612fa4565b036114345760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b600083815260186020526040902061144a612ec3565b600180830154600090815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e0810186529583015467ffffffffffffffff9081168752600284015487860152600384015487870152600484015460608801526005840154608088015260068401549187019190915260078301541660c08601529182019390935281518083018352600884018054929493850192829082906114f69061341b565b80601f01602080910402602001604051908101604052809291908181526020018280546115229061341b565b801561156f5780601f106115445761010080835404028352916020019161156f565b820191906000526020600020905b81548152906001019060200180831161155257829003601f168201915b505050918352505060019190910154602091820152908252600a83015482820152600b9092015460409091015290825260039092015491810191909152915050919050565b6000818152601860205260408120600181015482036115d65750600092915050565b60006115e582600101546104dd565b90506004825460ff1660058111156115ff576115ff612fa4565b0361160e575060049392505050565b600281600481111561162257611622612fa4565b03611631575060059392505050565b600381600481111561164557611645612fa4565b03611654575060029392505050565b600481600481111561166857611668612fa4565b03611677575060039392505050565b505460ff1692915050565b600061093582611690612571565b61296e565b600082815260166020908152604080832060179092529091206005015442116117005760405162461bcd60e51b815260206004820152601960248201527f52657175657374206e6f74207965742074696d6564206f7574000000000000006044820152606401610531565b80546001600160a01b031633146117595760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b600083815260176020526040812090815460ff16600481111561177e5761177e612fa4565b146117cb5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207374617465000000000000000000000000000000000000006044820152606401610531565b805460ff1916600217815581546117eb906001600160a01b03168561299e565b60405184907ff903f4774c7bd27355f9d7fcbc382b079b164a697a44ac5d95267a4c3cb3bb2290600090a26002810154601a8054829190600090611830908490613408565b909155505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c891906139cf565b61073d5761073d6139f1565b6000828152601860209081526040808320600101548084526016909252909120546001600160a01b031661193c5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b60008381526018602090815260408083206001810154845260168352818420825160038082526080820190945291949093909290820160608036833701905050905061198f61198a87610922565b6129c0565b816000815181106119a2576119a2613a07565b602090810291909101015260098201546119bb906129d1565b816001815181106119ce576119ce613a07565b6020026020010181815250508260030154816002815181106119f2576119f2613a07565b60200260200101818152505061091a8686836129dd565b611a11612ee3565b60008281526016602052604090205482906001600160a01b0316611a695760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600083815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e081018652600184015467ffffffffffffffff90811682526002850154828701526003850154828801526004850154606083015260058501546080830152600685015492820192909252600784015490911660c08201529281019290925282518084018452600882018054939492939285019282908290611b149061341b565b80601f0160208091040260200160405190810160405280929190818152602001828054611b409061341b565b8015611b8d5780601f10611b6257610100808354040283529160200191611b8d565b820191906000526020600020905b815481529060010190602001808311611b7057829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050915050919050565b6000818310611bcf5781611bd1565b825b9392505050565b6000611be382612b9c565b9050428110611c345760405162461bcd60e51b815260206004820152601860248201527f506572696f6420686173206e6f7420656e6465642079657400000000000000006044820152606401610531565b600354611c419082613408565b4210611c8f5760405162461bcd60e51b815260206004820152601460248201527f56616c69646174696f6e2074696d6564206f75740000000000000000000000006044820152606401610531565b6000838152600b6020908152604080832085845290915290205460ff1615611cf95760405162461bcd60e51b815260206004820181905260248201527f50726f6f6620776173207375626d69747465642c206e6f74206d697373696e676044820152606401610531565b611d03838361296e565b611d4f5760405162461bcd60e51b815260206004820152601660248201527f50726f6f6620776173206e6f74207265717569726564000000000000000000006044820152606401610531565b6000838152600c6020908152604080832085845290915290205460ff1615611db95760405162461bcd60e51b815260206004820152601f60248201527f50726f6f6620616c7265616479206d61726b6564206173206d697373696e67006044820152606401610531565b6000838152600c602090815260408083208584528252808320805460ff19166001908117909155868452600a9092528220805491929091611dfb908490613408565b9091555050505050565b60008181526018602090815260408083206001810154808552601790935292206005830154611e3d906001600160a01b03168561254f565b6003808401546000868152601860205260408120805460ff1916815560018082018390556002820183905593810182905560048101829055600501805473ffffffffffffffffffffffffffffffffffffffff191690558383018054929392909190611ea99084906133a0565b909155505060405181815283907f1d31c9f8dea6e179f6a050db117595feea8937029ea51f5168a4780be7e8f5529060200160405180910390a26000858152600a6020526040812055600083815260166020526040812060018085015490820154919291611f21919067ffffffffffffffff166133a0565b600783015490915067ffffffffffffffff1681118015611f5657506001845460ff166004811115611f5457611f54612fa4565b145b15611fa257835460ff19166004178455611f716001426133a0565b600485015560405185907f4769361a442504ecaf038f35e119bcccdd5e42096b24c09e3c17fd17c6684c0290600090a25b50505050505050565b60008481526016602052604090205484906001600160a01b03166120035760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b60008581526017602090815260408083206016909252909120815460ff19166003178255805461203c906001600160a01b03168861299e565b60008681526018602052604090206005810154612062906001600160a01b03168861254f565b6000888152601660209081526040808320815160a0808201845282546001600160a01b03168252835160e081018552600184015467ffffffffffffffff90811682526002850154828801526003850154828701526004850154606083015260058501546080830152600685015492820192909252600784015490911660c082015293810193909352815180830183526008820180546121b7959485019291908290829061210e9061341b565b80601f016020809104026020016040519081016040528092919081815260200182805461213a9061341b565b80156121875780601f1061215c57610100808354040283529160200191612187565b820191906000526020600020905b81548152906001019060200180831161216a57829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050612baf565b60048301549091506121c98183613408565b601a80546000906121db908490613408565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038981166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612262573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228691906139cf565b612292576122926139f1565b60405163a9059cbb60e01b81526001600160a01b038881166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612301573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232591906139cf565b612331576123316139f1565b50505050505050505050565b60008481526016602052604090205484906001600160a01b03166123955760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600084815260186020526040902060058101546123bb906001600160a01b03168661254f565b60006123cb878360020154612630565b60048301549091506123dd8183613408565b601a80546000906123ef908490613408565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a91906139cf565b6124a6576124a66139f1565b60405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612515573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253991906139cf565b612545576125456139f1565b5050505050505050565b6001600160a01b0382166000908152600e60205260409020610dec9082612bcb565b6000610cef42612bd7565b6000611bd161258b8484612590565b612c03565b60008061259f610100436133c9565b600654909150600090610100906125b99060ff16866133dd565b6125c391906133c9565b905060006125d3610100876133c9565b90506000610100826125e58587613408565b6125ef9190613408565b6125f991906133c9565b979650505050505050565b6000610935825490565b6001600160a01b03811660009081526001830160205260408120541515611bd1565b60008281526016602090815260408083206017909252822060050154831061269a5760405162461bcd60e51b815260206004820152601760248201527f5374617274206e6f74206265666f7265206578706972790000000000000000006044820152606401610531565b6005810154836126b98660009081526017602052604090206005015490565b6126c391906133a0565b6104d591906133dd565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152306024830181905260448301849052917f0000000000000000000000000000000000000000000000000000000000000000909116906323b872dd906064016020604051808303816000875af1158015612760573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278491906139cf565b610dec5760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c656400000000000000000000000000000000006044820152606401610531565b6001600160a01b0382166000908152600e60205260409020610dec9082612c5d565b60606000611bd183612c69565b6000611bd1836001600160a01b038416612cc5565b6000806000612822856115b4565b6000868152600860205260408120549192509061283e90612bd7565b9050600182600581111561285457612854612fa4565b14158061286857506128668582612d14565b155b1561287b576000809350935050506128f0565b6128858686612590565b9250600061289284612c03565b600454909150600090610100906128ac9060ff1682613a1d565b60008a8152600960205260409020546128c99161ffff16906133dd565b6128d391906133f4565b90508015806128e957506128e781836133c9565b155b9550505050505b9250929050565b60008160405160200161290a9190613377565b604051602081830303815290604052805190602001209050919050565b6001600160a01b0382166000908152600d60205260409020610dec9082612c5d565b600061295482612baf565b602083015151610935919067ffffffffffffffff166133dd565b600080600061297d8585612814565b90925090508180156109c0575060045460ff90811691161015949350505050565b6001600160a01b0382166000908152600d60205260409020610dec9082612bcb565b600060ff198216816104d582612d1e565b600080611bd183612d1e565b6000838152600b60205260408120906129f4612571565b815260208101919091526040016000205460ff1615612a555760405162461bcd60e51b815260206004820152601760248201527f50726f6f6620616c7265616479207375626d69747465640000000000000000006044820152606401610531565b6007546040517f94c8919d0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906394c8919d90612aa09085908590600401613a38565b602060405180830381865afa158015612abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae191906139cf565b612b2d5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610531565b6000838152600b60205260408120600191612b46612571565b815260200190815260200160002060006101000a81548160ff0219169083151502179055507f3b989d183b84b02259d7c14b34a9c9eb0fccb4c355a920d25e581e25aef4993d836040516113be91815260200190565b6000610935612baa83612d90565b612d9d565b60208101516080810151604090910151600091610935916133dd565b6000611bd18383612dc9565b60006109357f0000000000000000000000000000000000000000000000000000000000000000836133f4565b60008060ff8316612c156001436133a0565b612c1f91906133a0565b4090506000819003612c3357612c336139f1565b60408051602081018390520160405160208183030381529060405280519060200120915050919050565b6000611bd18383612cc5565b606081600001805480602002602001604051908101604052809291908181526020018280548015612cb957602002820191906000526020600020905b815481526020019060010190808311612ca5575b50505050509050919050565b6000818152600183016020526040812054612d0c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610935565b506000610935565b6000818311611bd1565b7fff00000000000000000000000000000000000000000000000000000000000000811660015b60208110156105e957600891821c91612d5e9082906133dd565b83901b7fff00000000000000000000000000000000000000000000000000000000000000169190911790600101612d44565b6000610935826001613408565b60006109357f0000000000000000000000000000000000000000000000000000000000000000836133dd565b60008181526001830160205260408120548015612eb2576000612ded6001836133a0565b8554909150600090612e01906001906133a0565b9050818114612e66576000866000018281548110612e2157612e21613a07565b9060005260206000200154905080876000018481548110612e4457612e44613a07565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e7757612e77613ae3565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610935565b6000915050610935565b5092915050565b6040518060400160405280612ed6612ee3565b8152602001600081525090565b6040518060a0016040528060006001600160a01b03168152602001612f526040518060e00160405280600067ffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600067ffffffffffffffff1681525090565b8152602001612f77604051806040016040528060608152602001600080191681525090565b815260006020820181905260409091015290565b600060208284031215612f9d57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6020810160058310612fce57612fce612fa4565b91905290565b60008060408385031215612fe757600080fd5b50508035926020909101359150565b6001600160a01b0381168114610dfb57600080fd5b60008060006060848603121561302057600080fd5b83359250602084013561303281612ff6565b9150604084013561304281612ff6565b809150509250925092565b600061010082840312156105e957600080fd5b6000806000610140848603121561307657600080fd5b833592506020840135915061308e856040860161304d565b90509250925092565b6020808252825182820181905260009190848201906040850190845b818110156130cf578351835292840192918401916001016130b3565b50909695505050505050565b6000815180845260005b81811015613101576020818501810151868301820152016130e5565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000825160ff815116602084015260ff602082015116604084015261ffff604082015116606084015260ff606082015116608084015250602083015160c060a0840152805160e0840152602081015161010084015260ff604082015116610120840152606081015160a06101408501526131a36101808501826130db565b905060ff608083015116610160850152604085015191506104d560c08501835160ff169052565b6000602082840312156131dc57600080fd5b813567ffffffffffffffff8111156131f357600080fd5b82016101608185031215611bd157600080fd5b600081516040845261321b60408501826130db565b602093840151949093019390935250919050565b60006101606001600160a01b038351168452602083015167ffffffffffffffff808251166020870152602082015160408701526040820151606087015260608201516080870152608082015160a087015260a082015160c08701528060c08301511660e087015250506040830151816101008601526132b082860182613206565b915050606083015161012085015260808301516101408501528091505092915050565b6020815260008251604060208401526132ef606084018261322f565b9050602084015160408401528091505092915050565b6020810160068310612fce57612fce612fa4565b6000806040838503121561332c57600080fd5b82359150602083013561333e81612ff6565b809150509250929050565b600080610120838503121561335d57600080fd5b8235915061336e846020850161304d565b90509250929050565b602081526000611bd1602083018461322f565b634e487b7160e01b600052601160045260246000fd5b818103818111156109355761093561338a565b634e487b7160e01b600052601260045260246000fd5b6000826133d8576133d86133b3565b500690565b80820281158282048414176109355761093561338a565b600082613403576134036133b3565b500490565b808201808211156109355761093561338a565b600181811c9082168061342f57607f821691505b6020821081036105e957634e487b7160e01b600052602260045260246000fd5b60006020828403121561346157600080fd5b8135611bd181612ff6565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156134a5576134a561346c565b60405290565b60405160a0810167ffffffffffffffff811182821017156134a5576134a561346c565b60405160e0810167ffffffffffffffff811182821017156134a5576134a561346c565b604051601f8201601f1916810167ffffffffffffffff8111828210171561351a5761351a61346c565b604052919050565b67ffffffffffffffff81168114610dfb57600080fd5b60006040828403121561354a57600080fd5b613552613482565b9050813567ffffffffffffffff8082111561356c57600080fd5b818401915084601f83011261358057600080fd5b81356020828211156135945761359461346c565b6135a6601f8301601f191682016134f1565b925081835286818386010111156135bc57600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b60008136036101608112156135f557600080fd5b6135fd6134ab565b833561360881612ff6565b815260e0601f198301121561361c57600080fd5b6136246134ce565b9150602084013561363481613522565b8083525060408401356020830152606084013560408301526080840135606083015260a0840135608083015260c084013560a083015260e084013561367881613522565b60c083015260208101919091526101008301359067ffffffffffffffff8211156136a157600080fd5b6136ad36838601613538565b604082015261012084013560608201526101409093013560808401525090919050565b6000602082840312156136e257600080fd5b8135611bd181613522565b6000813561093581613522565b60008235603e1983360301811261371057600080fd5b9190910192915050565b601f821115610dec576000816000526020600020601f850160051c810160208610156137435750805b601f850160051c820191505b8181101561091a5782815560010161374f565b8135601e1983360301811261377657600080fd5b8201803567ffffffffffffffff81111561378f57600080fd5b602081360381840113156137a257600080fd5b6137b6826137b0865461341b565b8661371a565b6000601f8311600181146137ec57600084156137d457508482018301355b600019600386901b1c1916600185901b178655613849565b600086815260209020601f19851690835b8281101561381e5787850186013582559385019360019091019085016137fd565b508582101561383d5760001960f88760031b161c198585890101351681555b505060018460011b0186555b50508085013560018501555050505050565b813561386681612ff6565b6001600160a01b03811673ffffffffffffffffffffffffffffffffffffffff1983541617825550602082013561389b81613522565b60018201805467ffffffffffffffff191667ffffffffffffffff83161790555060408201356002820155606082013560038201556080820135600482015560a0820135600582015560c0820135600682015561391f6138fc60e084016136ed565b6007830167ffffffffffffffff821667ffffffffffffffff198254161781555050565b6139396139306101008401846136fa565b60088301613762565b610120820135600a820155610140820135600b8201555050565b8381526101208101833561396681613522565b67ffffffffffffffff8082166020850152602086013560408501526040860135606085015260608601356080850152608086013560a085015260a086013560c085015260c086013591506139b982613522565b1660e08301526101009091019190915292915050565b6000602082840312156139e157600080fd5b81518015158114611bd157600080fd5b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b61ffff828116828216039080821115612ebc57612ebc61338a565b82358152602080840135908201526000610120828101613a68604085016040880180358252602090810135910152565b613a82608085016080880180358252602090810135910152565b613a9c60c0850160c0880180358252602090810135910152565b61010084019190915283519081905261014083019060209081860160005b82811015613ad657815185529383019390830190600101613aba565b5092979650505050505050565b634e487b7160e01b600052603160045260246000fdfea26469706673582212201ba21efda4fce1ed7b3990b94dd29e667ca238fbd4d0f83d310d1cdd9ff5dd1a64736f6c63430008170033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ae5760003560e01c806379502c55116100ee578063be5cdc4811610097578063e8aa0a0711610071578063e8aa0a07146103ed578063f752196b14610400578063fb1e61ca14610420578063fc0c546a1461044057600080fd5b8063be5cdc48146103a7578063c0cc4add146103c7578063c5d43351146103da57600080fd5b8063a3a0807e116100c8578063a3a0807e14610361578063a6af384b14610374578063b396dc791461038757600080fd5b806379502c55146103315780639777b72c14610346578063a29c29a41461034e57600080fd5b80634641dce61161015b5780635da73835116101355780635da73835146102b257806362d48e13146102c75780636b00c8cf146102da5780636e2b54ee1461031e57600080fd5b80634641dce6146102575780634802f44b1461027c57806359cc89ed1461029f57600080fd5b80630aefaabe1161018c5780630aefaabe1461020e578063329b5a0b14610221578063458d2bf11461024457600080fd5b806302fa8e65146101b357806305b90773146101d957806308695fcd146101f9575b600080fd5b6101c66101c1366004612f8b565b610466565b6040519081526020015b60405180910390f35b6101ec6101e7366004612f8b565b6104dd565b6040516101d09190612fba565b61020c610207366004612fd4565b6105ef565b005b61020c61021c36600461300b565b610745565b6101c661022f366004612f8b565b60009081526017602052604090206005015490565b6101c6610252366004612f8b565b610922565b61026a610265366004612f8b565b61093b565b60405160ff90911681526020016101d0565b61028f61028a366004612fd4565b61094e565b60405190151581526020016101d0565b61020c6102ad366004613060565b6109c9565b6102ba610ccd565b6040516101d09190613097565b61020c6102d5366004612fd4565b610cf4565b6103066102e8366004612f8b565b6000908152601860205260409020600501546001600160a01b031690565b6040516001600160a01b0390911681526020016101d0565b61020c61032c366004612f8b565b610df1565b610339610dfe565b6040516101d09190613121565b6102ba610fb2565b61020c61035c366004612f8b565b610fd1565b61028f61036f366004612f8b565b611041565b61020c6103823660046131ca565b611076565b61039a610395366004612f8b565b6113cb565b6040516101d091906132d3565b6103ba6103b5366004612f8b565b6115b4565b6040516101d09190613305565b61028f6103d5366004612f8b565b611682565b61020c6103e8366004613319565b611695565b61020c6103fb366004613349565b6118d4565b6101c661040e366004612f8b565b6000908152600a602052604090205490565b61043361042e366004612f8b565b611a09565b6040516101d09190613377565b7f0000000000000000000000000000000000000000000000000000000000000000610306565b60008181526017602052604081206004015481610482846104dd565b9050600081600481111561049857610498612fa4565b14806104b5575060018160048111156104b3576104b3612fa4565b145b156104c1575092915050565b6104d5826104d06001426133a0565b611bc0565b949350505050565b60008181526016602052604081205482906001600160a01b031661053a5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b60448201526064015b60405180910390fd5b600083815260176020526040812090815460ff16600481111561055f5761055f612fa4565b14801561057c575060008481526017602052604090206005015442115b1561058b5760029250506105e9565b6001815460ff1660048111156105a3576105a3612fa4565b14806105c457506000815460ff1660048111156105c2576105c2612fa4565b145b80156105d35750806004015442115b156105e25760039250506105e9565b5460ff1691505b50919050565b60016105fa836115b4565b600581111561060b5761060b612fa4565b146106585760405162461bcd60e51b815260206004820152601960248201527f536c6f74206e6f7420616363657074696e672070726f6f6673000000000000006044820152606401610531565b6106628282611bd8565b6000828152601860209081526040808320600181015484526016909252909120600f5461ffff62010000909104166106a6856000908152600a602052604090205490565b6106b091906133c9565b60000361073f57600f5460068201546000916064916106da91640100000000900460ff16906133dd565b6106e491906133f4565b9050808360040160008282546106fa91906133a0565b9091555050600f546000868152600a6020526040902054610100820460ff169162010000900461ffff169061072f91906133f4565b1061073d5761073d85611e05565b505b50505050565b826000808281526018602052604090205460ff16600581111561076a5761076a612fa4565b036107a65760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b600084815260186020526040902060058101546001600160a01b031633146108105760405162461bcd60e51b815260206004820152601960248201527f536c6f742066696c6c6564206279206f7468657220686f7374000000000000006044820152606401610531565b600061081b866115b4565b9050600481600581111561083157610831612fa4565b0361087e5760405162461bcd60e51b815260206004820152600c60248201527f416c7265616479207061696400000000000000000000000000000000000000006044820152606401610531565b600281600581111561089257610892612fa4565b036108ac576108a78260010154878787611fab565b61091a565b60058160058111156108c0576108c0612fa4565b036108d5576108a7826001015487878761233d565b60038160058111156108e9576108e9612fa4565b036108f8576108a7338761254f565b600181600581111561090c5761090c612fa4565b0361091a5761091a86611e05565b505050505050565b600061093582610930612571565b61257c565b92915050565b600061093582610949612571565b612590565b6040805160208082018590528183018490528251808303840181526060909201909252805191012060009033908290600154600082815260208190526040902091925060ff169061099e90612604565b1080156109c0575060008181526020819052604090206109be908361260e565b155b95945050505050565b60008381526016602052604090205483906001600160a01b0316610a215760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b6000848152601660205260409020600181015467ffffffffffffffff168410610a8c5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c696420736c6f7400000000000000000000000000000000000000006044820152606401610531565b6040805160208082018890528183018790528251808303840181526060909201909252805191012060009060008181526018602052604081206001810189905560038101889055919250610adf836115b4565b6005811115610af057610af0612fa4565b14610b3d5760405162461bcd60e51b815260206004820152601060248201527f536c6f74206973206e6f742066726565000000000000000000000000000000006044820152606401610531565b600483015460008381526008602090815260408083204290556009909152902055610b6882866118d4565b60058101805473ffffffffffffffffffffffffffffffffffffffff191633179055805460ff191660019081178255426002830155600088815260176020526040812080830180549193929091610bbf908490613408565b90915550610bcf90508842612630565b816002016000828254610be291906133a0565b90915550506006840154610bf633826126cd565b8060196000016000828254610c0b9190613408565b9091555050600483018190556005830154610c2f906001600160a01b0316856127d0565b887ff530852268993f91008f1a1e0b09b5c813acd4188481f1fa83c33c7182e814b489604051610c6191815260200190565b60405180910390a26001808601549083015467ffffffffffffffff9091169003610cc257815460ff1916600117825542600383015560405189907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a25b505050505050505050565b336000908152600e60205260409020606090610cef90610cec906127f2565b90565b905090565b610cfe828261094e565b610d4a5760405162461bcd60e51b815260206004820152601760248201527f5265736572766174696f6e206e6f7420616c6c6f7765640000000000000000006044820152606401610531565b60408051602080820185905281830184905282518083038401815260609092018352815191810191909120600081815291829052919020610d8b90336127ff565b50600154600082815260208190526040902060ff90911690610dac90612604565b03610dec57827f3bef2ebab8cc92e0edda5decf18232f0606a18405ef674b51ea9d1e0e3839b4183604051610de391815260200190565b60405180910390a25b505050565b610dfb8133611695565b50565b610e726040805160e081019091526000606082018181526080830182905260a0830182905260c0830191909152819081526040805160a08101825260008082526020828101829052928201819052606080830152608082015291019081526040805160208181019092526000815291015290565b6040805160e081018252600f805460ff808216606080860191825261010084048316608087015261ffff6201000085041660a080880191909152640100000000909404831660c087015290855285519283018652601080548452601154602085810191909152601254909316968401969096526013805495969495928701949291840191610eff9061341b565b80601f0160208091040260200160405190810160405280929190818152602001828054610f2b9061341b565b8015610f785780601f10610f4d57610100808354040283529160200191610f78565b820191906000526020600020905b815481529060010190602001808311610f5b57829003601f168201915b50505091835250506004919091015460ff908116602092830152918352604080518083019091526006949094015490911683520152919050565b336000908152600d60205260409020606090610cef90610cec906127f2565b806000808281526018602052604090205460ff166005811115610ff657610ff6612fa4565b036110325760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b61103d823333610745565b5050565b600080600061105784611052612571565b612814565b90925090508180156104d5575060045460ff9081169116109392505050565b33611084602083018361344f565b6001600160a01b0316146110da5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b60006110ed6110e8836135e1565b6128f7565b6000818152601660205260409020549091506001600160a01b0316156111555760405162461bcd60e51b815260206004820152601660248201527f5265717565737420616c726561647920657869737473000000000000000000006044820152606401610531565b600082610120013511801561117257506060820135610120830135105b6111be5760405162461bcd60e51b815260206004820152601360248201527f457870697279206e6f7420696e2072616e6765000000000000000000000000006044820152606401610531565b60006111d060408401602085016136d0565b67ffffffffffffffff16116112275760405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420736c6f747300000000000000000000000000006044820152606401610531565b61123760408301602084016136d0565b67ffffffffffffffff16611252610100840160e085016136d0565b67ffffffffffffffff1611156112aa5760405162461bcd60e51b815260206004820152601960248201527f6d6178536c6f744c6f7373206578636565647320736c6f7473000000000000006044820152606401610531565b600081815260166020526040902082906112c4828261385b565b506112d59050606083013542613408565b6000828152601760205260409020600401556112f661012083013542613408565b6000828152601760209081526040909120600501919091556113249061131e9084018461344f565b82612927565b6000611337611332846135e1565b612949565b6000838152601760205260408120600201829055601980549293508392909190611362908490613408565b90915550611372905033826126cd565b7f5fdb86c365a247a4d97dcbcc5c3abde9d6e3e2de26273f3fda8eef5073b9a96c828460200160176000868152602001908152602001600020600501546040516113be93929190613953565b60405180910390a1505050565b6113d3612ec3565b816000808281526018602052604090205460ff1660058111156113f8576113f8612fa4565b036114345760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b600083815260186020526040902061144a612ec3565b600180830154600090815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e0810186529583015467ffffffffffffffff9081168752600284015487860152600384015487870152600484015460608801526005840154608088015260068401549187019190915260078301541660c08601529182019390935281518083018352600884018054929493850192829082906114f69061341b565b80601f01602080910402602001604051908101604052809291908181526020018280546115229061341b565b801561156f5780601f106115445761010080835404028352916020019161156f565b820191906000526020600020905b81548152906001019060200180831161155257829003601f168201915b505050918352505060019190910154602091820152908252600a83015482820152600b9092015460409091015290825260039092015491810191909152915050919050565b6000818152601860205260408120600181015482036115d65750600092915050565b60006115e582600101546104dd565b90506004825460ff1660058111156115ff576115ff612fa4565b0361160e575060049392505050565b600281600481111561162257611622612fa4565b03611631575060059392505050565b600381600481111561164557611645612fa4565b03611654575060029392505050565b600481600481111561166857611668612fa4565b03611677575060039392505050565b505460ff1692915050565b600061093582611690612571565b61296e565b600082815260166020908152604080832060179092529091206005015442116117005760405162461bcd60e51b815260206004820152601960248201527f52657175657374206e6f74207965742074696d6564206f7574000000000000006044820152606401610531565b80546001600160a01b031633146117595760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b600083815260176020526040812090815460ff16600481111561177e5761177e612fa4565b146117cb5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207374617465000000000000000000000000000000000000006044820152606401610531565b805460ff1916600217815581546117eb906001600160a01b03168561299e565b60405184907ff903f4774c7bd27355f9d7fcbc382b079b164a697a44ac5d95267a4c3cb3bb2290600090a26002810154601a8054829190600090611830908490613408565b909155505060405163a9059cbb60e01b81526001600160a01b038581166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156118a4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118c891906139cf565b61073d5761073d6139f1565b6000828152601860209081526040808320600101548084526016909252909120546001600160a01b031661193c5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b60008381526018602090815260408083206001810154845260168352818420825160038082526080820190945291949093909290820160608036833701905050905061198f61198a87610922565b6129c0565b816000815181106119a2576119a2613a07565b602090810291909101015260098201546119bb906129d1565b816001815181106119ce576119ce613a07565b6020026020010181815250508260030154816002815181106119f2576119f2613a07565b60200260200101818152505061091a8686836129dd565b611a11612ee3565b60008281526016602052604090205482906001600160a01b0316611a695760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600083815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e081018652600184015467ffffffffffffffff90811682526002850154828701526003850154828801526004850154606083015260058501546080830152600685015492820192909252600784015490911660c08201529281019290925282518084018452600882018054939492939285019282908290611b149061341b565b80601f0160208091040260200160405190810160405280929190818152602001828054611b409061341b565b8015611b8d5780601f10611b6257610100808354040283529160200191611b8d565b820191906000526020600020905b815481529060010190602001808311611b7057829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050915050919050565b6000818310611bcf5781611bd1565b825b9392505050565b6000611be382612b9c565b9050428110611c345760405162461bcd60e51b815260206004820152601860248201527f506572696f6420686173206e6f7420656e6465642079657400000000000000006044820152606401610531565b600354611c419082613408565b4210611c8f5760405162461bcd60e51b815260206004820152601460248201527f56616c69646174696f6e2074696d6564206f75740000000000000000000000006044820152606401610531565b6000838152600b6020908152604080832085845290915290205460ff1615611cf95760405162461bcd60e51b815260206004820181905260248201527f50726f6f6620776173207375626d69747465642c206e6f74206d697373696e676044820152606401610531565b611d03838361296e565b611d4f5760405162461bcd60e51b815260206004820152601660248201527f50726f6f6620776173206e6f74207265717569726564000000000000000000006044820152606401610531565b6000838152600c6020908152604080832085845290915290205460ff1615611db95760405162461bcd60e51b815260206004820152601f60248201527f50726f6f6620616c7265616479206d61726b6564206173206d697373696e67006044820152606401610531565b6000838152600c602090815260408083208584528252808320805460ff19166001908117909155868452600a9092528220805491929091611dfb908490613408565b9091555050505050565b60008181526018602090815260408083206001810154808552601790935292206005830154611e3d906001600160a01b03168561254f565b6003808401546000868152601860205260408120805460ff1916815560018082018390556002820183905593810182905560048101829055600501805473ffffffffffffffffffffffffffffffffffffffff191690558383018054929392909190611ea99084906133a0565b909155505060405181815283907f1d31c9f8dea6e179f6a050db117595feea8937029ea51f5168a4780be7e8f5529060200160405180910390a26000858152600a6020526040812055600083815260166020526040812060018085015490820154919291611f21919067ffffffffffffffff166133a0565b600783015490915067ffffffffffffffff1681118015611f5657506001845460ff166004811115611f5457611f54612fa4565b145b15611fa257835460ff19166004178455611f716001426133a0565b600485015560405185907f4769361a442504ecaf038f35e119bcccdd5e42096b24c09e3c17fd17c6684c0290600090a25b50505050505050565b60008481526016602052604090205484906001600160a01b03166120035760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b60008581526017602090815260408083206016909252909120815460ff19166003178255805461203c906001600160a01b03168861299e565b60008681526018602052604090206005810154612062906001600160a01b03168861254f565b6000888152601660209081526040808320815160a0808201845282546001600160a01b03168252835160e081018552600184015467ffffffffffffffff90811682526002850154828801526003850154828701526004850154606083015260058501546080830152600685015492820192909252600784015490911660c082015293810193909352815180830183526008820180546121b7959485019291908290829061210e9061341b565b80601f016020809104026020016040519081016040528092919081815260200182805461213a9061341b565b80156121875780601f1061215c57610100808354040283529160200191612187565b820191906000526020600020905b81548152906001019060200180831161216a57829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050612baf565b60048301549091506121c98183613408565b601a80546000906121db908490613408565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038981166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612262573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061228691906139cf565b612292576122926139f1565b60405163a9059cbb60e01b81526001600160a01b038881166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612301573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061232591906139cf565b612331576123316139f1565b50505050505050505050565b60008481526016602052604090205484906001600160a01b03166123955760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600084815260186020526040902060058101546123bb906001600160a01b03168661254f565b60006123cb878360020154612630565b60048301549091506123dd8183613408565b601a80546000906123ef908490613408565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612476573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061249a91906139cf565b6124a6576124a66139f1565b60405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612515573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061253991906139cf565b612545576125456139f1565b5050505050505050565b6001600160a01b0382166000908152600e60205260409020610dec9082612bcb565b6000610cef42612bd7565b6000611bd161258b8484612590565b612c03565b60008061259f610100436133c9565b600654909150600090610100906125b99060ff16866133dd565b6125c391906133c9565b905060006125d3610100876133c9565b90506000610100826125e58587613408565b6125ef9190613408565b6125f991906133c9565b979650505050505050565b6000610935825490565b6001600160a01b03811660009081526001830160205260408120541515611bd1565b60008281526016602090815260408083206017909252822060050154831061269a5760405162461bcd60e51b815260206004820152601760248201527f5374617274206e6f74206265666f7265206578706972790000000000000000006044820152606401610531565b6005810154836126b98660009081526017602052604090206005015490565b6126c391906133a0565b6104d591906133dd565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152306024830181905260448301849052917f0000000000000000000000000000000000000000000000000000000000000000909116906323b872dd906064016020604051808303816000875af1158015612760573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061278491906139cf565b610dec5760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c656400000000000000000000000000000000006044820152606401610531565b6001600160a01b0382166000908152600e60205260409020610dec9082612c5d565b60606000611bd183612c69565b6000611bd1836001600160a01b038416612cc5565b6000806000612822856115b4565b6000868152600860205260408120549192509061283e90612bd7565b9050600182600581111561285457612854612fa4565b14158061286857506128668582612d14565b155b1561287b576000809350935050506128f0565b6128858686612590565b9250600061289284612c03565b600454909150600090610100906128ac9060ff1682613a1d565b60008a8152600960205260409020546128c99161ffff16906133dd565b6128d391906133f4565b90508015806128e957506128e781836133c9565b155b9550505050505b9250929050565b60008160405160200161290a9190613377565b604051602081830303815290604052805190602001209050919050565b6001600160a01b0382166000908152600d60205260409020610dec9082612c5d565b600061295482612baf565b602083015151610935919067ffffffffffffffff166133dd565b600080600061297d8585612814565b90925090508180156109c0575060045460ff90811691161015949350505050565b6001600160a01b0382166000908152600d60205260409020610dec9082612bcb565b600060ff198216816104d582612d1e565b600080611bd183612d1e565b6000838152600b60205260408120906129f4612571565b815260208101919091526040016000205460ff1615612a555760405162461bcd60e51b815260206004820152601760248201527f50726f6f6620616c7265616479207375626d69747465640000000000000000006044820152606401610531565b6007546040517f94c8919d0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906394c8919d90612aa09085908590600401613a38565b602060405180830381865afa158015612abd573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612ae191906139cf565b612b2d5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610531565b6000838152600b60205260408120600191612b46612571565b815260200190815260200160002060006101000a81548160ff0219169083151502179055507f3b989d183b84b02259d7c14b34a9c9eb0fccb4c355a920d25e581e25aef4993d836040516113be91815260200190565b6000610935612baa83612d90565b612d9d565b60208101516080810151604090910151600091610935916133dd565b6000611bd18383612dc9565b60006109357f0000000000000000000000000000000000000000000000000000000000000000836133f4565b60008060ff8316612c156001436133a0565b612c1f91906133a0565b4090506000819003612c3357612c336139f1565b60408051602081018390520160405160208183030381529060405280519060200120915050919050565b6000611bd18383612cc5565b606081600001805480602002602001604051908101604052809291908181526020018280548015612cb957602002820191906000526020600020905b815481526020019060010190808311612ca5575b50505050509050919050565b6000818152600183016020526040812054612d0c57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610935565b506000610935565b6000818311611bd1565b7fff00000000000000000000000000000000000000000000000000000000000000811660015b60208110156105e957600891821c91612d5e9082906133dd565b83901b7fff00000000000000000000000000000000000000000000000000000000000000169190911790600101612d44565b6000610935826001613408565b60006109357f0000000000000000000000000000000000000000000000000000000000000000836133dd565b60008181526001830160205260408120548015612eb2576000612ded6001836133a0565b8554909150600090612e01906001906133a0565b9050818114612e66576000866000018281548110612e2157612e21613a07565b9060005260206000200154905080876000018481548110612e4457612e44613a07565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612e7757612e77613ae3565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610935565b6000915050610935565b5092915050565b6040518060400160405280612ed6612ee3565b8152602001600081525090565b6040518060a0016040528060006001600160a01b03168152602001612f526040518060e00160405280600067ffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600067ffffffffffffffff1681525090565b8152602001612f77604051806040016040528060608152602001600080191681525090565b815260006020820181905260409091015290565b600060208284031215612f9d57600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b6020810160058310612fce57612fce612fa4565b91905290565b60008060408385031215612fe757600080fd5b50508035926020909101359150565b6001600160a01b0381168114610dfb57600080fd5b60008060006060848603121561302057600080fd5b83359250602084013561303281612ff6565b9150604084013561304281612ff6565b809150509250925092565b600061010082840312156105e957600080fd5b6000806000610140848603121561307657600080fd5b833592506020840135915061308e856040860161304d565b90509250925092565b6020808252825182820181905260009190848201906040850190845b818110156130cf578351835292840192918401916001016130b3565b50909695505050505050565b6000815180845260005b81811015613101576020818501810151868301820152016130e5565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000825160ff815116602084015260ff602082015116604084015261ffff604082015116606084015260ff606082015116608084015250602083015160c060a0840152805160e0840152602081015161010084015260ff604082015116610120840152606081015160a06101408501526131a36101808501826130db565b905060ff608083015116610160850152604085015191506104d560c08501835160ff169052565b6000602082840312156131dc57600080fd5b813567ffffffffffffffff8111156131f357600080fd5b82016101608185031215611bd157600080fd5b600081516040845261321b60408501826130db565b602093840151949093019390935250919050565b60006101606001600160a01b038351168452602083015167ffffffffffffffff808251166020870152602082015160408701526040820151606087015260608201516080870152608082015160a087015260a082015160c08701528060c08301511660e087015250506040830151816101008601526132b082860182613206565b915050606083015161012085015260808301516101408501528091505092915050565b6020815260008251604060208401526132ef606084018261322f565b9050602084015160408401528091505092915050565b6020810160068310612fce57612fce612fa4565b6000806040838503121561332c57600080fd5b82359150602083013561333e81612ff6565b809150509250929050565b600080610120838503121561335d57600080fd5b8235915061336e846020850161304d565b90509250929050565b602081526000611bd1602083018461322f565b634e487b7160e01b600052601160045260246000fd5b818103818111156109355761093561338a565b634e487b7160e01b600052601260045260246000fd5b6000826133d8576133d86133b3565b500690565b80820281158282048414176109355761093561338a565b600082613403576134036133b3565b500490565b808201808211156109355761093561338a565b600181811c9082168061342f57607f821691505b6020821081036105e957634e487b7160e01b600052602260045260246000fd5b60006020828403121561346157600080fd5b8135611bd181612ff6565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff811182821017156134a5576134a561346c565b60405290565b60405160a0810167ffffffffffffffff811182821017156134a5576134a561346c565b60405160e0810167ffffffffffffffff811182821017156134a5576134a561346c565b604051601f8201601f1916810167ffffffffffffffff8111828210171561351a5761351a61346c565b604052919050565b67ffffffffffffffff81168114610dfb57600080fd5b60006040828403121561354a57600080fd5b613552613482565b9050813567ffffffffffffffff8082111561356c57600080fd5b818401915084601f83011261358057600080fd5b81356020828211156135945761359461346c565b6135a6601f8301601f191682016134f1565b925081835286818386010111156135bc57600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b60008136036101608112156135f557600080fd5b6135fd6134ab565b833561360881612ff6565b815260e0601f198301121561361c57600080fd5b6136246134ce565b9150602084013561363481613522565b8083525060408401356020830152606084013560408301526080840135606083015260a0840135608083015260c084013560a083015260e084013561367881613522565b60c083015260208101919091526101008301359067ffffffffffffffff8211156136a157600080fd5b6136ad36838601613538565b604082015261012084013560608201526101409093013560808401525090919050565b6000602082840312156136e257600080fd5b8135611bd181613522565b6000813561093581613522565b60008235603e1983360301811261371057600080fd5b9190910192915050565b601f821115610dec576000816000526020600020601f850160051c810160208610156137435750805b601f850160051c820191505b8181101561091a5782815560010161374f565b8135601e1983360301811261377657600080fd5b8201803567ffffffffffffffff81111561378f57600080fd5b602081360381840113156137a257600080fd5b6137b6826137b0865461341b565b8661371a565b6000601f8311600181146137ec57600084156137d457508482018301355b600019600386901b1c1916600185901b178655613849565b600086815260209020601f19851690835b8281101561381e5787850186013582559385019360019091019085016137fd565b508582101561383d5760001960f88760031b161c198585890101351681555b505060018460011b0186555b50508085013560018501555050505050565b813561386681612ff6565b6001600160a01b03811673ffffffffffffffffffffffffffffffffffffffff1983541617825550602082013561389b81613522565b60018201805467ffffffffffffffff191667ffffffffffffffff83161790555060408201356002820155606082013560038201556080820135600482015560a0820135600582015560c0820135600682015561391f6138fc60e084016136ed565b6007830167ffffffffffffffff821667ffffffffffffffff198254161781555050565b6139396139306101008401846136fa565b60088301613762565b610120820135600a820155610140820135600b8201555050565b8381526101208101833561396681613522565b67ffffffffffffffff8082166020850152602086013560408501526040860135606085015260608601356080850152608086013560a085015260a086013560c085015260c086013591506139b982613522565b1660e08301526101009091019190915292915050565b6000602082840312156139e157600080fd5b81518015158114611bd157600080fd5b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b61ffff828116828216039080821115612ebc57612ebc61338a565b82358152602080840135908201526000610120828101613a68604085016040880180358252602090810135910152565b613a82608085016080880180358252602090810135910152565b613a9c60c0850160c0880180358252602090810135910152565b61010084019190915283519081905261014083019060209081860160005b82811015613ad657815185529383019390830190600101613aba565b5092979650505050505050565b634e487b7160e01b600052603160045260246000fdfea26469706673582212201ba21efda4fce1ed7b3990b94dd29e667ca238fbd4d0f83d310d1cdd9ff5dd1a64736f6c63430008170033", + "numDeployments": 4, + "solcInputHash": "73497e5b46b1a1eec0c64f9cd6de8fb8", + "metadata": "{\"compiler\":{\"version\":\"0.8.23+commit.f704f362\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"repairRewardPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"maxNumberOfSlashes\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"slashCriterion\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"slashPercentage\",\"type\":\"uint8\"}],\"internalType\":\"struct CollateralConfig\",\"name\":\"collateral\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"period\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timeout\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"downtime\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"zkeyHash\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"downtimeProduct\",\"type\":\"uint8\"}],\"internalType\":\"struct ProofConfig\",\"name\":\"proofs\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"maxReservations\",\"type\":\"uint8\"}],\"internalType\":\"struct SlotReservationsConfig\",\"name\":\"reservations\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketplaceConfig\",\"name\":\"configuration\",\"type\":\"tuple\"},{\"internalType\":\"contract IERC20\",\"name\":\"token_\",\"type\":\"address\"},{\"internalType\":\"contract IGroth16Verifier\",\"name\":\"verifier\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"ProofSubmitted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"RequestCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"RequestFailed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"RequestFulfilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"SlotFilled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"SlotFreed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"SlotReservationsFull\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"indexed\":false,\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"}],\"name\":\"StorageRequested\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"canReserveSlot\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"config\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"uint8\",\"name\":\"repairRewardPercentage\",\"type\":\"uint8\"},{\"internalType\":\"uint8\",\"name\":\"maxNumberOfSlashes\",\"type\":\"uint8\"},{\"internalType\":\"uint16\",\"name\":\"slashCriterion\",\"type\":\"uint16\"},{\"internalType\":\"uint8\",\"name\":\"slashPercentage\",\"type\":\"uint8\"}],\"internalType\":\"struct CollateralConfig\",\"name\":\"collateral\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"period\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"timeout\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"downtime\",\"type\":\"uint8\"},{\"internalType\":\"string\",\"name\":\"zkeyHash\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"downtimeProduct\",\"type\":\"uint8\"}],\"internalType\":\"struct ProofConfig\",\"name\":\"proofs\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"maxReservations\",\"type\":\"uint8\"}],\"internalType\":\"struct SlotReservationsConfig\",\"name\":\"reservations\",\"type\":\"tuple\"}],\"internalType\":\"struct MarketplaceConfig\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"a\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"x\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"y\",\"type\":\"tuple\"}],\"internalType\":\"struct G2Point\",\"name\":\"b\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"c\",\"type\":\"tuple\"}],\"internalType\":\"struct Groth16Proof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"fillSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"rewardRecipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"collateralRecipient\",\"type\":\"address\"}],\"name\":\"freeSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"freeSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"getActiveSlot\",\"outputs\":[{\"components\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"cid\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"struct Content\",\"name\":\"content\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct Request\",\"name\":\"request\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"internalType\":\"struct Marketplace.ActiveSlot\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getChallenge\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"getHost\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"getPointer\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"getRequest\",\"outputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"cid\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"struct Content\",\"name\":\"content\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct Request\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"isProofRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"},{\"internalType\":\"Periods.Period\",\"name\":\"period\",\"type\":\"uint256\"}],\"name\":\"markProofAsMissing\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"missingProofs\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"myRequests\",\"outputs\":[{\"internalType\":\"RequestId[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"mySlots\",\"outputs\":[{\"internalType\":\"SlotId[]\",\"name\":\"\",\"type\":\"bytes32[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"requestEnd\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"requestExpiry\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"requestState\",\"outputs\":[{\"internalType\":\"enum RequestState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"client\",\"type\":\"address\"},{\"components\":[{\"internalType\":\"uint64\",\"name\":\"slots\",\"type\":\"uint64\"},{\"internalType\":\"uint256\",\"name\":\"slotSize\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"duration\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"proofProbability\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"reward\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"collateral\",\"type\":\"uint256\"},{\"internalType\":\"uint64\",\"name\":\"maxSlotLoss\",\"type\":\"uint64\"}],\"internalType\":\"struct Ask\",\"name\":\"ask\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"cid\",\"type\":\"string\"},{\"internalType\":\"bytes32\",\"name\":\"merkleRoot\",\"type\":\"bytes32\"}],\"internalType\":\"struct Content\",\"name\":\"content\",\"type\":\"tuple\"},{\"internalType\":\"uint256\",\"name\":\"expiry\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"nonce\",\"type\":\"bytes32\"}],\"internalType\":\"struct Request\",\"name\":\"request\",\"type\":\"tuple\"}],\"name\":\"requestStorage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"slotIndex\",\"type\":\"uint256\"}],\"name\":\"reserveSlot\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"slotId\",\"type\":\"bytes32\"}],\"name\":\"slotState\",\"outputs\":[{\"internalType\":\"enum SlotState\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"a\",\"type\":\"tuple\"},{\"components\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"x\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"real\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"imag\",\"type\":\"uint256\"}],\"internalType\":\"struct Fp2Element\",\"name\":\"y\",\"type\":\"tuple\"}],\"internalType\":\"struct G2Point\",\"name\":\"b\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"x\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"y\",\"type\":\"uint256\"}],\"internalType\":\"struct G1Point\",\"name\":\"c\",\"type\":\"tuple\"}],\"internalType\":\"struct Groth16Proof\",\"name\":\"proof\",\"type\":\"tuple\"}],\"name\":\"submitProof\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"token\",\"outputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"SlotId\",\"name\":\"id\",\"type\":\"bytes32\"}],\"name\":\"willProofBeRequired\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"RequestId\",\"name\":\"requestId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"withdrawRecipient\",\"type\":\"address\"}],\"name\":\"withdrawFunds\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"fillSlot(bytes32,uint256,((uint256,uint256),((uint256,uint256),(uint256,uint256)),(uint256,uint256)))\":{\"params\":{\"proof\":\"Groth16 proof procing possession of the slot data.\",\"requestId\":\"RequestId identifying the request containing the slot to fill.\",\"slotIndex\":\"Index of the slot in the request.\"}},\"freeSlot(bytes32)\":{\"details\":\"The host that filled the slot must have initiated the transaction (msg.sender). This overload allows `rewardRecipient` and `collateralRecipient` to be optional.\",\"params\":{\"slotId\":\"id of the slot to free\"}},\"freeSlot(bytes32,address,address)\":{\"params\":{\"collateralRecipient\":\"address to refund collateral to\",\"rewardRecipient\":\"address to send rewards to\",\"slotId\":\"id of the slot to free\"}},\"getChallenge(bytes32)\":{\"params\":{\"id\":\"Slot's ID for which the challenge should be calculated\"},\"returns\":{\"_0\":\"Challenge for current Period that should be used for generation of proofs\"}},\"getPointer(bytes32)\":{\"details\":\"For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\",\"params\":{\"id\":\"Slot's ID for which the pointer should be calculated\"},\"returns\":{\"_0\":\"Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\"}},\"isProofRequired(bytes32)\":{\"params\":{\"id\":\"Slot's ID for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\"},\"returns\":{\"_0\":\"bool indicating if proof is required for current period\"}},\"missingProofs(bytes32)\":{\"returns\":{\"_0\":\"Number of missed proofs since Slot was Filled\"}},\"willProofBeRequired(bytes32)\":{\"details\":\"for more info about downtime see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime)\",\"params\":{\"id\":\"SlotId for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\"},\"returns\":{\"_0\":\"bool\"}},\"withdrawFunds(bytes32)\":{\"details\":\"Request must be cancelled, failed or finished, and the transaction must originate from the depositor address.\",\"params\":{\"requestId\":\"the id of the request\"}},\"withdrawFunds(bytes32,address)\":{\"details\":\"Request must be expired, must be in RequestState.New, and the transaction must originate from the depositer address.\",\"params\":{\"requestId\":\"the id of the request\",\"withdrawRecipient\":\"address to return the remaining funds to\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"fillSlot(bytes32,uint256,((uint256,uint256),((uint256,uint256),(uint256,uint256)),(uint256,uint256)))\":{\"notice\":\"Fills a slot. Reverts if an invalid proof of the slot data is provided.\"},\"freeSlot(bytes32)\":{\"notice\":\"Frees a slot, paying out rewards and returning collateral for finished or cancelled requests to the host that has filled the slot.\"},\"freeSlot(bytes32,address,address)\":{\"notice\":\"Frees a slot, paying out rewards and returning collateral for finished or cancelled requests.\"},\"willProofBeRequired(bytes32)\":{\"notice\":\"Proof Downtime specifies part of the Period when the proof is not required even if the proof should be required. This function returns true if the pointer is in downtime (hence no proof required now) and at the same time the proof will be required later on in the Period.\"},\"withdrawFunds(bytes32)\":{\"notice\":\"Withdraws remaining storage request funds back to the client that deposited them.\"},\"withdrawFunds(bytes32,address)\":{\"notice\":\"Withdraws storage request funds to the provided address.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/Marketplace.sol\":\"Marketplace\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":1000},\"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/math/Math.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Standard math utilities missing in the Solidity language.\\n */\\nlibrary Math {\\n enum Rounding {\\n Down, // Toward negative infinity\\n Up, // Toward infinity\\n Zero // Toward zero\\n }\\n\\n /**\\n * @dev Returns the largest of two numbers.\\n */\\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a > b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the smallest of two numbers.\\n */\\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a < b ? a : b;\\n }\\n\\n /**\\n * @dev Returns the average of two numbers. The result is rounded towards\\n * zero.\\n */\\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b) / 2 can overflow.\\n return (a & b) + (a ^ b) / 2;\\n }\\n\\n /**\\n * @dev Returns the ceiling of the division of two numbers.\\n *\\n * This differs from standard division with `/` in that it rounds up instead\\n * of rounding down.\\n */\\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\\n // (a + b - 1) / b can overflow on addition, so we distribute.\\n return a == 0 ? 0 : (a - 1) / b + 1;\\n }\\n\\n /**\\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\\n * with further edits by Uniswap Labs also under MIT license.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator\\n ) internal pure returns (uint256 result) {\\n unchecked {\\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\\n // variables such that product = prod1 * 2^256 + prod0.\\n uint256 prod0; // Least significant 256 bits of the product\\n uint256 prod1; // Most significant 256 bits of the product\\n assembly {\\n let mm := mulmod(x, y, not(0))\\n prod0 := mul(x, y)\\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\\n }\\n\\n // Handle non-overflow cases, 256 by 256 division.\\n if (prod1 == 0) {\\n return prod0 / denominator;\\n }\\n\\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\\n require(denominator > prod1);\\n\\n ///////////////////////////////////////////////\\n // 512 by 256 division.\\n ///////////////////////////////////////////////\\n\\n // Make division exact by subtracting the remainder from [prod1 prod0].\\n uint256 remainder;\\n assembly {\\n // Compute remainder using mulmod.\\n remainder := mulmod(x, y, denominator)\\n\\n // Subtract 256 bit number from 512 bit number.\\n prod1 := sub(prod1, gt(remainder, prod0))\\n prod0 := sub(prod0, remainder)\\n }\\n\\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\\n // See https://cs.stackexchange.com/q/138556/92363.\\n\\n // Does not overflow because the denominator cannot be zero at this stage in the function.\\n uint256 twos = denominator & (~denominator + 1);\\n assembly {\\n // Divide denominator by twos.\\n denominator := div(denominator, twos)\\n\\n // Divide [prod1 prod0] by twos.\\n prod0 := div(prod0, twos)\\n\\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\\n twos := add(div(sub(0, twos), twos), 1)\\n }\\n\\n // Shift in bits from prod1 into prod0.\\n prod0 |= prod1 * twos;\\n\\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\\n // four bits. That is, denominator * inv = 1 mod 2^4.\\n uint256 inverse = (3 * denominator) ^ 2;\\n\\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\\n // in modular arithmetic, doubling the correct bits in each step.\\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\\n\\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\\n // is no longer required.\\n result = prod0 * inverse;\\n return result;\\n }\\n }\\n\\n /**\\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\\n */\\n function mulDiv(\\n uint256 x,\\n uint256 y,\\n uint256 denominator,\\n Rounding rounding\\n ) internal pure returns (uint256) {\\n uint256 result = mulDiv(x, y, denominator);\\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\\n result += 1;\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\\n *\\n * Inspired by Henry S. Warren, Jr.'s \\\"Hacker's Delight\\\" (Chapter 11).\\n */\\n function sqrt(uint256 a) internal pure returns (uint256) {\\n if (a == 0) {\\n return 0;\\n }\\n\\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\\n //\\n // We know that the \\\"msb\\\" (most significant bit) of our target number `a` is a power of 2 such that we have\\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\\n //\\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\\n // \\u2192 `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\\n // \\u2192 `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\\n //\\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\\n uint256 result = 1 << (log2(a) >> 1);\\n\\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\\n // into the expected uint128 result.\\n unchecked {\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n result = (result + a / result) >> 1;\\n return min(result, a / result);\\n }\\n }\\n\\n /**\\n * @notice Calculates sqrt(a), following the selected rounding direction.\\n */\\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = sqrt(a);\\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 2, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 128;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 64;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 32;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 16;\\n }\\n if (value >> 8 > 0) {\\n value >>= 8;\\n result += 8;\\n }\\n if (value >> 4 > 0) {\\n value >>= 4;\\n result += 4;\\n }\\n if (value >> 2 > 0) {\\n value >>= 2;\\n result += 2;\\n }\\n if (value >> 1 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log2(value);\\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 10, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >= 10**64) {\\n value /= 10**64;\\n result += 64;\\n }\\n if (value >= 10**32) {\\n value /= 10**32;\\n result += 32;\\n }\\n if (value >= 10**16) {\\n value /= 10**16;\\n result += 16;\\n }\\n if (value >= 10**8) {\\n value /= 10**8;\\n result += 8;\\n }\\n if (value >= 10**4) {\\n value /= 10**4;\\n result += 4;\\n }\\n if (value >= 10**2) {\\n value /= 10**2;\\n result += 2;\\n }\\n if (value >= 10**1) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log10(value);\\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\\n }\\n }\\n\\n /**\\n * @dev Return the log in base 256, rounded down, of a positive value.\\n * Returns 0 if given 0.\\n *\\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\\n */\\n function log256(uint256 value) internal pure returns (uint256) {\\n uint256 result = 0;\\n unchecked {\\n if (value >> 128 > 0) {\\n value >>= 128;\\n result += 16;\\n }\\n if (value >> 64 > 0) {\\n value >>= 64;\\n result += 8;\\n }\\n if (value >> 32 > 0) {\\n value >>= 32;\\n result += 4;\\n }\\n if (value >> 16 > 0) {\\n value >>= 16;\\n result += 2;\\n }\\n if (value >> 8 > 0) {\\n result += 1;\\n }\\n }\\n return result;\\n }\\n\\n /**\\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\\n * Returns 0 if given 0.\\n */\\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\\n unchecked {\\n uint256 result = log256(value);\\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa1e8e83cd0087785df04ac79fb395d9f3684caeaf973d9e2c71caef723a3a5d6\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Library for managing\\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\\n * types.\\n *\\n * Sets have the following properties:\\n *\\n * - Elements are added, removed, and checked for existence in constant time\\n * (O(1)).\\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\\n *\\n * ```\\n * contract Example {\\n * // Add the library methods\\n * using EnumerableSet for EnumerableSet.AddressSet;\\n *\\n * // Declare a set state variable\\n * EnumerableSet.AddressSet private mySet;\\n * }\\n * ```\\n *\\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\\n * and `uint256` (`UintSet`) are supported.\\n *\\n * [WARNING]\\n * ====\\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\\n * unusable.\\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\\n *\\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\\n * array of EnumerableSet.\\n * ====\\n */\\nlibrary EnumerableSet {\\n // To implement this library for multiple types with as little code\\n // repetition as possible, we write it in terms of a generic Set type with\\n // bytes32 values.\\n // The Set implementation uses private functions, and user-facing\\n // implementations (such as AddressSet) are just wrappers around the\\n // underlying Set.\\n // This means that we can only create new EnumerableSets for types that fit\\n // in bytes32.\\n\\n struct Set {\\n // Storage of set values\\n bytes32[] _values;\\n // Position of the value in the `values` array, plus 1 because index 0\\n // means a value is not in the set.\\n mapping(bytes32 => uint256) _indexes;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function _add(Set storage set, bytes32 value) private returns (bool) {\\n if (!_contains(set, value)) {\\n set._values.push(value);\\n // The value is stored at length-1, but we add 1 to all indexes\\n // and use 0 as a sentinel value\\n set._indexes[value] = set._values.length;\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function _remove(Set storage set, bytes32 value) private returns (bool) {\\n // We read and store the value's index to prevent multiple reads from the same storage slot\\n uint256 valueIndex = set._indexes[value];\\n\\n if (valueIndex != 0) {\\n // Equivalent to contains(set, value)\\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\\n // the array, and then remove the last element (sometimes called as 'swap and pop').\\n // This modifies the order of the array, as noted in {at}.\\n\\n uint256 toDeleteIndex = valueIndex - 1;\\n uint256 lastIndex = set._values.length - 1;\\n\\n if (lastIndex != toDeleteIndex) {\\n bytes32 lastValue = set._values[lastIndex];\\n\\n // Move the last value to the index where the value to delete is\\n set._values[toDeleteIndex] = lastValue;\\n // Update the index for the moved value\\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\\n }\\n\\n // Delete the slot where the moved value was stored\\n set._values.pop();\\n\\n // Delete the index for the deleted slot\\n delete set._indexes[value];\\n\\n return true;\\n } else {\\n return false;\\n }\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\\n return set._indexes[value] != 0;\\n }\\n\\n /**\\n * @dev Returns the number of values on the set. O(1).\\n */\\n function _length(Set storage set) private view returns (uint256) {\\n return set._values.length;\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\\n return set._values[index];\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function _values(Set storage set) private view returns (bytes32[] memory) {\\n return set._values;\\n }\\n\\n // Bytes32Set\\n\\n struct Bytes32Set {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _add(set._inner, value);\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\\n return _remove(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\\n return _contains(set._inner, value);\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(Bytes32Set storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\\n return _at(set._inner, index);\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n bytes32[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // AddressSet\\n\\n struct AddressSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(AddressSet storage set, address value) internal returns (bool) {\\n return _add(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(AddressSet storage set, address value) internal returns (bool) {\\n return _remove(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(AddressSet storage set, address value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(uint256(uint160(value))));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(AddressSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\\n return address(uint160(uint256(_at(set._inner, index))));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(AddressSet storage set) internal view returns (address[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n address[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n\\n // UintSet\\n\\n struct UintSet {\\n Set _inner;\\n }\\n\\n /**\\n * @dev Add a value to a set. O(1).\\n *\\n * Returns true if the value was added to the set, that is if it was not\\n * already present.\\n */\\n function add(UintSet storage set, uint256 value) internal returns (bool) {\\n return _add(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Removes a value from a set. O(1).\\n *\\n * Returns true if the value was removed from the set, that is if it was\\n * present.\\n */\\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\\n return _remove(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns true if the value is in the set. O(1).\\n */\\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\\n return _contains(set._inner, bytes32(value));\\n }\\n\\n /**\\n * @dev Returns the number of values in the set. O(1).\\n */\\n function length(UintSet storage set) internal view returns (uint256) {\\n return _length(set._inner);\\n }\\n\\n /**\\n * @dev Returns the value stored at position `index` in the set. O(1).\\n *\\n * Note that there are no guarantees on the ordering of values inside the\\n * array, and it may change when more values are added or removed.\\n *\\n * Requirements:\\n *\\n * - `index` must be strictly less than {length}.\\n */\\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\\n return uint256(_at(set._inner, index));\\n }\\n\\n /**\\n * @dev Return the entire set in an array\\n *\\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\\n */\\n function values(UintSet storage set) internal view returns (uint256[] memory) {\\n bytes32[] memory store = _values(set._inner);\\n uint256[] memory result;\\n\\n /// @solidity memory-safe-assembly\\n assembly {\\n result := store\\n }\\n\\n return result;\\n }\\n}\\n\",\"keccak256\":\"0xc3ff3f5c4584e1d9a483ad7ced51ab64523201f4e3d3c65293e4ca8aeb77a961\",\"license\":\"MIT\"},\"contracts/Configuration.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\n\\nstruct MarketplaceConfig {\\n CollateralConfig collateral;\\n ProofConfig proofs;\\n SlotReservationsConfig reservations;\\n}\\n\\nstruct CollateralConfig {\\n /// @dev percentage of remaining collateral slot after it has been freed\\n /// (equivalent to `collateral - (collateral*maxNumberOfSlashes*slashPercentage)/100`)\\n /// TODO: to be aligned more closely with actual cost of repair once bandwidth incentives are known,\\n /// see https://github.com/codex-storage/codex-contracts-eth/pull/47#issuecomment-1465511949.\\n uint8 repairRewardPercentage;\\n uint8 maxNumberOfSlashes; // frees slot when the number of slashing reaches this value\\n uint16 slashCriterion; // amount of proofs missed that lead to slashing\\n uint8 slashPercentage; // percentage of the collateral that is slashed\\n}\\n\\nstruct ProofConfig {\\n uint256 period; // proofs requirements are calculated per period (in seconds)\\n uint256 timeout; // mark proofs as missing before the timeout (in seconds)\\n uint8 downtime; // ignore this much recent blocks for proof requirements\\n string zkeyHash; // hash of the zkey file which is linked to the verifier\\n // Ensures the pointer does not remain in downtime for many consecutive\\n // periods. For each period increase, move the pointer `pointerProduct`\\n // blocks. Should be a prime number to ensure there are no cycles.\\n uint8 downtimeProduct;\\n}\\n\\nstruct SlotReservationsConfig {\\n // Number of allowed reservations per slot\\n uint8 maxReservations;\\n}\\n\",\"keccak256\":\"0x76c7a6183e1031680ffc3e3a0bd52d257d43ee7311aebdd542949894dfddf9ac\",\"license\":\"MIT\"},\"contracts/Endian.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\ncontract Endian {\\n /// reverses byte order to allow conversion between little endian and big\\n /// endian integers\\n function _byteSwap(bytes32 input) internal pure returns (bytes32 output) {\\n output = output | bytes1(input);\\n for (uint i = 1; i < 32; i++) {\\n output = output >> 8;\\n output = output | bytes1(input << (i * 8));\\n }\\n }\\n}\\n\",\"keccak256\":\"0xd6acc2a19aaedc1b903681fedf6e302aabdd33695dee215e21b5190a83d0769e\",\"license\":\"MIT\"},\"contracts/Groth16.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nstruct G1Point {\\n uint256 x;\\n uint256 y;\\n}\\n\\n// A field element F_{p^2} encoded as `real + i * imag`.\\n// We chose to not represent this as an array of 2 numbers, because both Circom\\n// and Ethereum EIP-197 encode to an array, but with conflicting encodings.\\nstruct Fp2Element {\\n uint256 real;\\n uint256 imag;\\n}\\n\\nstruct G2Point {\\n Fp2Element x;\\n Fp2Element y;\\n}\\n\\nstruct Groth16Proof {\\n G1Point a;\\n G2Point b;\\n G1Point c;\\n}\\n\\ninterface IGroth16Verifier {\\n function verify(\\n Groth16Proof calldata proof,\\n uint256[] calldata pubSignals\\n ) external view returns (bool);\\n}\\n\",\"keccak256\":\"0xe1c7a8730cf718c9b69052c81ca3241d7f61c25f3d7944962077d768bf601baf\",\"license\":\"MIT\"},\"contracts/Marketplace.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/Math.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"./Configuration.sol\\\";\\nimport \\\"./Requests.sol\\\";\\nimport \\\"./Proofs.sol\\\";\\nimport \\\"./SlotReservations.sol\\\";\\nimport \\\"./StateRetrieval.sol\\\";\\nimport \\\"./Endian.sol\\\";\\nimport \\\"./Groth16.sol\\\";\\n\\ncontract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using EnumerableSet for EnumerableSet.AddressSet;\\n using Requests for Request;\\n\\n IERC20 private immutable _token;\\n MarketplaceConfig private _config;\\n\\n mapping(RequestId => Request) private _requests;\\n mapping(RequestId => RequestContext) internal _requestContexts;\\n mapping(SlotId => Slot) internal _slots;\\n\\n MarketplaceTotals internal _marketplaceTotals;\\n\\n struct RequestContext {\\n RequestState state;\\n uint256 slotsFilled;\\n /// @notice Tracks how much funds should be returned to the client as not all funds might be used for hosting the request\\n /// @dev The sum starts with the full reward amount for the request and is reduced every time a host fills a slot.\\n /// The reduction is calculated from the duration of time between the slot being filled and the request's end.\\n /// This is the amount that will be paid out to the host when the request successfully finishes.\\n /// @dev fundsToReturnToClient == 0 is used to signal that after request is terminated all the remaining funds were withdrawn.\\n /// This is possible, because technically it is not possible for this variable to reach 0 in \\\"natural\\\" way as\\n /// that would require all the slots to be filled at the same block as the request was created.\\n uint256 fundsToReturnToClient;\\n uint256 startedAt;\\n uint256 endsAt;\\n uint256 expiresAt;\\n }\\n\\n struct Slot {\\n SlotState state;\\n RequestId requestId;\\n /// @notice Timestamp that signals when slot was filled\\n /// @dev Used for calculating payouts as hosts are paid based on time they actually host the content\\n uint256 filledAt;\\n uint256 slotIndex;\\n /// @notice Tracks the current amount of host's collateral that is to be payed out at the end of Slot's lifespan.\\n /// @dev When Slot is filled, the collateral is collected in amount of request.ask.collateral\\n /// @dev When Host is slashed for missing a proof the slashed amount is reflected in this variable\\n uint256 currentCollateral;\\n address host; // address used for collateral interactions and identifying hosts\\n }\\n\\n struct ActiveSlot {\\n Request request;\\n uint256 slotIndex;\\n }\\n\\n constructor(\\n MarketplaceConfig memory configuration,\\n IERC20 token_,\\n IGroth16Verifier verifier\\n )\\n SlotReservations(configuration.reservations)\\n Proofs(configuration.proofs, verifier)\\n {\\n _token = token_;\\n\\n require(\\n configuration.collateral.repairRewardPercentage <= 100,\\n \\\"Must be less than 100\\\"\\n );\\n require(\\n configuration.collateral.slashPercentage <= 100,\\n \\\"Must be less than 100\\\"\\n );\\n require(\\n configuration.collateral.maxNumberOfSlashes *\\n configuration.collateral.slashPercentage <=\\n 100,\\n \\\"Maximum slashing exceeds 100%\\\"\\n );\\n _config = configuration;\\n }\\n\\n function config() public view returns (MarketplaceConfig memory) {\\n return _config;\\n }\\n\\n function token() public view returns (IERC20) {\\n return _token;\\n }\\n\\n function requestStorage(Request calldata request) public {\\n require(request.client == msg.sender, \\\"Invalid client address\\\");\\n\\n RequestId id = request.id();\\n require(_requests[id].client == address(0), \\\"Request already exists\\\");\\n require(\\n request.expiry > 0 && request.expiry < request.ask.duration,\\n \\\"Expiry not in range\\\"\\n );\\n require(request.ask.slots > 0, \\\"Insufficient slots\\\");\\n require(\\n request.ask.maxSlotLoss <= request.ask.slots,\\n \\\"maxSlotLoss exceeds slots\\\"\\n );\\n\\n _requests[id] = request;\\n _requestContexts[id].endsAt = block.timestamp + request.ask.duration;\\n _requestContexts[id].expiresAt = block.timestamp + request.expiry;\\n\\n _addToMyRequests(request.client, id);\\n\\n uint256 amount = request.maxPrice();\\n _requestContexts[id].fundsToReturnToClient = amount;\\n _marketplaceTotals.received += amount;\\n _transferFrom(msg.sender, amount);\\n\\n emit StorageRequested(id, request.ask, _requestContexts[id].expiresAt);\\n }\\n\\n /**\\n * @notice Fills a slot. Reverts if an invalid proof of the slot data is\\n provided.\\n * @param requestId RequestId identifying the request containing the slot to\\n fill.\\n * @param slotIndex Index of the slot in the request.\\n * @param proof Groth16 proof procing possession of the slot data.\\n */\\n function fillSlot(\\n RequestId requestId,\\n uint256 slotIndex,\\n Groth16Proof calldata proof\\n ) public requestIsKnown(requestId) {\\n Request storage request = _requests[requestId];\\n require(slotIndex < request.ask.slots, \\\"Invalid slot\\\");\\n\\n SlotId slotId = Requests.slotId(requestId, slotIndex);\\n require(_reservations[slotId].contains(msg.sender), \\\"Reservation required\\\");\\n\\n Slot storage slot = _slots[slotId];\\n slot.requestId = requestId;\\n slot.slotIndex = slotIndex;\\n RequestContext storage context = _requestContexts[requestId];\\n\\n require(slotState(slotId) == SlotState.Free, \\\"Slot is not free\\\");\\n\\n _startRequiringProofs(slotId, request.ask.proofProbability);\\n submitProof(slotId, proof);\\n\\n slot.host = msg.sender;\\n slot.state = SlotState.Filled;\\n slot.filledAt = block.timestamp;\\n\\n context.slotsFilled += 1;\\n context.fundsToReturnToClient -= _slotPayout(requestId, slot.filledAt);\\n\\n // Collect collateral\\n uint256 collateralAmount = request.ask.collateral;\\n _transferFrom(msg.sender, collateralAmount);\\n _marketplaceTotals.received += collateralAmount;\\n slot.currentCollateral = collateralAmount;\\n\\n _addToMySlots(slot.host, slotId);\\n\\n emit SlotFilled(requestId, slotIndex);\\n if (context.slotsFilled == request.ask.slots) {\\n context.state = RequestState.Started;\\n context.startedAt = block.timestamp;\\n emit RequestFulfilled(requestId);\\n }\\n }\\n\\n /**\\n * @notice Frees a slot, paying out rewards and returning collateral for\\n finished or cancelled requests to the host that has filled the slot.\\n * @param slotId id of the slot to free\\n * @dev The host that filled the slot must have initiated the transaction\\n (msg.sender). This overload allows `rewardRecipient` and\\n `collateralRecipient` to be optional.\\n */\\n function freeSlot(SlotId slotId) public slotIsNotFree(slotId) {\\n return freeSlot(slotId, msg.sender, msg.sender);\\n }\\n\\n /**\\n * @notice Frees a slot, paying out rewards and returning collateral for\\n finished or cancelled requests.\\n * @param slotId id of the slot to free\\n * @param rewardRecipient address to send rewards to\\n * @param collateralRecipient address to refund collateral to\\n */\\n function freeSlot(\\n SlotId slotId,\\n address rewardRecipient,\\n address collateralRecipient\\n ) public slotIsNotFree(slotId) {\\n Slot storage slot = _slots[slotId];\\n require(slot.host == msg.sender, \\\"Slot filled by other host\\\");\\n SlotState state = slotState(slotId);\\n require(state != SlotState.Paid, \\\"Already paid\\\");\\n\\n if (state == SlotState.Finished) {\\n _payoutSlot(slot.requestId, slotId, rewardRecipient, collateralRecipient);\\n } else if (state == SlotState.Cancelled) {\\n _payoutCancelledSlot(\\n slot.requestId,\\n slotId,\\n rewardRecipient,\\n collateralRecipient\\n );\\n } else if (state == SlotState.Failed) {\\n _removeFromMySlots(msg.sender, slotId);\\n } else if (state == SlotState.Filled) {\\n // free slot without returning collateral, effectively a 100% slash\\n _forciblyFreeSlot(slotId);\\n }\\n }\\n\\n function _challengeToFieldElement(\\n bytes32 challenge\\n ) internal pure returns (uint256) {\\n // use only 31 bytes of the challenge to ensure that it fits into the field\\n bytes32 truncated = bytes32(bytes31(challenge));\\n // convert from little endian to big endian\\n bytes32 bigEndian = _byteSwap(truncated);\\n // convert bytes to integer\\n return uint256(bigEndian);\\n }\\n\\n function _merkleRootToFieldElement(\\n bytes32 merkleRoot\\n ) internal pure returns (uint256) {\\n // convert from little endian to big endian\\n bytes32 bigEndian = _byteSwap(merkleRoot);\\n // convert bytes to integer\\n return uint256(bigEndian);\\n }\\n\\n function submitProof(\\n SlotId id,\\n Groth16Proof calldata proof\\n ) public requestIsKnown(_slots[id].requestId) {\\n Slot storage slot = _slots[id];\\n Request storage request = _requests[slot.requestId];\\n uint256[] memory pubSignals = new uint256[](3);\\n pubSignals[0] = _challengeToFieldElement(getChallenge(id));\\n pubSignals[1] = _merkleRootToFieldElement(request.content.merkleRoot);\\n pubSignals[2] = slot.slotIndex;\\n _proofReceived(id, proof, pubSignals);\\n }\\n\\n function markProofAsMissing(SlotId slotId, Period period) public {\\n require(slotState(slotId) == SlotState.Filled, \\\"Slot not accepting proofs\\\");\\n _markProofAsMissing(slotId, period);\\n Slot storage slot = _slots[slotId];\\n Request storage request = _requests[slot.requestId];\\n\\n // TODO: Reward for validator that calls this function\\n\\n if (missingProofs(slotId) % _config.collateral.slashCriterion == 0) {\\n uint256 slashedAmount = (request.ask.collateral *\\n _config.collateral.slashPercentage) / 100;\\n slot.currentCollateral -= slashedAmount;\\n if (\\n missingProofs(slotId) / _config.collateral.slashCriterion >=\\n _config.collateral.maxNumberOfSlashes\\n ) {\\n // When the number of slashings is at or above the allowed amount,\\n // free the slot.\\n _forciblyFreeSlot(slotId);\\n }\\n }\\n }\\n\\n /**\\n * @notice Abandons the slot without returning collateral, effectively slashing the\\n entire collateral.\\n * @param slotId SlotId of the slot to free.\\n * @dev _slots[slotId] is deleted, resetting _slots[slotId].currentCollateral\\n to 0.\\n */\\n function _forciblyFreeSlot(SlotId slotId) internal {\\n Slot storage slot = _slots[slotId];\\n RequestId requestId = slot.requestId;\\n RequestContext storage context = _requestContexts[requestId];\\n\\n // We need to refund the amount of payout of the current node to the `fundsToReturnToClient` so\\n // we keep correctly the track of the funds that needs to be returned at the end.\\n context.fundsToReturnToClient += _slotPayout(requestId, slot.filledAt);\\n\\n _removeFromMySlots(slot.host, slotId);\\n uint256 slotIndex = slot.slotIndex;\\n delete _slots[slotId];\\n context.slotsFilled -= 1;\\n emit SlotFreed(requestId, slotIndex);\\n _resetMissingProofs(slotId);\\n\\n Request storage request = _requests[requestId];\\n uint256 slotsLost = request.ask.slots - context.slotsFilled;\\n if (\\n slotsLost > request.ask.maxSlotLoss &&\\n context.state == RequestState.Started\\n ) {\\n context.state = RequestState.Failed;\\n context.endsAt = block.timestamp - 1;\\n emit RequestFailed(requestId);\\n }\\n }\\n\\n function _payoutSlot(\\n RequestId requestId,\\n SlotId slotId,\\n address rewardRecipient,\\n address collateralRecipient\\n ) private requestIsKnown(requestId) {\\n RequestContext storage context = _requestContexts[requestId];\\n Request storage request = _requests[requestId];\\n context.state = RequestState.Finished;\\n Slot storage slot = _slots[slotId];\\n\\n _removeFromMyRequests(request.client, requestId);\\n _removeFromMySlots(slot.host, slotId);\\n\\n uint256 payoutAmount = _slotPayout(requestId, slot.filledAt);\\n uint256 collateralAmount = slot.currentCollateral;\\n _marketplaceTotals.sent += (payoutAmount + collateralAmount);\\n slot.state = SlotState.Paid;\\n assert(_token.transfer(rewardRecipient, payoutAmount));\\n assert(_token.transfer(collateralRecipient, collateralAmount));\\n }\\n\\n /**\\n * @notice Pays out a host for duration of time that the slot was filled, and\\n returns the collateral.\\n * @dev The payouts are sent to the rewardRecipient, and collateral is returned\\n to the host address.\\n * @param requestId RequestId of the request that contains the slot to be paid\\n out.\\n * @param slotId SlotId of the slot to be paid out.\\n */\\n function _payoutCancelledSlot(\\n RequestId requestId,\\n SlotId slotId,\\n address rewardRecipient,\\n address collateralRecipient\\n ) private requestIsKnown(requestId) {\\n Slot storage slot = _slots[slotId];\\n _removeFromMySlots(slot.host, slotId);\\n\\n uint256 payoutAmount = _slotPayout(\\n requestId,\\n slot.filledAt,\\n requestExpiry(requestId)\\n );\\n uint256 collateralAmount = slot.currentCollateral;\\n _marketplaceTotals.sent += (payoutAmount + collateralAmount);\\n slot.state = SlotState.Paid;\\n assert(_token.transfer(rewardRecipient, payoutAmount));\\n assert(_token.transfer(collateralRecipient, collateralAmount));\\n }\\n\\n /**\\n * @notice Withdraws remaining storage request funds back to the client that\\n deposited them.\\n * @dev Request must be cancelled, failed or finished, and the\\n transaction must originate from the depositor address.\\n * @param requestId the id of the request\\n */\\n function withdrawFunds(RequestId requestId) public {\\n withdrawFunds(requestId, msg.sender);\\n }\\n\\n /**\\n * @notice Withdraws storage request funds to the provided address.\\n * @dev Request must be expired, must be in RequestState.New, and the\\n transaction must originate from the depositer address.\\n * @param requestId the id of the request\\n * @param withdrawRecipient address to return the remaining funds to\\n */\\n function withdrawFunds(\\n RequestId requestId,\\n address withdrawRecipient\\n ) public {\\n Request storage request = _requests[requestId];\\n require(request.client == msg.sender, \\\"Invalid client address\\\");\\n RequestContext storage context = _requestContexts[requestId];\\n RequestState state = requestState(requestId);\\n require(\\n state == RequestState.Cancelled ||\\n state == RequestState.Failed ||\\n state == RequestState.Finished,\\n \\\"Invalid state\\\"\\n );\\n\\n // fundsToReturnToClient == 0 is used for \\\"double-spend\\\" protection, once the funds are withdrawn\\n // then this variable is set to 0.\\n require(context.fundsToReturnToClient != 0, \\\"Nothing to withdraw\\\");\\n\\n if (state == RequestState.Cancelled) {\\n context.state = RequestState.Cancelled;\\n emit RequestCancelled(requestId);\\n\\n // `fundsToReturnToClient` currently tracks funds to be returned for requests that successfully finish.\\n // When requests are cancelled, funds earmarked for payment for the duration\\n // between request expiry and request end (for every slot that was filled), should be returned to the client.\\n // Update `fundsToReturnToClient` to reflect this.\\n context.fundsToReturnToClient +=\\n context.slotsFilled *\\n _slotPayout(requestId, requestExpiry(requestId));\\n } else if (state == RequestState.Failed) {\\n // For Failed requests the client is refunded whole amount.\\n context.fundsToReturnToClient = request.maxPrice();\\n } else {\\n context.state = RequestState.Finished;\\n }\\n\\n _removeFromMyRequests(request.client, requestId);\\n\\n uint256 amount = context.fundsToReturnToClient;\\n _marketplaceTotals.sent += amount;\\n assert(_token.transfer(withdrawRecipient, amount));\\n\\n // We zero out the funds tracking in order to prevent double-spends\\n context.fundsToReturnToClient = 0;\\n }\\n\\n function getActiveSlot(\\n SlotId slotId\\n ) public view slotIsNotFree(slotId) returns (ActiveSlot memory) {\\n Slot storage slot = _slots[slotId];\\n ActiveSlot memory activeSlot;\\n activeSlot.request = _requests[slot.requestId];\\n activeSlot.slotIndex = slot.slotIndex;\\n return activeSlot;\\n }\\n\\n modifier requestIsKnown(RequestId requestId) {\\n require(_requests[requestId].client != address(0), \\\"Unknown request\\\");\\n _;\\n }\\n\\n function getRequest(\\n RequestId requestId\\n ) public view requestIsKnown(requestId) returns (Request memory) {\\n return _requests[requestId];\\n }\\n\\n modifier slotIsNotFree(SlotId slotId) {\\n require(_slots[slotId].state != SlotState.Free, \\\"Slot is free\\\");\\n _;\\n }\\n\\n function requestEnd(RequestId requestId) public view returns (uint256) {\\n uint256 end = _requestContexts[requestId].endsAt;\\n RequestState state = requestState(requestId);\\n if (state == RequestState.New || state == RequestState.Started) {\\n return end;\\n } else {\\n return Math.min(end, block.timestamp - 1);\\n }\\n }\\n\\n function requestExpiry(RequestId requestId) public view returns (uint256) {\\n return _requestContexts[requestId].expiresAt;\\n }\\n\\n /**\\n * @notice Calculates the amount that should be paid out to a host that successfully finished the request\\n * @param requestId RequestId of the request used to calculate the payout\\n * amount.\\n * @param startingTimestamp timestamp indicating when a host filled a slot and\\n * started providing proofs.\\n */\\n function _slotPayout(\\n RequestId requestId,\\n uint256 startingTimestamp\\n ) private view returns (uint256) {\\n return\\n _slotPayout(\\n requestId,\\n startingTimestamp,\\n _requestContexts[requestId].endsAt\\n );\\n }\\n\\n /// @notice Calculates the amount that should be paid out to a host based on the specified time frame.\\n function _slotPayout(\\n RequestId requestId,\\n uint256 startingTimestamp,\\n uint256 endingTimestamp\\n ) private view returns (uint256) {\\n Request storage request = _requests[requestId];\\n require(startingTimestamp < endingTimestamp, \\\"Start not before expiry\\\");\\n\\n return (endingTimestamp - startingTimestamp) * request.ask.reward;\\n }\\n\\n function getHost(SlotId slotId) public view returns (address) {\\n return _slots[slotId].host;\\n }\\n\\n function requestState(\\n RequestId requestId\\n ) public view requestIsKnown(requestId) returns (RequestState) {\\n RequestContext storage context = _requestContexts[requestId];\\n if (\\n context.state == RequestState.New &&\\n block.timestamp > requestExpiry(requestId)\\n ) {\\n return RequestState.Cancelled;\\n } else if (\\n (context.state == RequestState.Started ||\\n context.state == RequestState.New) && block.timestamp > context.endsAt\\n ) {\\n return RequestState.Finished;\\n } else {\\n return context.state;\\n }\\n }\\n\\n function slotState(SlotId slotId) public view override returns (SlotState) {\\n Slot storage slot = _slots[slotId];\\n if (RequestId.unwrap(slot.requestId) == 0) {\\n return SlotState.Free;\\n }\\n RequestState reqState = requestState(slot.requestId);\\n if (slot.state == SlotState.Paid) {\\n return SlotState.Paid;\\n }\\n if (reqState == RequestState.Cancelled) {\\n return SlotState.Cancelled;\\n }\\n if (reqState == RequestState.Finished) {\\n return SlotState.Finished;\\n }\\n if (reqState == RequestState.Failed) {\\n return SlotState.Failed;\\n }\\n return slot.state;\\n }\\n\\n function _transferFrom(address sender, uint256 amount) internal {\\n address receiver = address(this);\\n require(_token.transferFrom(sender, receiver, amount), \\\"Transfer failed\\\");\\n }\\n\\n event StorageRequested(RequestId requestId, Ask ask, uint256 expiry);\\n event RequestFulfilled(RequestId indexed requestId);\\n event RequestFailed(RequestId indexed requestId);\\n event SlotFilled(RequestId indexed requestId, uint256 slotIndex);\\n event SlotFreed(RequestId indexed requestId, uint256 slotIndex);\\n event RequestCancelled(RequestId indexed requestId);\\n\\n struct MarketplaceTotals {\\n uint256 received;\\n uint256 sent;\\n }\\n}\\n\",\"keccak256\":\"0x652d911cbc7355ffeef72ee2ae851fe2768318fb3fc01f3aa749bff5b69c0e5f\",\"license\":\"MIT\"},\"contracts/Periods.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\ncontract Periods {\\n type Period is uint256;\\n\\n uint256 internal immutable _secondsPerPeriod;\\n\\n constructor(uint256 secondsPerPeriod) {\\n _secondsPerPeriod = secondsPerPeriod;\\n }\\n\\n function _periodOf(uint256 timestamp) internal view returns (Period) {\\n return Period.wrap(timestamp / _secondsPerPeriod);\\n }\\n\\n function _blockPeriod() internal view returns (Period) {\\n return _periodOf(block.timestamp);\\n }\\n\\n function _nextPeriod(Period period) internal pure returns (Period) {\\n return Period.wrap(Period.unwrap(period) + 1);\\n }\\n\\n function _periodStart(Period period) internal view returns (uint256) {\\n return Period.unwrap(period) * _secondsPerPeriod;\\n }\\n\\n function _periodEnd(Period period) internal view returns (uint256) {\\n return _periodStart(_nextPeriod(period));\\n }\\n\\n function _isBefore(Period a, Period b) internal pure returns (bool) {\\n return Period.unwrap(a) < Period.unwrap(b);\\n }\\n\\n function _isAfter(Period a, Period b) internal pure returns (bool) {\\n return _isBefore(b, a);\\n }\\n}\\n\",\"keccak256\":\"0xd70cb0ff823e635a1f52f39d8d32451d2d17d2588dc0a894d28432af72f878ff\",\"license\":\"MIT\"},\"contracts/Proofs.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"./Configuration.sol\\\";\\nimport \\\"./Requests.sol\\\";\\nimport \\\"./Periods.sol\\\";\\nimport \\\"./Groth16.sol\\\";\\n\\n/**\\n * @title Proofs\\n * @notice Abstract contract that handles proofs tracking, validation and reporting functionality\\n */\\nabstract contract Proofs is Periods {\\n ProofConfig private _config;\\n IGroth16Verifier private _verifier;\\n\\n /**\\n * Creation of the contract requires at least 256 mined blocks!\\n * @param config Proving configuration\\n */\\n constructor(\\n ProofConfig memory config,\\n IGroth16Verifier verifier\\n ) Periods(config.period) {\\n require(block.number > 256, \\\"Insufficient block height\\\");\\n _config = config;\\n _verifier = verifier;\\n }\\n\\n mapping(SlotId => uint256) private _slotStarts; // TODO: Should be smaller than uint256\\n mapping(SlotId => uint256) private _probabilities;\\n mapping(SlotId => uint256) private _missed; // TODO: Should be smaller than uint256\\n mapping(SlotId => mapping(Period => bool)) private _received;\\n mapping(SlotId => mapping(Period => bool)) private _missing;\\n\\n function slotState(SlotId id) public view virtual returns (SlotState);\\n\\n /**\\n * @return Number of missed proofs since Slot was Filled\\n */\\n function missingProofs(SlotId slotId) public view returns (uint256) {\\n return _missed[slotId];\\n }\\n\\n /**\\n * @param slotId Slot's ID for which the proofs should be reset\\n * @notice Resets the missing proofs counter to zero\\n */\\n function _resetMissingProofs(SlotId slotId) internal {\\n _missed[slotId] = 0;\\n }\\n\\n /**\\n * @param id Slot's ID for which the proofs should be started to require\\n * @param probability Integer which specifies the probability of how often the proofs will be required. Lower number means higher probability.\\n * @notice Notes down the block's timestamp as Slot's starting time for requiring proofs\\n * and saves the required probability.\\n */\\n function _startRequiringProofs(SlotId id, uint256 probability) internal {\\n _slotStarts[id] = block.timestamp;\\n _probabilities[id] = probability;\\n }\\n\\n /**\\n * @param id Slot's ID for which the pointer should be calculated\\n * @param period Period for which the pointer should be calculated\\n * @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\\n * @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\\n */\\n function _getPointer(SlotId id, Period period) internal view returns (uint8) {\\n uint256 blockNumber = block.number % 256;\\n uint256 periodNumber = (Period.unwrap(period) * _config.downtimeProduct) %\\n 256;\\n uint256 idOffset = uint256(SlotId.unwrap(id)) % 256;\\n uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;\\n return uint8(pointer);\\n }\\n\\n /**\\n * @param id Slot's ID for which the pointer should be calculated\\n * @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\\n * @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\\n */\\n function getPointer(SlotId id) public view returns (uint8) {\\n return _getPointer(id, _blockPeriod());\\n }\\n\\n /**\\n * @param pointer Integer [0-255] that indicates an offset of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\\n * @return Challenge that should be used for generation of proofs\\n */\\n function _getChallenge(uint8 pointer) internal view returns (bytes32) {\\n bytes32 hash = blockhash(block.number - 1 - pointer);\\n assert(uint256(hash) != 0);\\n return keccak256(abi.encode(hash));\\n }\\n\\n /**\\n * @param id Slot's ID for which the challenge should be calculated\\n * @param period Period for which the challenge should be calculated\\n * @return Challenge that should be used for generation of proofs\\n */\\n function _getChallenge(\\n SlotId id,\\n Period period\\n ) internal view returns (bytes32) {\\n return _getChallenge(_getPointer(id, period));\\n }\\n\\n /**\\n * @param id Slot's ID for which the challenge should be calculated\\n * @return Challenge for current Period that should be used for generation of proofs\\n */\\n function getChallenge(SlotId id) public view returns (bytes32) {\\n return _getChallenge(id, _blockPeriod());\\n }\\n\\n /**\\n * @param id Slot's ID for which the requirements are gathered. If the Slot's state is other than Filled, `false` is always returned.\\n * @param period Period for which the requirements are gathered.\\n */\\n function _getProofRequirement(\\n SlotId id,\\n Period period\\n ) internal view returns (bool isRequired, uint8 pointer) {\\n SlotState state = slotState(id);\\n Period start = _periodOf(_slotStarts[id]);\\n if (state != SlotState.Filled || !_isAfter(period, start)) {\\n return (false, 0);\\n }\\n pointer = _getPointer(id, period);\\n bytes32 challenge = _getChallenge(pointer);\\n\\n /// Scaling of the probability according the downtime configuration\\n /// See: https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime\\n uint256 probability = (_probabilities[id] * (256 - _config.downtime)) / 256;\\n isRequired = probability == 0 || uint256(challenge) % probability == 0;\\n }\\n\\n /**\\n * See isProofRequired\\n */\\n function _isProofRequired(\\n SlotId id,\\n Period period\\n ) internal view returns (bool) {\\n bool isRequired;\\n uint8 pointer;\\n (isRequired, pointer) = _getProofRequirement(id, period);\\n return isRequired && pointer >= _config.downtime;\\n }\\n\\n /**\\n * @param id Slot's ID for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\\n * @return bool indicating if proof is required for current period\\n */\\n function isProofRequired(SlotId id) public view returns (bool) {\\n return _isProofRequired(id, _blockPeriod());\\n }\\n\\n /**\\n * Proof Downtime specifies part of the Period when the proof is not required even\\n * if the proof should be required. This function returns true if the pointer is\\n * in downtime (hence no proof required now) and at the same time the proof\\n * will be required later on in the Period.\\n *\\n * @dev for more info about downtime see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime)\\n * @param id SlotId for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\\n * @return bool\\n */\\n function willProofBeRequired(SlotId id) public view returns (bool) {\\n bool isRequired;\\n uint8 pointer;\\n (isRequired, pointer) = _getProofRequirement(id, _blockPeriod());\\n return isRequired && pointer < _config.downtime;\\n }\\n\\n /**\\n * Function used for submitting and verification of the proofs.\\n *\\n * @dev Reverts when proof is invalid or had been already submitted.\\n * @dev Emits ProofSubmitted event.\\n * @param id Slot's ID for which the proof requirements should be checked\\n * @param proof Groth16 proof\\n * @param pubSignals Proofs public input\\n */\\n function _proofReceived(\\n SlotId id,\\n Groth16Proof calldata proof,\\n uint[] memory pubSignals\\n ) internal {\\n require(!_received[id][_blockPeriod()], \\\"Proof already submitted\\\");\\n require(_verifier.verify(proof, pubSignals), \\\"Invalid proof\\\");\\n _received[id][_blockPeriod()] = true;\\n emit ProofSubmitted(id);\\n }\\n\\n /**\\n * Function used to mark proof as missing.\\n *\\n * @param id Slot's ID for which the proof is missing\\n * @param missedPeriod Period for which the proof was missed\\n * @dev Reverts when:\\n * - missedPeriod has not ended yet ended\\n * - missing proof was time-barred\\n * - proof was submitted\\n * - proof was not required for missedPeriod period\\n * - proof was already marked as missing\\n */\\n function _markProofAsMissing(SlotId id, Period missedPeriod) internal {\\n uint256 end = _periodEnd(missedPeriod);\\n require(end < block.timestamp, \\\"Period has not ended yet\\\");\\n require(block.timestamp < end + _config.timeout, \\\"Validation timed out\\\");\\n require(!_received[id][missedPeriod], \\\"Proof was submitted, not missing\\\");\\n require(_isProofRequired(id, missedPeriod), \\\"Proof was not required\\\");\\n require(!_missing[id][missedPeriod], \\\"Proof already marked as missing\\\");\\n _missing[id][missedPeriod] = true;\\n _missed[id] += 1;\\n }\\n\\n event ProofSubmitted(SlotId id);\\n}\\n\",\"keccak256\":\"0x742a491cf61d941b39bc2694dd039917438276f881849922e51fb08360d32ef0\",\"license\":\"MIT\"},\"contracts/Requests.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\ntype RequestId is bytes32;\\ntype SlotId is bytes32;\\n\\nstruct Request {\\n address client;\\n Ask ask;\\n Content content;\\n uint256 expiry; // amount of seconds since start of the request at which this request expires\\n bytes32 nonce; // random nonce to differentiate between similar requests\\n}\\n\\nstruct Ask {\\n uint64 slots; // the number of requested slots\\n uint256 slotSize; // amount of storage per slot (in number of bytes)\\n uint256 duration; // how long content should be stored (in seconds)\\n uint256 proofProbability; // how often storage proofs are required\\n uint256 reward; // amount of tokens paid per second per slot to hosts\\n uint256 collateral; // amount of tokens required to be deposited by the hosts in order to fill the slot\\n uint64 maxSlotLoss; // Max slots that can be lost without data considered to be lost\\n}\\n\\nstruct Content {\\n string cid; // content id, used to download the dataset\\n bytes32 merkleRoot; // merkle root of the dataset, used to verify storage proofs\\n}\\n\\nenum RequestState {\\n New, // [default] waiting to fill slots\\n Started, // all slots filled, accepting regular proofs\\n Cancelled, // not enough slots filled before expiry\\n Finished, // successfully completed\\n Failed // too many nodes have failed to provide proofs, data lost\\n}\\n\\nenum SlotState {\\n Free, // [default] not filled yet, or host has vacated the slot\\n Filled, // host has filled slot\\n Finished, // successfully completed\\n Failed, // the request has failed\\n Paid, // host has been paid\\n Cancelled // when request was cancelled then slot is cancelled as well\\n}\\n\\nlibrary Requests {\\n function id(Request memory request) internal pure returns (RequestId) {\\n return RequestId.wrap(keccak256(abi.encode(request)));\\n }\\n\\n function slotId(\\n RequestId requestId,\\n uint256 slotIndex\\n ) internal pure returns (SlotId) {\\n return SlotId.wrap(keccak256(abi.encode(requestId, slotIndex)));\\n }\\n\\n function toRequestIds(\\n bytes32[] memory ids\\n ) internal pure returns (RequestId[] memory result) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := ids\\n }\\n }\\n\\n function toSlotIds(\\n bytes32[] memory ids\\n ) internal pure returns (SlotId[] memory result) {\\n // solhint-disable-next-line no-inline-assembly\\n assembly {\\n result := ids\\n }\\n }\\n\\n function maxPrice(Request memory request) internal pure returns (uint256) {\\n return request.ask.slots * request.ask.duration * request.ask.reward;\\n }\\n}\\n\",\"keccak256\":\"0x7ade8617cce1ac6149830ad180c07c8b041e6cddb3e8c83ecdd23994b3f13197\",\"license\":\"MIT\"},\"contracts/SlotReservations.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"./Requests.sol\\\";\\nimport \\\"./Configuration.sol\\\";\\n\\ncontract SlotReservations {\\n using EnumerableSet for EnumerableSet.AddressSet;\\n\\n mapping(SlotId => EnumerableSet.AddressSet) internal _reservations;\\n SlotReservationsConfig private _config;\\n\\n constructor(SlotReservationsConfig memory config) {\\n _config = config;\\n }\\n\\n function reserveSlot(RequestId requestId, uint256 slotIndex) public {\\n require(canReserveSlot(requestId, slotIndex), \\\"Reservation not allowed\\\");\\n\\n SlotId slotId = Requests.slotId(requestId, slotIndex);\\n _reservations[slotId].add(msg.sender);\\n\\n if (_reservations[slotId].length() == _config.maxReservations) {\\n emit SlotReservationsFull(requestId, slotIndex);\\n }\\n }\\n\\n function canReserveSlot(\\n RequestId requestId,\\n uint256 slotIndex\\n ) public view returns (bool) {\\n address host = msg.sender;\\n SlotId slotId = Requests.slotId(requestId, slotIndex);\\n return\\n // TODO: add in check for address inside of expanding window\\n (_reservations[slotId].length() < _config.maxReservations) &&\\n (!_reservations[slotId].contains(host));\\n }\\n\\n event SlotReservationsFull(RequestId indexed requestId, uint256 slotIndex);\\n}\\n\",\"keccak256\":\"0x8931bef1b8c9ed44b4f19257e2e43d91051ef8c5ed2e4e0fd82c0547451a3cf9\",\"license\":\"MIT\"},\"contracts/StateRetrieval.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.23;\\n\\nimport \\\"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\\\";\\nimport \\\"./Requests.sol\\\";\\n\\ncontract StateRetrieval {\\n using EnumerableSet for EnumerableSet.Bytes32Set;\\n using Requests for bytes32[];\\n\\n mapping(address => EnumerableSet.Bytes32Set) private _requestsPerClient;\\n mapping(address => EnumerableSet.Bytes32Set) private _slotsPerHost;\\n\\n function myRequests() public view returns (RequestId[] memory) {\\n return _requestsPerClient[msg.sender].values().toRequestIds();\\n }\\n\\n function mySlots() public view returns (SlotId[] memory) {\\n return _slotsPerHost[msg.sender].values().toSlotIds();\\n }\\n\\n function _hasSlots(address host) internal view returns (bool) {\\n return _slotsPerHost[host].length() > 0;\\n }\\n\\n function _addToMyRequests(address client, RequestId requestId) internal {\\n _requestsPerClient[client].add(RequestId.unwrap(requestId));\\n }\\n\\n function _addToMySlots(address host, SlotId slotId) internal {\\n _slotsPerHost[host].add(SlotId.unwrap(slotId));\\n }\\n\\n function _removeFromMyRequests(address client, RequestId requestId) internal {\\n _requestsPerClient[client].remove(RequestId.unwrap(requestId));\\n }\\n\\n function _removeFromMySlots(address host, SlotId slotId) internal {\\n _slotsPerHost[host].remove(SlotId.unwrap(slotId));\\n }\\n}\\n\",\"keccak256\":\"0x734c58b16cd1bf57aed889162708140b4a093698963c5cf688308f7d8b2d5deb\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60c06040523480156200001157600080fd5b506040516200451038038062004510833981016040819052620000349162000571565b602083015180516040850151516001805460ff191660ff909216919091179055608052816101004311620000af5760405162461bcd60e51b815260206004820152601960248201527f496e73756666696369656e7420626c6f636b206865696768740000000000000060448201526064015b60405180910390fd5b81516002908155602083015160035560408301516004805460ff191660ff9092169190911790556060830151839190600590620000ed908262000724565b50608091909101516004909101805460ff191660ff928316179055600780546001600160a01b0319166001600160a01b0393841617905590841660a0528451516064911611159050620001835760405162461bcd60e51b815260206004820152601560248201527f4d757374206265206c657373207468616e2031303000000000000000000000006044820152606401620000a6565b606483600001516060015160ff161115620001e15760405162461bcd60e51b815260206004820152601560248201527f4d757374206265206c657373207468616e2031303000000000000000000000006044820152606401620000a6565b82516060810151602090910151606491620001fc91620007f0565b60ff1611156200024f5760405162461bcd60e51b815260206004820152601d60248201527f4d6178696d756d20736c617368696e67206578636565647320313030250000006044820152606401620000a6565b82518051600f805460208085015160408087015160609788015160ff9081166401000000000260ff60201b1961ffff90931662010000029290921664ffffff0000199482166101000261ffff199097169882169890981795909517929092169590951717835580880151805160109081559181015160115593840151601280549190931660ff19919091161790915592820151869391929190601390620002f7908262000724565b50608091909101516004909101805460ff1990811660ff938416179091556040939093015151600692909201805490931691161790555062000822915050565b634e487b7160e01b600052604160045260246000fd5b60405160a081016001600160401b038111828210171562000372576200037262000337565b60405290565b604051606081016001600160401b038111828210171562000372576200037262000337565b604051608081016001600160401b038111828210171562000372576200037262000337565b604051601f8201601f191681016001600160401b0381118282101715620003ed57620003ed62000337565b604052919050565b805160ff811681146200040757600080fd5b919050565b600060a082840312156200041f57600080fd5b620004296200034d565b905081518152602080830151818301526200044760408401620003f5565b604083015260608301516001600160401b03808211156200046757600080fd5b818501915085601f8301126200047c57600080fd5b81518181111562000491576200049162000337565b620004a5601f8201601f19168501620003c2565b91508082528684828501011115620004bc57600080fd5b60005b81811015620004dc578381018501518382018601528401620004bf565b50600084828401015250806060850152505050620004fd60808301620003f5565b608082015292915050565b6000602082840312156200051b57600080fd5b604051602081016001600160401b038111828210171562000540576200054062000337565b6040529050806200055183620003f5565b905292915050565b80516001600160a01b03811681146200040757600080fd5b6000806000606084860312156200058757600080fd5b83516001600160401b03808211156200059f57600080fd5b9085019081870360c0811215620005b557600080fd5b620005bf62000378565b6080821215620005ce57600080fd5b620005d86200039d565b9150620005e584620003f5565b8252620005f560208501620003f5565b6020830152604084015161ffff811681146200061057600080fd5b60408301526200062360608501620003f5565b6060830152908152608083015190828211156200063f57600080fd5b6200064d898386016200040c565b6020820152620006618960a0860162000508565b604082015295506200067a925050506020850162000559565b91506200068a6040850162000559565b90509250925092565b600181811c90821680620006a857607f821691505b602082108103620006c957634e487b7160e01b600052602260045260246000fd5b50919050565b601f8211156200071f576000816000526020600020601f850160051c81016020861015620006fa5750805b601f850160051c820191505b818110156200071b5782815560010162000706565b5050505b505050565b81516001600160401b0381111562000740576200074062000337565b620007588162000751845462000693565b84620006cf565b602080601f831160018114620007905760008415620007775750858301515b600019600386901b1c1916600185901b1785556200071b565b600085815260208120601f198616915b82811015620007c157888601518255948401946001909101908401620007a0565b5085821015620007e05787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b60ff81811683821602908116908181146200081b57634e487b7160e01b600052601160045260246000fd5b5092915050565b60805160a051613c97620008796000396000818161044201528181611ad5015281816123800152818161241f015281816125ad0152818161264c0152612817015260008181612d460152612f0c0152613c976000f3fe608060405234801561001057600080fd5b50600436106101ae5760003560e01c806379502c55116100ee578063be5cdc4811610097578063e8aa0a0711610071578063e8aa0a07146103ed578063f752196b14610400578063fb1e61ca14610420578063fc0c546a1461044057600080fd5b8063be5cdc48146103a7578063c0cc4add146103c7578063c5d43351146103da57600080fd5b8063a3a0807e116100c8578063a3a0807e14610361578063a6af384b14610374578063b396dc791461038757600080fd5b806379502c55146103315780639777b72c14610346578063a29c29a41461034e57600080fd5b80634641dce61161015b5780635da73835116101355780635da73835146102b257806362d48e13146102c75780636b00c8cf146102da5780636e2b54ee1461031e57600080fd5b80634641dce6146102575780634802f44b1461027c57806359cc89ed1461029f57600080fd5b80630aefaabe1161018c5780630aefaabe1461020e578063329b5a0b14610221578063458d2bf11461024457600080fd5b806302fa8e65146101b357806305b90773146101d957806308695fcd146101f9575b600080fd5b6101c66101c13660046130f3565b610466565b6040519081526020015b60405180910390f35b6101ec6101e73660046130f3565b6104dd565b6040516101d09190613122565b61020c61020736600461313c565b6105ef565b005b61020c61021c366004613173565b610745565b6101c661022f3660046130f3565b60009081526017602052604090206005015490565b6101c66102523660046130f3565b610922565b61026a6102653660046130f3565b61093b565b60405160ff90911681526020016101d0565b61028f61028a36600461313c565b61094e565b60405190151581526020016101d0565b61020c6102ad3660046131c8565b6109c9565b6102ba610d30565b6040516101d091906131ff565b61020c6102d536600461313c565b610d57565b6103066102e83660046130f3565b6000908152601860205260409020600501546001600160a01b031690565b6040516001600160a01b0390911681526020016101d0565b61020c61032c3660046130f3565b610e54565b610339610e61565b6040516101d09190613289565b6102ba611015565b61020c61035c3660046130f3565b611034565b61028f61036f3660046130f3565b6110a4565b61020c610382366004613332565b6110d9565b61039a6103953660046130f3565b61142e565b6040516101d0919061343b565b6103ba6103b53660046130f3565b611617565b6040516101d0919061346d565b61028f6103d53660046130f3565b6116e5565b61020c6103e8366004613481565b6116f8565b61020c6103fb3660046134b1565b611b5d565b6101c661040e3660046130f3565b6000908152600a602052604090205490565b61043361042e3660046130f3565b611c92565b6040516101d091906134df565b7f0000000000000000000000000000000000000000000000000000000000000000610306565b60008181526017602052604081206004015481610482846104dd565b905060008160048111156104985761049861310c565b14806104b5575060018160048111156104b3576104b361310c565b145b156104c1575092915050565b6104d5826104d0600142613508565b611e49565b949350505050565b60008181526016602052604081205482906001600160a01b031661053a5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b60448201526064015b60405180910390fd5b600083815260176020526040812090815460ff16600481111561055f5761055f61310c565b14801561057c575060008481526017602052604090206005015442115b1561058b5760029250506105e9565b6001815460ff1660048111156105a3576105a361310c565b14806105c457506000815460ff1660048111156105c2576105c261310c565b145b80156105d35750806004015442115b156105e25760039250506105e9565b5460ff1691505b50919050565b60016105fa83611617565b600581111561060b5761060b61310c565b146106585760405162461bcd60e51b815260206004820152601960248201527f536c6f74206e6f7420616363657074696e672070726f6f6673000000000000006044820152606401610531565b6106628282611e61565b6000828152601860209081526040808320600181015484526016909252909120600f5461ffff62010000909104166106a6856000908152600a602052604090205490565b6106b09190613531565b60000361073f57600f5460068201546000916064916106da91640100000000900460ff1690613545565b6106e4919061355c565b9050808360040160008282546106fa9190613508565b9091555050600f546000868152600a6020526040902054610100820460ff169162010000900461ffff169061072f919061355c565b1061073d5761073d8561208e565b505b50505050565b826000808281526018602052604090205460ff16600581111561076a5761076a61310c565b036107a65760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b600084815260186020526040902060058101546001600160a01b031633146108105760405162461bcd60e51b815260206004820152601960248201527f536c6f742066696c6c6564206279206f7468657220686f7374000000000000006044820152606401610531565b600061081b86611617565b905060048160058111156108315761083161310c565b0361087e5760405162461bcd60e51b815260206004820152600c60248201527f416c7265616479207061696400000000000000000000000000000000000000006044820152606401610531565b60028160058111156108925761089261310c565b036108ac576108a7826001015487878761225c565b61091a565b60058160058111156108c0576108c061310c565b036108d5576108a782600101548787876124a4565b60038160058111156108e9576108e961310c565b036108f8576108a733876126cf565b600181600581111561090c5761090c61310c565b0361091a5761091a8661208e565b505050505050565b6000610935826109306126f1565b6126fc565b92915050565b6000610935826109496126f1565b612710565b6040805160208082018590528183018490528251808303840181526060909201909252805191012060009033908290600154600082815260208190526040902091925060ff169061099e90612784565b1080156109c0575060008181526020819052604090206109be908361278e565b155b95945050505050565b60008381526016602052604090205483906001600160a01b0316610a215760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b6000848152601660205260409020600181015467ffffffffffffffff168410610a8c5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c696420736c6f7400000000000000000000000000000000000000006044820152606401610531565b60408051602080820188905281830187905282518083038401815260609092018352815191810191909120600081815291829052919020610acd903361278e565b610b195760405162461bcd60e51b815260206004820152601460248201527f5265736572766174696f6e2072657175697265640000000000000000000000006044820152606401610531565b6000818152601860209081526040808320600181018a905560038101899055898452601790925282209091610b4d84611617565b6005811115610b5e57610b5e61310c565b14610bab5760405162461bcd60e51b815260206004820152601060248201527f536c6f74206973206e6f742066726565000000000000000000000000000000006044820152606401610531565b600484015460008481526008602090815260408083204290556009909152902055610bd68387611b5d565b60058201805473ffffffffffffffffffffffffffffffffffffffff191633179055815460ff1916600190811783554260028401558181018054600090610c1d908490613570565b92505081905550610c328883600201546127b0565b816002016000828254610c459190613508565b90915550506006840154610c5933826127cf565b8060196000016000828254610c6e9190613570565b9091555050600483018190556005830154610c92906001600160a01b0316856128d2565b887ff530852268993f91008f1a1e0b09b5c813acd4188481f1fa83c33c7182e814b489604051610cc491815260200190565b60405180910390a26001808601549083015467ffffffffffffffff9091169003610d2557815460ff1916600117825542600383015560405189907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a25b505050505050505050565b336000908152600e60205260409020606090610d5290610d4f906128f4565b90565b905090565b610d61828261094e565b610dad5760405162461bcd60e51b815260206004820152601760248201527f5265736572766174696f6e206e6f7420616c6c6f7765640000000000000000006044820152606401610531565b60408051602080820185905281830184905282518083038401815260609092018352815191810191909120600081815291829052919020610dee9033612901565b50600154600082815260208190526040902060ff90911690610e0f90612784565b03610e4f57827f3bef2ebab8cc92e0edda5decf18232f0606a18405ef674b51ea9d1e0e3839b4183604051610e4691815260200190565b60405180910390a25b505050565b610e5e81336116f8565b50565b610ed56040805160e081019091526000606082018181526080830182905260a0830182905260c0830191909152819081526040805160a08101825260008082526020828101829052928201819052606080830152608082015291019081526040805160208181019092526000815291015290565b6040805160e081018252600f805460ff808216606080860191825261010084048316608087015261ffff6201000085041660a080880191909152640100000000909404831660c087015290855285519283018652601080548452601154602085810191909152601254909316968401969096526013805495969495928701949291840191610f6290613583565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8e90613583565b8015610fdb5780601f10610fb057610100808354040283529160200191610fdb565b820191906000526020600020905b815481529060010190602001808311610fbe57829003601f168201915b50505091835250506004919091015460ff908116602092830152918352604080518083019091526006949094015490911683520152919050565b336000908152600d60205260409020606090610d5290610d4f906128f4565b806000808281526018602052604090205460ff1660058111156110595761105961310c565b036110955760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b6110a0823333610745565b5050565b60008060006110ba846110b56126f1565b612916565b90925090508180156104d5575060045460ff9081169116109392505050565b336110e760208301836135b7565b6001600160a01b03161461113d5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b600061115061114b83613749565b6129f9565b6000818152601660205260409020549091506001600160a01b0316156111b85760405162461bcd60e51b815260206004820152601660248201527f5265717565737420616c726561647920657869737473000000000000000000006044820152606401610531565b60008261012001351180156111d557506060820135610120830135105b6112215760405162461bcd60e51b815260206004820152601360248201527f457870697279206e6f7420696e2072616e6765000000000000000000000000006044820152606401610531565b60006112336040840160208501613838565b67ffffffffffffffff161161128a5760405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420736c6f747300000000000000000000000000006044820152606401610531565b61129a6040830160208401613838565b67ffffffffffffffff166112b5610100840160e08501613838565b67ffffffffffffffff16111561130d5760405162461bcd60e51b815260206004820152601960248201527f6d6178536c6f744c6f7373206578636565647320736c6f7473000000000000006044820152606401610531565b6000818152601660205260409020829061132782826139c3565b506113389050606083013542613570565b60008281526017602052604090206004015561135961012083013542613570565b60008281526017602090815260409091206005019190915561138790611381908401846135b7565b82612a29565b600061139a61139584613749565b612a4b565b60008381526017602052604081206002018290556019805492935083929091906113c5908490613570565b909155506113d5905033826127cf565b7f5fdb86c365a247a4d97dcbcc5c3abde9d6e3e2de26273f3fda8eef5073b9a96c8284602001601760008681526020019081526020016000206005015460405161142193929190613abb565b60405180910390a1505050565b61143661302b565b816000808281526018602052604090205460ff16600581111561145b5761145b61310c565b036114975760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b60008381526018602052604090206114ad61302b565b600180830154600090815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e0810186529583015467ffffffffffffffff9081168752600284015487860152600384015487870152600484015460608801526005840154608088015260068401549187019190915260078301541660c086015291820193909352815180830183526008840180549294938501928290829061155990613583565b80601f016020809104026020016040519081016040528092919081815260200182805461158590613583565b80156115d25780601f106115a7576101008083540402835291602001916115d2565b820191906000526020600020905b8154815290600101906020018083116115b557829003601f168201915b505050918352505060019190910154602091820152908252600a83015482820152600b9092015460409091015290825260039092015491810191909152915050919050565b6000818152601860205260408120600181015482036116395750600092915050565b600061164882600101546104dd565b90506004825460ff1660058111156116625761166261310c565b03611671575060049392505050565b60028160048111156116855761168561310c565b03611694575060059392505050565b60038160048111156116a8576116a861310c565b036116b7575060029392505050565b60048160048111156116cb576116cb61310c565b036116da575060039392505050565b505460ff1692915050565b6000610935826116f36126f1565b612a7c565b600082815260166020526040902080546001600160a01b0316331461175f5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b600083815260176020526040812090611777856104dd565b9050600281600481111561178d5761178d61310c565b14806117aa575060048160048111156117a8576117a861310c565b145b806117c6575060038160048111156117c4576117c461310c565b145b6118125760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207374617465000000000000000000000000000000000000006044820152606401610531565b81600201546000036118665760405162461bcd60e51b815260206004820152601360248201527f4e6f7468696e6720746f207769746864726177000000000000000000000000006044820152606401610531565b600281600481111561187a5761187a61310c565b0361190457815460ff1916600217825560405185907ff903f4774c7bd27355f9d7fcbc382b079b164a697a44ac5d95267a4c3cb3bb2290600090a26118d7856118d28760009081526017602052604090206005015490565b6127b0565b82600101546118e69190613545565b8260020160008282546118f99190613570565b90915550611a7b9050565b60048160048111156119185761191861310c565b03611a6f576040805160a0808201835285546001600160a01b03168252825160e081018452600187015467ffffffffffffffff90811682526002880154602083810191909152600389015483870152600489015460608401526005890154608084015260068901549383019390935260078801541660c08201529082015281518083018352600886018054611a65948893908501929091829082906119bc90613583565b80601f01602080910402602001604051908101604052809291908181526020018280546119e890613583565b8015611a355780601f10611a0a57610100808354040283529160200191611a35565b820191906000526020600020905b815481529060010190602001808311611a1857829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050612a4b565b6002830155611a7b565b815460ff191660031782555b8254611a90906001600160a01b031686612aac565b6002820154601a8054829190600090611aaa908490613570565b909155505060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015611b1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b429190613b37565b611b4e57611b4e613b59565b50506000600290910155505050565b6000828152601860209081526040808320600101548084526016909252909120546001600160a01b0316611bc55760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600083815260186020908152604080832060018101548452601683528184208251600380825260808201909452919490939092908201606080368337019050509050611c18611c1387610922565b612ace565b81600081518110611c2b57611c2b613b6f565b60209081029190910101526009820154611c4490612adf565b81600181518110611c5757611c57613b6f565b602002602001018181525050826003015481600281518110611c7b57611c7b613b6f565b60200260200101818152505061091a868683612aeb565b611c9a61304b565b60008281526016602052604090205482906001600160a01b0316611cf25760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600083815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e081018652600184015467ffffffffffffffff90811682526002850154828701526003850154828801526004850154606083015260058501546080830152600685015492820192909252600784015490911660c08201529281019290925282518084018452600882018054939492939285019282908290611d9d90613583565b80601f0160208091040260200160405190810160405280929190818152602001828054611dc990613583565b8015611e165780601f10611deb57610100808354040283529160200191611e16565b820191906000526020600020905b815481529060010190602001808311611df957829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050915050919050565b6000818310611e585781611e5a565b825b9392505050565b6000611e6c82612caa565b9050428110611ebd5760405162461bcd60e51b815260206004820152601860248201527f506572696f6420686173206e6f7420656e6465642079657400000000000000006044820152606401610531565b600354611eca9082613570565b4210611f185760405162461bcd60e51b815260206004820152601460248201527f56616c69646174696f6e2074696d6564206f75740000000000000000000000006044820152606401610531565b6000838152600b6020908152604080832085845290915290205460ff1615611f825760405162461bcd60e51b815260206004820181905260248201527f50726f6f6620776173207375626d69747465642c206e6f74206d697373696e676044820152606401610531565b611f8c8383612a7c565b611fd85760405162461bcd60e51b815260206004820152601660248201527f50726f6f6620776173206e6f74207265717569726564000000000000000000006044820152606401610531565b6000838152600c6020908152604080832085845290915290205460ff16156120425760405162461bcd60e51b815260206004820152601f60248201527f50726f6f6620616c7265616479206d61726b6564206173206d697373696e67006044820152606401610531565b6000838152600c602090815260408083208584528252808320805460ff19166001908117909155868452600a9092528220805491929091612084908490613570565b9091555050505050565b600081815260186020908152604080832060018101548085526017909352922060028301546120be9083906127b0565b8160020160008282546120d19190613570565b909155505060058301546120ee906001600160a01b0316856126cf565b6003808401546000868152601860205260408120805460ff1916815560018082018390556002820183905593810182905560048101829055600501805473ffffffffffffffffffffffffffffffffffffffff19169055838301805492939290919061215a908490613508565b909155505060405181815283907f1d31c9f8dea6e179f6a050db117595feea8937029ea51f5168a4780be7e8f5529060200160405180910390a26000858152600a60205260408120556000838152601660205260408120600180850154908201549192916121d2919067ffffffffffffffff16613508565b600783015490915067ffffffffffffffff168111801561220757506001845460ff1660048111156122055761220561310c565b145b1561225357835460ff19166004178455612222600142613508565b600485015560405185907f4769361a442504ecaf038f35e119bcccdd5e42096b24c09e3c17fd17c6684c0290600090a25b50505050505050565b60008481526016602052604090205484906001600160a01b03166122b45760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600085815260176020908152604080832060168352818420815460ff191660031782558885526018909352922081546122f6906001600160a01b031689612aac565b600581015461230e906001600160a01b0316886126cf565b600061231e8983600201546127b0565b60048301549091506123308183613570565b601a8054600090612342908490613570565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038981166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156123c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ed9190613b37565b6123f9576123f9613b59565b60405163a9059cbb60e01b81526001600160a01b038881166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248c9190613b37565b61249857612498613b59565b50505050505050505050565b60008481526016602052604090205484906001600160a01b03166124fc5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b60008481526018602052604090206005810154612522906001600160a01b0316866126cf565b600061254b8783600201546125468a60009081526017602052604090206005015490565b612cbd565b600483015490915061255d8183613570565b601a805460009061256f908490613570565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156125f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261a9190613b37565b61262657612626613b59565b60405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612695573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b99190613b37565b6126c5576126c5613b59565b5050505050505050565b6001600160a01b0382166000908152600e60205260409020610e4f9082612d33565b6000610d5242612d3f565b6000611e5a61270b8484612710565b612d6b565b60008061271f61010043613531565b600654909150600090610100906127399060ff1686613545565b6127439190613531565b9050600061275361010087613531565b90506000610100826127658587613570565b61276f9190613570565b6127799190613531565b979650505050505050565b6000610935825490565b6001600160a01b03811660009081526001830160205260408120541515611e5a565b600082815260176020526040812060040154611e5a9084908490612cbd565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152306024830181905260448301849052917f0000000000000000000000000000000000000000000000000000000000000000909116906323b872dd906064016020604051808303816000875af1158015612862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128869190613b37565b610e4f5760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c656400000000000000000000000000000000006044820152606401610531565b6001600160a01b0382166000908152600e60205260409020610e4f9082612dc5565b60606000611e5a83612dd1565b6000611e5a836001600160a01b038416612e2d565b600080600061292485611617565b6000868152600860205260408120549192509061294090612d3f565b905060018260058111156129565761295661310c565b14158061296a57506129688582612e7c565b155b1561297d576000809350935050506129f2565b6129878686612710565b9250600061299484612d6b565b600454909150600090610100906129ae9060ff1682613b85565b60008a8152600960205260409020546129cb9161ffff1690613545565b6129d5919061355c565b90508015806129eb57506129e98183613531565b155b9550505050505b9250929050565b600081604051602001612a0c91906134df565b604051602081830303815290604052805190602001209050919050565b6001600160a01b0382166000908152600d60205260409020610e4f9082612dc5565b6020810151608081015160408201519151600092612a729167ffffffffffffffff16613545565b6109359190613545565b6000806000612a8b8585612916565b90925090508180156109c0575060045460ff90811691161015949350505050565b6001600160a01b0382166000908152600d60205260409020610e4f9082612d33565b600060ff198216816104d582612e86565b600080611e5a83612e86565b6000838152600b6020526040812090612b026126f1565b815260208101919091526040016000205460ff1615612b635760405162461bcd60e51b815260206004820152601760248201527f50726f6f6620616c7265616479207375626d69747465640000000000000000006044820152606401610531565b6007546040517f94c8919d0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906394c8919d90612bae9085908590600401613ba0565b602060405180830381865afa158015612bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bef9190613b37565b612c3b5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610531565b6000838152600b60205260408120600191612c546126f1565b815260200190815260200160002060006101000a81548160ff0219169083151502179055507f3b989d183b84b02259d7c14b34a9c9eb0fccb4c355a920d25e581e25aef4993d8360405161142191815260200190565b6000610935612cb883612ef8565b612f05565b6000838152601660205260408120828410612d1a5760405162461bcd60e51b815260206004820152601760248201527f5374617274206e6f74206265666f7265206578706972790000000000000000006044820152606401610531565b6005810154612d298585613508565b6109c09190613545565b6000611e5a8383612f31565b60006109357f00000000000000000000000000000000000000000000000000000000000000008361355c565b60008060ff8316612d7d600143613508565b612d879190613508565b4090506000819003612d9b57612d9b613b59565b60408051602081018390520160405160208183030381529060405280519060200120915050919050565b6000611e5a8383612e2d565b606081600001805480602002602001604051908101604052809291908181526020018280548015612e2157602002820191906000526020600020905b815481526020019060010190808311612e0d575b50505050509050919050565b6000818152600183016020526040812054612e7457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610935565b506000610935565b6000818311611e5a565b7fff00000000000000000000000000000000000000000000000000000000000000811660015b60208110156105e957600891821c91612ec6908290613545565b83901b7fff00000000000000000000000000000000000000000000000000000000000000169190911790600101612eac565b6000610935826001613570565b60006109357f000000000000000000000000000000000000000000000000000000000000000083613545565b6000818152600183016020526040812054801561301a576000612f55600183613508565b8554909150600090612f6990600190613508565b9050818114612fce576000866000018281548110612f8957612f89613b6f565b9060005260206000200154905080876000018481548110612fac57612fac613b6f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612fdf57612fdf613c4b565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610935565b6000915050610935565b5092915050565b604051806040016040528061303e61304b565b8152602001600081525090565b6040518060a0016040528060006001600160a01b031681526020016130ba6040518060e00160405280600067ffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600067ffffffffffffffff1681525090565b81526020016130df604051806040016040528060608152602001600080191681525090565b815260006020820181905260409091015290565b60006020828403121561310557600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60208101600583106131365761313661310c565b91905290565b6000806040838503121561314f57600080fd5b50508035926020909101359150565b6001600160a01b0381168114610e5e57600080fd5b60008060006060848603121561318857600080fd5b83359250602084013561319a8161315e565b915060408401356131aa8161315e565b809150509250925092565b600061010082840312156105e957600080fd5b600080600061014084860312156131de57600080fd5b83359250602084013591506131f685604086016131b5565b90509250925092565b6020808252825182820181905260009190848201906040850190845b818110156132375783518352928401929184019160010161321b565b50909695505050505050565b6000815180845260005b818110156132695760208185018101518683018201520161324d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000825160ff815116602084015260ff602082015116604084015261ffff604082015116606084015260ff606082015116608084015250602083015160c060a0840152805160e0840152602081015161010084015260ff604082015116610120840152606081015160a061014085015261330b610180850182613243565b905060ff608083015116610160850152604085015191506104d560c08501835160ff169052565b60006020828403121561334457600080fd5b813567ffffffffffffffff81111561335b57600080fd5b82016101608185031215611e5a57600080fd5b60008151604084526133836040850182613243565b602093840151949093019390935250919050565b60006101606001600160a01b038351168452602083015167ffffffffffffffff808251166020870152602082015160408701526040820151606087015260608201516080870152608082015160a087015260a082015160c08701528060c08301511660e087015250506040830151816101008601526134188286018261336e565b915050606083015161012085015260808301516101408501528091505092915050565b6020815260008251604060208401526134576060840182613397565b9050602084015160408401528091505092915050565b60208101600683106131365761313661310c565b6000806040838503121561349457600080fd5b8235915060208301356134a68161315e565b809150509250929050565b60008061012083850312156134c557600080fd5b823591506134d684602085016131b5565b90509250929050565b602081526000611e5a6020830184613397565b634e487b7160e01b600052601160045260246000fd5b81810381811115610935576109356134f2565b634e487b7160e01b600052601260045260246000fd5b6000826135405761354061351b565b500690565b8082028115828204841417610935576109356134f2565b60008261356b5761356b61351b565b500490565b80820180821115610935576109356134f2565b600181811c9082168061359757607f821691505b6020821081036105e957634e487b7160e01b600052602260045260246000fd5b6000602082840312156135c957600080fd5b8135611e5a8161315e565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561360d5761360d6135d4565b60405290565b60405160a0810167ffffffffffffffff8111828210171561360d5761360d6135d4565b60405160e0810167ffffffffffffffff8111828210171561360d5761360d6135d4565b604051601f8201601f1916810167ffffffffffffffff81118282101715613682576136826135d4565b604052919050565b67ffffffffffffffff81168114610e5e57600080fd5b6000604082840312156136b257600080fd5b6136ba6135ea565b9050813567ffffffffffffffff808211156136d457600080fd5b818401915084601f8301126136e857600080fd5b81356020828211156136fc576136fc6135d4565b61370e601f8301601f19168201613659565b9250818352868183860101111561372457600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b600081360361016081121561375d57600080fd5b613765613613565b83356137708161315e565b815260e0601f198301121561378457600080fd5b61378c613636565b9150602084013561379c8161368a565b8083525060408401356020830152606084013560408301526080840135606083015260a0840135608083015260c084013560a083015260e08401356137e08161368a565b60c083015260208101919091526101008301359067ffffffffffffffff82111561380957600080fd5b613815368386016136a0565b604082015261012084013560608201526101409093013560808401525090919050565b60006020828403121561384a57600080fd5b8135611e5a8161368a565b600081356109358161368a565b60008235603e1983360301811261387857600080fd5b9190910192915050565b601f821115610e4f576000816000526020600020601f850160051c810160208610156138ab5750805b601f850160051c820191505b8181101561091a578281556001016138b7565b8135601e198336030181126138de57600080fd5b8201803567ffffffffffffffff8111156138f757600080fd5b6020813603818401131561390a57600080fd5b61391e826139188654613583565b86613882565b6000601f831160018114613954576000841561393c57508482018301355b600019600386901b1c1916600185901b1786556139b1565b600086815260209020601f19851690835b82811015613986578785018601358255938501936001909101908501613965565b50858210156139a55760001960f88760031b161c198585890101351681555b505060018460011b0186555b50508085013560018501555050505050565b81356139ce8161315e565b6001600160a01b03811673ffffffffffffffffffffffffffffffffffffffff19835416178255506020820135613a038161368a565b60018201805467ffffffffffffffff191667ffffffffffffffff83161790555060408201356002820155606082013560038201556080820135600482015560a0820135600582015560c08201356006820155613a87613a6460e08401613855565b6007830167ffffffffffffffff821667ffffffffffffffff198254161781555050565b613aa1613a98610100840184613862565b600883016138ca565b610120820135600a820155610140820135600b8201555050565b83815261012081018335613ace8161368a565b67ffffffffffffffff8082166020850152602086013560408501526040860135606085015260608601356080850152608086013560a085015260a086013560c085015260c08601359150613b218261368a565b1660e08301526101009091019190915292915050565b600060208284031215613b4957600080fd5b81518015158114611e5a57600080fd5b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b61ffff828116828216039080821115613024576130246134f2565b82358152602080840135908201526000610120828101613bd0604085016040880180358252602090810135910152565b613bea608085016080880180358252602090810135910152565b613c0460c0850160c0880180358252602090810135910152565b61010084019190915283519081905261014083019060209081860160005b82811015613c3e57815185529383019390830190600101613c22565b5092979650505050505050565b634e487b7160e01b600052603160045260246000fdfea26469706673582212201734667e2912f3ec0ced846ccd2aacfe7f1b3040e228245e555c67a7c591bbcf64736f6c63430008170033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101ae5760003560e01c806379502c55116100ee578063be5cdc4811610097578063e8aa0a0711610071578063e8aa0a07146103ed578063f752196b14610400578063fb1e61ca14610420578063fc0c546a1461044057600080fd5b8063be5cdc48146103a7578063c0cc4add146103c7578063c5d43351146103da57600080fd5b8063a3a0807e116100c8578063a3a0807e14610361578063a6af384b14610374578063b396dc791461038757600080fd5b806379502c55146103315780639777b72c14610346578063a29c29a41461034e57600080fd5b80634641dce61161015b5780635da73835116101355780635da73835146102b257806362d48e13146102c75780636b00c8cf146102da5780636e2b54ee1461031e57600080fd5b80634641dce6146102575780634802f44b1461027c57806359cc89ed1461029f57600080fd5b80630aefaabe1161018c5780630aefaabe1461020e578063329b5a0b14610221578063458d2bf11461024457600080fd5b806302fa8e65146101b357806305b90773146101d957806308695fcd146101f9575b600080fd5b6101c66101c13660046130f3565b610466565b6040519081526020015b60405180910390f35b6101ec6101e73660046130f3565b6104dd565b6040516101d09190613122565b61020c61020736600461313c565b6105ef565b005b61020c61021c366004613173565b610745565b6101c661022f3660046130f3565b60009081526017602052604090206005015490565b6101c66102523660046130f3565b610922565b61026a6102653660046130f3565b61093b565b60405160ff90911681526020016101d0565b61028f61028a36600461313c565b61094e565b60405190151581526020016101d0565b61020c6102ad3660046131c8565b6109c9565b6102ba610d30565b6040516101d091906131ff565b61020c6102d536600461313c565b610d57565b6103066102e83660046130f3565b6000908152601860205260409020600501546001600160a01b031690565b6040516001600160a01b0390911681526020016101d0565b61020c61032c3660046130f3565b610e54565b610339610e61565b6040516101d09190613289565b6102ba611015565b61020c61035c3660046130f3565b611034565b61028f61036f3660046130f3565b6110a4565b61020c610382366004613332565b6110d9565b61039a6103953660046130f3565b61142e565b6040516101d0919061343b565b6103ba6103b53660046130f3565b611617565b6040516101d0919061346d565b61028f6103d53660046130f3565b6116e5565b61020c6103e8366004613481565b6116f8565b61020c6103fb3660046134b1565b611b5d565b6101c661040e3660046130f3565b6000908152600a602052604090205490565b61043361042e3660046130f3565b611c92565b6040516101d091906134df565b7f0000000000000000000000000000000000000000000000000000000000000000610306565b60008181526017602052604081206004015481610482846104dd565b905060008160048111156104985761049861310c565b14806104b5575060018160048111156104b3576104b361310c565b145b156104c1575092915050565b6104d5826104d0600142613508565b611e49565b949350505050565b60008181526016602052604081205482906001600160a01b031661053a5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b60448201526064015b60405180910390fd5b600083815260176020526040812090815460ff16600481111561055f5761055f61310c565b14801561057c575060008481526017602052604090206005015442115b1561058b5760029250506105e9565b6001815460ff1660048111156105a3576105a361310c565b14806105c457506000815460ff1660048111156105c2576105c261310c565b145b80156105d35750806004015442115b156105e25760039250506105e9565b5460ff1691505b50919050565b60016105fa83611617565b600581111561060b5761060b61310c565b146106585760405162461bcd60e51b815260206004820152601960248201527f536c6f74206e6f7420616363657074696e672070726f6f6673000000000000006044820152606401610531565b6106628282611e61565b6000828152601860209081526040808320600181015484526016909252909120600f5461ffff62010000909104166106a6856000908152600a602052604090205490565b6106b09190613531565b60000361073f57600f5460068201546000916064916106da91640100000000900460ff1690613545565b6106e4919061355c565b9050808360040160008282546106fa9190613508565b9091555050600f546000868152600a6020526040902054610100820460ff169162010000900461ffff169061072f919061355c565b1061073d5761073d8561208e565b505b50505050565b826000808281526018602052604090205460ff16600581111561076a5761076a61310c565b036107a65760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b600084815260186020526040902060058101546001600160a01b031633146108105760405162461bcd60e51b815260206004820152601960248201527f536c6f742066696c6c6564206279206f7468657220686f7374000000000000006044820152606401610531565b600061081b86611617565b905060048160058111156108315761083161310c565b0361087e5760405162461bcd60e51b815260206004820152600c60248201527f416c7265616479207061696400000000000000000000000000000000000000006044820152606401610531565b60028160058111156108925761089261310c565b036108ac576108a7826001015487878761225c565b61091a565b60058160058111156108c0576108c061310c565b036108d5576108a782600101548787876124a4565b60038160058111156108e9576108e961310c565b036108f8576108a733876126cf565b600181600581111561090c5761090c61310c565b0361091a5761091a8661208e565b505050505050565b6000610935826109306126f1565b6126fc565b92915050565b6000610935826109496126f1565b612710565b6040805160208082018590528183018490528251808303840181526060909201909252805191012060009033908290600154600082815260208190526040902091925060ff169061099e90612784565b1080156109c0575060008181526020819052604090206109be908361278e565b155b95945050505050565b60008381526016602052604090205483906001600160a01b0316610a215760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b6000848152601660205260409020600181015467ffffffffffffffff168410610a8c5760405162461bcd60e51b815260206004820152600c60248201527f496e76616c696420736c6f7400000000000000000000000000000000000000006044820152606401610531565b60408051602080820188905281830187905282518083038401815260609092018352815191810191909120600081815291829052919020610acd903361278e565b610b195760405162461bcd60e51b815260206004820152601460248201527f5265736572766174696f6e2072657175697265640000000000000000000000006044820152606401610531565b6000818152601860209081526040808320600181018a905560038101899055898452601790925282209091610b4d84611617565b6005811115610b5e57610b5e61310c565b14610bab5760405162461bcd60e51b815260206004820152601060248201527f536c6f74206973206e6f742066726565000000000000000000000000000000006044820152606401610531565b600484015460008481526008602090815260408083204290556009909152902055610bd68387611b5d565b60058201805473ffffffffffffffffffffffffffffffffffffffff191633179055815460ff1916600190811783554260028401558181018054600090610c1d908490613570565b92505081905550610c328883600201546127b0565b816002016000828254610c459190613508565b90915550506006840154610c5933826127cf565b8060196000016000828254610c6e9190613570565b9091555050600483018190556005830154610c92906001600160a01b0316856128d2565b887ff530852268993f91008f1a1e0b09b5c813acd4188481f1fa83c33c7182e814b489604051610cc491815260200190565b60405180910390a26001808601549083015467ffffffffffffffff9091169003610d2557815460ff1916600117825542600383015560405189907f85e1543bf2f84fe80c6badbce3648c8539ad1df4d2b3d822938ca0538be727e690600090a25b505050505050505050565b336000908152600e60205260409020606090610d5290610d4f906128f4565b90565b905090565b610d61828261094e565b610dad5760405162461bcd60e51b815260206004820152601760248201527f5265736572766174696f6e206e6f7420616c6c6f7765640000000000000000006044820152606401610531565b60408051602080820185905281830184905282518083038401815260609092018352815191810191909120600081815291829052919020610dee9033612901565b50600154600082815260208190526040902060ff90911690610e0f90612784565b03610e4f57827f3bef2ebab8cc92e0edda5decf18232f0606a18405ef674b51ea9d1e0e3839b4183604051610e4691815260200190565b60405180910390a25b505050565b610e5e81336116f8565b50565b610ed56040805160e081019091526000606082018181526080830182905260a0830182905260c0830191909152819081526040805160a08101825260008082526020828101829052928201819052606080830152608082015291019081526040805160208181019092526000815291015290565b6040805160e081018252600f805460ff808216606080860191825261010084048316608087015261ffff6201000085041660a080880191909152640100000000909404831660c087015290855285519283018652601080548452601154602085810191909152601254909316968401969096526013805495969495928701949291840191610f6290613583565b80601f0160208091040260200160405190810160405280929190818152602001828054610f8e90613583565b8015610fdb5780601f10610fb057610100808354040283529160200191610fdb565b820191906000526020600020905b815481529060010190602001808311610fbe57829003601f168201915b50505091835250506004919091015460ff908116602092830152918352604080518083019091526006949094015490911683520152919050565b336000908152600d60205260409020606090610d5290610d4f906128f4565b806000808281526018602052604090205460ff1660058111156110595761105961310c565b036110955760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b6110a0823333610745565b5050565b60008060006110ba846110b56126f1565b612916565b90925090508180156104d5575060045460ff9081169116109392505050565b336110e760208301836135b7565b6001600160a01b03161461113d5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b600061115061114b83613749565b6129f9565b6000818152601660205260409020549091506001600160a01b0316156111b85760405162461bcd60e51b815260206004820152601660248201527f5265717565737420616c726561647920657869737473000000000000000000006044820152606401610531565b60008261012001351180156111d557506060820135610120830135105b6112215760405162461bcd60e51b815260206004820152601360248201527f457870697279206e6f7420696e2072616e6765000000000000000000000000006044820152606401610531565b60006112336040840160208501613838565b67ffffffffffffffff161161128a5760405162461bcd60e51b815260206004820152601260248201527f496e73756666696369656e7420736c6f747300000000000000000000000000006044820152606401610531565b61129a6040830160208401613838565b67ffffffffffffffff166112b5610100840160e08501613838565b67ffffffffffffffff16111561130d5760405162461bcd60e51b815260206004820152601960248201527f6d6178536c6f744c6f7373206578636565647320736c6f7473000000000000006044820152606401610531565b6000818152601660205260409020829061132782826139c3565b506113389050606083013542613570565b60008281526017602052604090206004015561135961012083013542613570565b60008281526017602090815260409091206005019190915561138790611381908401846135b7565b82612a29565b600061139a61139584613749565b612a4b565b60008381526017602052604081206002018290556019805492935083929091906113c5908490613570565b909155506113d5905033826127cf565b7f5fdb86c365a247a4d97dcbcc5c3abde9d6e3e2de26273f3fda8eef5073b9a96c8284602001601760008681526020019081526020016000206005015460405161142193929190613abb565b60405180910390a1505050565b61143661302b565b816000808281526018602052604090205460ff16600581111561145b5761145b61310c565b036114975760405162461bcd60e51b815260206004820152600c60248201526b536c6f74206973206672656560a01b6044820152606401610531565b60008381526018602052604090206114ad61302b565b600180830154600090815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e0810186529583015467ffffffffffffffff9081168752600284015487860152600384015487870152600484015460608801526005840154608088015260068401549187019190915260078301541660c086015291820193909352815180830183526008840180549294938501928290829061155990613583565b80601f016020809104026020016040519081016040528092919081815260200182805461158590613583565b80156115d25780601f106115a7576101008083540402835291602001916115d2565b820191906000526020600020905b8154815290600101906020018083116115b557829003601f168201915b505050918352505060019190910154602091820152908252600a83015482820152600b9092015460409091015290825260039092015491810191909152915050919050565b6000818152601860205260408120600181015482036116395750600092915050565b600061164882600101546104dd565b90506004825460ff1660058111156116625761166261310c565b03611671575060049392505050565b60028160048111156116855761168561310c565b03611694575060059392505050565b60038160048111156116a8576116a861310c565b036116b7575060029392505050565b60048160048111156116cb576116cb61310c565b036116da575060039392505050565b505460ff1692915050565b6000610935826116f36126f1565b612a7c565b600082815260166020526040902080546001600160a01b0316331461175f5760405162461bcd60e51b815260206004820152601660248201527f496e76616c696420636c69656e742061646472657373000000000000000000006044820152606401610531565b600083815260176020526040812090611777856104dd565b9050600281600481111561178d5761178d61310c565b14806117aa575060048160048111156117a8576117a861310c565b145b806117c6575060038160048111156117c4576117c461310c565b145b6118125760405162461bcd60e51b815260206004820152600d60248201527f496e76616c6964207374617465000000000000000000000000000000000000006044820152606401610531565b81600201546000036118665760405162461bcd60e51b815260206004820152601360248201527f4e6f7468696e6720746f207769746864726177000000000000000000000000006044820152606401610531565b600281600481111561187a5761187a61310c565b0361190457815460ff1916600217825560405185907ff903f4774c7bd27355f9d7fcbc382b079b164a697a44ac5d95267a4c3cb3bb2290600090a26118d7856118d28760009081526017602052604090206005015490565b6127b0565b82600101546118e69190613545565b8260020160008282546118f99190613570565b90915550611a7b9050565b60048160048111156119185761191861310c565b03611a6f576040805160a0808201835285546001600160a01b03168252825160e081018452600187015467ffffffffffffffff90811682526002880154602083810191909152600389015483870152600489015460608401526005890154608084015260068901549383019390935260078801541660c08201529082015281518083018352600886018054611a65948893908501929091829082906119bc90613583565b80601f01602080910402602001604051908101604052809291908181526020018280546119e890613583565b8015611a355780601f10611a0a57610100808354040283529160200191611a35565b820191906000526020600020905b815481529060010190602001808311611a1857829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050612a4b565b6002830155611a7b565b815460ff191660031782555b8254611a90906001600160a01b031686612aac565b6002820154601a8054829190600090611aaa908490613570565b909155505060405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015611b1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b429190613b37565b611b4e57611b4e613b59565b50506000600290910155505050565b6000828152601860209081526040808320600101548084526016909252909120546001600160a01b0316611bc55760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600083815260186020908152604080832060018101548452601683528184208251600380825260808201909452919490939092908201606080368337019050509050611c18611c1387610922565b612ace565b81600081518110611c2b57611c2b613b6f565b60209081029190910101526009820154611c4490612adf565b81600181518110611c5757611c57613b6f565b602002602001018181525050826003015481600281518110611c7b57611c7b613b6f565b60200260200101818152505061091a868683612aeb565b611c9a61304b565b60008281526016602052604090205482906001600160a01b0316611cf25760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600083815260166020908152604091829020825160a0808201855282546001600160a01b03168252845160e081018652600184015467ffffffffffffffff90811682526002850154828701526003850154828801526004850154606083015260058501546080830152600685015492820192909252600784015490911660c08201529281019290925282518084018452600882018054939492939285019282908290611d9d90613583565b80601f0160208091040260200160405190810160405280929190818152602001828054611dc990613583565b8015611e165780601f10611deb57610100808354040283529160200191611e16565b820191906000526020600020905b815481529060010190602001808311611df957829003601f168201915b505050505081526020016001820154815250508152602001600a8201548152602001600b82015481525050915050919050565b6000818310611e585781611e5a565b825b9392505050565b6000611e6c82612caa565b9050428110611ebd5760405162461bcd60e51b815260206004820152601860248201527f506572696f6420686173206e6f7420656e6465642079657400000000000000006044820152606401610531565b600354611eca9082613570565b4210611f185760405162461bcd60e51b815260206004820152601460248201527f56616c69646174696f6e2074696d6564206f75740000000000000000000000006044820152606401610531565b6000838152600b6020908152604080832085845290915290205460ff1615611f825760405162461bcd60e51b815260206004820181905260248201527f50726f6f6620776173207375626d69747465642c206e6f74206d697373696e676044820152606401610531565b611f8c8383612a7c565b611fd85760405162461bcd60e51b815260206004820152601660248201527f50726f6f6620776173206e6f74207265717569726564000000000000000000006044820152606401610531565b6000838152600c6020908152604080832085845290915290205460ff16156120425760405162461bcd60e51b815260206004820152601f60248201527f50726f6f6620616c7265616479206d61726b6564206173206d697373696e67006044820152606401610531565b6000838152600c602090815260408083208584528252808320805460ff19166001908117909155868452600a9092528220805491929091612084908490613570565b9091555050505050565b600081815260186020908152604080832060018101548085526017909352922060028301546120be9083906127b0565b8160020160008282546120d19190613570565b909155505060058301546120ee906001600160a01b0316856126cf565b6003808401546000868152601860205260408120805460ff1916815560018082018390556002820183905593810182905560048101829055600501805473ffffffffffffffffffffffffffffffffffffffff19169055838301805492939290919061215a908490613508565b909155505060405181815283907f1d31c9f8dea6e179f6a050db117595feea8937029ea51f5168a4780be7e8f5529060200160405180910390a26000858152600a60205260408120556000838152601660205260408120600180850154908201549192916121d2919067ffffffffffffffff16613508565b600783015490915067ffffffffffffffff168111801561220757506001845460ff1660048111156122055761220561310c565b145b1561225357835460ff19166004178455612222600142613508565b600485015560405185907f4769361a442504ecaf038f35e119bcccdd5e42096b24c09e3c17fd17c6684c0290600090a25b50505050505050565b60008481526016602052604090205484906001600160a01b03166122b45760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b600085815260176020908152604080832060168352818420815460ff191660031782558885526018909352922081546122f6906001600160a01b031689612aac565b600581015461230e906001600160a01b0316886126cf565b600061231e8983600201546127b0565b60048301549091506123308183613570565b601a8054600090612342908490613570565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038981166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156123c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906123ed9190613b37565b6123f9576123f9613b59565b60405163a9059cbb60e01b81526001600160a01b038881166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612468573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061248c9190613b37565b61249857612498613b59565b50505050505050505050565b60008481526016602052604090205484906001600160a01b03166124fc5760405162461bcd60e51b815260206004820152600f60248201526e155b9adb9bdddb881c995c5d595cdd608a1b6044820152606401610531565b60008481526018602052604090206005810154612522906001600160a01b0316866126cf565b600061254b8783600201546125468a60009081526017602052604090206005015490565b612cbd565b600483015490915061255d8183613570565b601a805460009061256f908490613570565b90915550508254600490849060ff1916600183021790555060405163a9059cbb60e01b81526001600160a01b038781166004830152602482018490527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af11580156125f6573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061261a9190613b37565b61262657612626613b59565b60405163a9059cbb60e01b81526001600160a01b038681166004830152602482018390527f0000000000000000000000000000000000000000000000000000000000000000169063a9059cbb906044016020604051808303816000875af1158015612695573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906126b99190613b37565b6126c5576126c5613b59565b5050505050505050565b6001600160a01b0382166000908152600e60205260409020610e4f9082612d33565b6000610d5242612d3f565b6000611e5a61270b8484612710565b612d6b565b60008061271f61010043613531565b600654909150600090610100906127399060ff1686613545565b6127439190613531565b9050600061275361010087613531565b90506000610100826127658587613570565b61276f9190613570565b6127799190613531565b979650505050505050565b6000610935825490565b6001600160a01b03811660009081526001830160205260408120541515611e5a565b600082815260176020526040812060040154611e5a9084908490612cbd565b6040517f23b872dd0000000000000000000000000000000000000000000000000000000081526001600160a01b038381166004830152306024830181905260448301849052917f0000000000000000000000000000000000000000000000000000000000000000909116906323b872dd906064016020604051808303816000875af1158015612862573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906128869190613b37565b610e4f5760405162461bcd60e51b815260206004820152600f60248201527f5472616e73666572206661696c656400000000000000000000000000000000006044820152606401610531565b6001600160a01b0382166000908152600e60205260409020610e4f9082612dc5565b60606000611e5a83612dd1565b6000611e5a836001600160a01b038416612e2d565b600080600061292485611617565b6000868152600860205260408120549192509061294090612d3f565b905060018260058111156129565761295661310c565b14158061296a57506129688582612e7c565b155b1561297d576000809350935050506129f2565b6129878686612710565b9250600061299484612d6b565b600454909150600090610100906129ae9060ff1682613b85565b60008a8152600960205260409020546129cb9161ffff1690613545565b6129d5919061355c565b90508015806129eb57506129e98183613531565b155b9550505050505b9250929050565b600081604051602001612a0c91906134df565b604051602081830303815290604052805190602001209050919050565b6001600160a01b0382166000908152600d60205260409020610e4f9082612dc5565b6020810151608081015160408201519151600092612a729167ffffffffffffffff16613545565b6109359190613545565b6000806000612a8b8585612916565b90925090508180156109c0575060045460ff90811691161015949350505050565b6001600160a01b0382166000908152600d60205260409020610e4f9082612d33565b600060ff198216816104d582612e86565b600080611e5a83612e86565b6000838152600b6020526040812090612b026126f1565b815260208101919091526040016000205460ff1615612b635760405162461bcd60e51b815260206004820152601760248201527f50726f6f6620616c7265616479207375626d69747465640000000000000000006044820152606401610531565b6007546040517f94c8919d0000000000000000000000000000000000000000000000000000000081526001600160a01b03909116906394c8919d90612bae9085908590600401613ba0565b602060405180830381865afa158015612bcb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190612bef9190613b37565b612c3b5760405162461bcd60e51b815260206004820152600d60248201527f496e76616c69642070726f6f66000000000000000000000000000000000000006044820152606401610531565b6000838152600b60205260408120600191612c546126f1565b815260200190815260200160002060006101000a81548160ff0219169083151502179055507f3b989d183b84b02259d7c14b34a9c9eb0fccb4c355a920d25e581e25aef4993d8360405161142191815260200190565b6000610935612cb883612ef8565b612f05565b6000838152601660205260408120828410612d1a5760405162461bcd60e51b815260206004820152601760248201527f5374617274206e6f74206265666f7265206578706972790000000000000000006044820152606401610531565b6005810154612d298585613508565b6109c09190613545565b6000611e5a8383612f31565b60006109357f00000000000000000000000000000000000000000000000000000000000000008361355c565b60008060ff8316612d7d600143613508565b612d879190613508565b4090506000819003612d9b57612d9b613b59565b60408051602081018390520160405160208183030381529060405280519060200120915050919050565b6000611e5a8383612e2d565b606081600001805480602002602001604051908101604052809291908181526020018280548015612e2157602002820191906000526020600020905b815481526020019060010190808311612e0d575b50505050509050919050565b6000818152600183016020526040812054612e7457508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155610935565b506000610935565b6000818311611e5a565b7fff00000000000000000000000000000000000000000000000000000000000000811660015b60208110156105e957600891821c91612ec6908290613545565b83901b7fff00000000000000000000000000000000000000000000000000000000000000169190911790600101612eac565b6000610935826001613570565b60006109357f000000000000000000000000000000000000000000000000000000000000000083613545565b6000818152600183016020526040812054801561301a576000612f55600183613508565b8554909150600090612f6990600190613508565b9050818114612fce576000866000018281548110612f8957612f89613b6f565b9060005260206000200154905080876000018481548110612fac57612fac613b6f565b6000918252602080832090910192909255918252600188019052604090208390555b8554869080612fdf57612fdf613c4b565b600190038181906000526020600020016000905590558560010160008681526020019081526020016000206000905560019350505050610935565b6000915050610935565b5092915050565b604051806040016040528061303e61304b565b8152602001600081525090565b6040518060a0016040528060006001600160a01b031681526020016130ba6040518060e00160405280600067ffffffffffffffff1681526020016000815260200160008152602001600081526020016000815260200160008152602001600067ffffffffffffffff1681525090565b81526020016130df604051806040016040528060608152602001600080191681525090565b815260006020820181905260409091015290565b60006020828403121561310557600080fd5b5035919050565b634e487b7160e01b600052602160045260246000fd5b60208101600583106131365761313661310c565b91905290565b6000806040838503121561314f57600080fd5b50508035926020909101359150565b6001600160a01b0381168114610e5e57600080fd5b60008060006060848603121561318857600080fd5b83359250602084013561319a8161315e565b915060408401356131aa8161315e565b809150509250925092565b600061010082840312156105e957600080fd5b600080600061014084860312156131de57600080fd5b83359250602084013591506131f685604086016131b5565b90509250925092565b6020808252825182820181905260009190848201906040850190845b818110156132375783518352928401929184019160010161321b565b50909695505050505050565b6000815180845260005b818110156132695760208185018101518683018201520161324d565b506000602082860101526020601f19601f83011685010191505092915050565b602081526000825160ff815116602084015260ff602082015116604084015261ffff604082015116606084015260ff606082015116608084015250602083015160c060a0840152805160e0840152602081015161010084015260ff604082015116610120840152606081015160a061014085015261330b610180850182613243565b905060ff608083015116610160850152604085015191506104d560c08501835160ff169052565b60006020828403121561334457600080fd5b813567ffffffffffffffff81111561335b57600080fd5b82016101608185031215611e5a57600080fd5b60008151604084526133836040850182613243565b602093840151949093019390935250919050565b60006101606001600160a01b038351168452602083015167ffffffffffffffff808251166020870152602082015160408701526040820151606087015260608201516080870152608082015160a087015260a082015160c08701528060c08301511660e087015250506040830151816101008601526134188286018261336e565b915050606083015161012085015260808301516101408501528091505092915050565b6020815260008251604060208401526134576060840182613397565b9050602084015160408401528091505092915050565b60208101600683106131365761313661310c565b6000806040838503121561349457600080fd5b8235915060208301356134a68161315e565b809150509250929050565b60008061012083850312156134c557600080fd5b823591506134d684602085016131b5565b90509250929050565b602081526000611e5a6020830184613397565b634e487b7160e01b600052601160045260246000fd5b81810381811115610935576109356134f2565b634e487b7160e01b600052601260045260246000fd5b6000826135405761354061351b565b500690565b8082028115828204841417610935576109356134f2565b60008261356b5761356b61351b565b500490565b80820180821115610935576109356134f2565b600181811c9082168061359757607f821691505b6020821081036105e957634e487b7160e01b600052602260045260246000fd5b6000602082840312156135c957600080fd5b8135611e5a8161315e565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff8111828210171561360d5761360d6135d4565b60405290565b60405160a0810167ffffffffffffffff8111828210171561360d5761360d6135d4565b60405160e0810167ffffffffffffffff8111828210171561360d5761360d6135d4565b604051601f8201601f1916810167ffffffffffffffff81118282101715613682576136826135d4565b604052919050565b67ffffffffffffffff81168114610e5e57600080fd5b6000604082840312156136b257600080fd5b6136ba6135ea565b9050813567ffffffffffffffff808211156136d457600080fd5b818401915084601f8301126136e857600080fd5b81356020828211156136fc576136fc6135d4565b61370e601f8301601f19168201613659565b9250818352868183860101111561372457600080fd5b8181850182850137600081838501015282855280860135818601525050505092915050565b600081360361016081121561375d57600080fd5b613765613613565b83356137708161315e565b815260e0601f198301121561378457600080fd5b61378c613636565b9150602084013561379c8161368a565b8083525060408401356020830152606084013560408301526080840135606083015260a0840135608083015260c084013560a083015260e08401356137e08161368a565b60c083015260208101919091526101008301359067ffffffffffffffff82111561380957600080fd5b613815368386016136a0565b604082015261012084013560608201526101409093013560808401525090919050565b60006020828403121561384a57600080fd5b8135611e5a8161368a565b600081356109358161368a565b60008235603e1983360301811261387857600080fd5b9190910192915050565b601f821115610e4f576000816000526020600020601f850160051c810160208610156138ab5750805b601f850160051c820191505b8181101561091a578281556001016138b7565b8135601e198336030181126138de57600080fd5b8201803567ffffffffffffffff8111156138f757600080fd5b6020813603818401131561390a57600080fd5b61391e826139188654613583565b86613882565b6000601f831160018114613954576000841561393c57508482018301355b600019600386901b1c1916600185901b1786556139b1565b600086815260209020601f19851690835b82811015613986578785018601358255938501936001909101908501613965565b50858210156139a55760001960f88760031b161c198585890101351681555b505060018460011b0186555b50508085013560018501555050505050565b81356139ce8161315e565b6001600160a01b03811673ffffffffffffffffffffffffffffffffffffffff19835416178255506020820135613a038161368a565b60018201805467ffffffffffffffff191667ffffffffffffffff83161790555060408201356002820155606082013560038201556080820135600482015560a0820135600582015560c08201356006820155613a87613a6460e08401613855565b6007830167ffffffffffffffff821667ffffffffffffffff198254161781555050565b613aa1613a98610100840184613862565b600883016138ca565b610120820135600a820155610140820135600b8201555050565b83815261012081018335613ace8161368a565b67ffffffffffffffff8082166020850152602086013560408501526040860135606085015260608601356080850152608086013560a085015260a086013560c085015260c08601359150613b218261368a565b1660e08301526101009091019190915292915050565b600060208284031215613b4957600080fd5b81518015158114611e5a57600080fd5b634e487b7160e01b600052600160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b61ffff828116828216039080821115613024576130246134f2565b82358152602080840135908201526000610120828101613bd0604085016040880180358252602090810135910152565b613bea608085016080880180358252602090810135910152565b613c0460c0850160c0880180358252602090810135910152565b61010084019190915283519081905261014083019060209081860160005b82811015613c3e57815185529383019390830190600101613c22565b5092979650505050505050565b634e487b7160e01b600052603160045260246000fdfea26469706673582212201734667e2912f3ec0ced846ccd2aacfe7f1b3040e228245e555c67a7c591bbcf64736f6c63430008170033", "devdoc": { "kind": "dev", "methods": { @@ -1301,7 +1301,7 @@ } }, "withdrawFunds(bytes32)": { - "details": "Request must be expired, must be in RequestStat e.New, and the transaction must originate from the depositer address.", + "details": "Request must be cancelled, failed or finished, and the transaction must originate from the depositor address.", "params": { "requestId": "the id of the request" } @@ -1343,15 +1343,15 @@ "storageLayout": { "storage": [ { - "astId": 5532, + "astId": 5628, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_reservations", "offset": 0, "slot": "0", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_struct(AddressSet)1902_storage)" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_struct(AddressSet)1902_storage)" }, { - "astId": 5535, + "astId": 5631, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_config", "offset": 0, @@ -1359,7 +1359,7 @@ "type": "t_struct(SlotReservationsConfig)2226_storage" }, { - "astId": 4783, + "astId": 4892, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_config", "offset": 0, @@ -1367,7 +1367,7 @@ "type": "t_struct(ProofConfig)2223_storage" }, { - "astId": 4786, + "astId": 4895, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_verifier", "offset": 0, @@ -1375,47 +1375,47 @@ "type": "t_contract(IGroth16Verifier)2412" }, { - "astId": 4822, + "astId": 4931, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_slotStarts", "offset": 0, "slot": "8", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_uint256)" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_uint256)" }, { - "astId": 4827, + "astId": 4936, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_probabilities", "offset": 0, "slot": "9", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_uint256)" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_uint256)" }, { - "astId": 4832, + "astId": 4941, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_missed", "offset": 0, "slot": "10", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_uint256)" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_uint256)" }, { - "astId": 4840, + "astId": 4949, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_received", "offset": 0, "slot": "11", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_mapping(t_userDefinedValueType(Period)4640,t_bool))" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_mapping(t_userDefinedValueType(Period)4749,t_bool))" }, { - "astId": 4848, + "astId": 4957, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_missing", "offset": 0, "slot": "12", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_mapping(t_userDefinedValueType(Period)4640,t_bool))" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_mapping(t_userDefinedValueType(Period)4749,t_bool))" }, { - "astId": 5664, + "astId": 5760, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_requestsPerClient", "offset": 0, @@ -1423,7 +1423,7 @@ "type": "t_mapping(t_address,t_struct(Bytes32Set)1781_storage)" }, { - "astId": 5669, + "astId": 5765, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_slotsPerHost", "offset": 0, @@ -1431,7 +1431,7 @@ "type": "t_mapping(t_address,t_struct(Bytes32Set)1781_storage)" }, { - "astId": 3035, + "astId": 3039, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_config", "offset": 0, @@ -1439,36 +1439,36 @@ "type": "t_struct(MarketplaceConfig)2202_storage" }, { - "astId": 3041, + "astId": 3045, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_requests", "offset": 0, "slot": "22", - "type": "t_mapping(t_userDefinedValueType(RequestId)5367,t_struct(Request)5382_storage)" + "type": "t_mapping(t_userDefinedValueType(RequestId)5476,t_struct(Request)5491_storage)" }, { - "astId": 3047, + "astId": 3051, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_requestContexts", "offset": 0, "slot": "23", - "type": "t_mapping(t_userDefinedValueType(RequestId)5367,t_struct(RequestContext)3071_storage)" + "type": "t_mapping(t_userDefinedValueType(RequestId)5476,t_struct(RequestContext)3075_storage)" }, { - "astId": 3053, + "astId": 3057, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_slots", "offset": 0, "slot": "24", - "type": "t_mapping(t_userDefinedValueType(SlotId)5369,t_struct(Slot)3088_storage)" + "type": "t_mapping(t_userDefinedValueType(SlotId)5478,t_struct(Slot)3092_storage)" }, { - "astId": 3056, + "astId": 3060, "contract": "contracts/Marketplace.sol:Marketplace", "label": "_marketplaceTotals", "offset": 0, "slot": "25", - "type": "t_struct(MarketplaceTotals)4635_storage" + "type": "t_struct(MarketplaceTotals)4744_storage" } ], "types": { @@ -1498,12 +1498,12 @@ "label": "contract IGroth16Verifier", "numberOfBytes": "20" }, - "t_enum(RequestState)5408": { + "t_enum(RequestState)5517": { "encoding": "inplace", "label": "enum RequestState", "numberOfBytes": "1" }, - "t_enum(SlotState)5415": { + "t_enum(SlotState)5524": { "encoding": "inplace", "label": "enum SlotState", "numberOfBytes": "1" @@ -1522,51 +1522,51 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_mapping(t_userDefinedValueType(Period)4640,t_bool)": { + "t_mapping(t_userDefinedValueType(Period)4749,t_bool)": { "encoding": "mapping", - "key": "t_userDefinedValueType(Period)4640", + "key": "t_userDefinedValueType(Period)4749", "label": "mapping(Periods.Period => bool)", "numberOfBytes": "32", "value": "t_bool" }, - "t_mapping(t_userDefinedValueType(RequestId)5367,t_struct(Request)5382_storage)": { + "t_mapping(t_userDefinedValueType(RequestId)5476,t_struct(Request)5491_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(RequestId)5367", + "key": "t_userDefinedValueType(RequestId)5476", "label": "mapping(RequestId => struct Request)", "numberOfBytes": "32", - "value": "t_struct(Request)5382_storage" + "value": "t_struct(Request)5491_storage" }, - "t_mapping(t_userDefinedValueType(RequestId)5367,t_struct(RequestContext)3071_storage)": { + "t_mapping(t_userDefinedValueType(RequestId)5476,t_struct(RequestContext)3075_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(RequestId)5367", + "key": "t_userDefinedValueType(RequestId)5476", "label": "mapping(RequestId => struct Marketplace.RequestContext)", "numberOfBytes": "32", - "value": "t_struct(RequestContext)3071_storage" + "value": "t_struct(RequestContext)3075_storage" }, - "t_mapping(t_userDefinedValueType(SlotId)5369,t_mapping(t_userDefinedValueType(Period)4640,t_bool))": { + "t_mapping(t_userDefinedValueType(SlotId)5478,t_mapping(t_userDefinedValueType(Period)4749,t_bool))": { "encoding": "mapping", - "key": "t_userDefinedValueType(SlotId)5369", + "key": "t_userDefinedValueType(SlotId)5478", "label": "mapping(SlotId => mapping(Periods.Period => bool))", "numberOfBytes": "32", - "value": "t_mapping(t_userDefinedValueType(Period)4640,t_bool)" + "value": "t_mapping(t_userDefinedValueType(Period)4749,t_bool)" }, - "t_mapping(t_userDefinedValueType(SlotId)5369,t_struct(AddressSet)1902_storage)": { + "t_mapping(t_userDefinedValueType(SlotId)5478,t_struct(AddressSet)1902_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(SlotId)5369", + "key": "t_userDefinedValueType(SlotId)5478", "label": "mapping(SlotId => struct EnumerableSet.AddressSet)", "numberOfBytes": "32", "value": "t_struct(AddressSet)1902_storage" }, - "t_mapping(t_userDefinedValueType(SlotId)5369,t_struct(Slot)3088_storage)": { + "t_mapping(t_userDefinedValueType(SlotId)5478,t_struct(Slot)3092_storage)": { "encoding": "mapping", - "key": "t_userDefinedValueType(SlotId)5369", + "key": "t_userDefinedValueType(SlotId)5478", "label": "mapping(SlotId => struct Marketplace.Slot)", "numberOfBytes": "32", - "value": "t_struct(Slot)3088_storage" + "value": "t_struct(Slot)3092_storage" }, - "t_mapping(t_userDefinedValueType(SlotId)5369,t_uint256)": { + "t_mapping(t_userDefinedValueType(SlotId)5478,t_uint256)": { "encoding": "mapping", - "key": "t_userDefinedValueType(SlotId)5369", + "key": "t_userDefinedValueType(SlotId)5478", "label": "mapping(SlotId => uint256)", "numberOfBytes": "32", "value": "t_uint256" @@ -1591,12 +1591,12 @@ ], "numberOfBytes": "64" }, - "t_struct(Ask)5397_storage": { + "t_struct(Ask)5506_storage": { "encoding": "inplace", "label": "struct Ask", "members": [ { - "astId": 5384, + "astId": 5493, "contract": "contracts/Marketplace.sol:Marketplace", "label": "slots", "offset": 0, @@ -1604,7 +1604,7 @@ "type": "t_uint64" }, { - "astId": 5386, + "astId": 5495, "contract": "contracts/Marketplace.sol:Marketplace", "label": "slotSize", "offset": 0, @@ -1612,7 +1612,7 @@ "type": "t_uint256" }, { - "astId": 5388, + "astId": 5497, "contract": "contracts/Marketplace.sol:Marketplace", "label": "duration", "offset": 0, @@ -1620,7 +1620,7 @@ "type": "t_uint256" }, { - "astId": 5390, + "astId": 5499, "contract": "contracts/Marketplace.sol:Marketplace", "label": "proofProbability", "offset": 0, @@ -1628,7 +1628,7 @@ "type": "t_uint256" }, { - "astId": 5392, + "astId": 5501, "contract": "contracts/Marketplace.sol:Marketplace", "label": "reward", "offset": 0, @@ -1636,7 +1636,7 @@ "type": "t_uint256" }, { - "astId": 5394, + "astId": 5503, "contract": "contracts/Marketplace.sol:Marketplace", "label": "collateral", "offset": 0, @@ -1644,7 +1644,7 @@ "type": "t_uint256" }, { - "astId": 5396, + "astId": 5505, "contract": "contracts/Marketplace.sol:Marketplace", "label": "maxSlotLoss", "offset": 0, @@ -1708,12 +1708,12 @@ ], "numberOfBytes": "32" }, - "t_struct(Content)5402_storage": { + "t_struct(Content)5511_storage": { "encoding": "inplace", "label": "struct Content", "members": [ { - "astId": 5399, + "astId": 5508, "contract": "contracts/Marketplace.sol:Marketplace", "label": "cid", "offset": 0, @@ -1721,7 +1721,7 @@ "type": "t_string_storage" }, { - "astId": 5401, + "astId": 5510, "contract": "contracts/Marketplace.sol:Marketplace", "label": "merkleRoot", "offset": 0, @@ -1762,12 +1762,12 @@ ], "numberOfBytes": "224" }, - "t_struct(MarketplaceTotals)4635_storage": { + "t_struct(MarketplaceTotals)4744_storage": { "encoding": "inplace", "label": "struct Marketplace.MarketplaceTotals", "members": [ { - "astId": 4632, + "astId": 4741, "contract": "contracts/Marketplace.sol:Marketplace", "label": "received", "offset": 0, @@ -1775,7 +1775,7 @@ "type": "t_uint256" }, { - "astId": 4634, + "astId": 4743, "contract": "contracts/Marketplace.sol:Marketplace", "label": "sent", "offset": 0, @@ -1832,12 +1832,12 @@ ], "numberOfBytes": "160" }, - "t_struct(Request)5382_storage": { + "t_struct(Request)5491_storage": { "encoding": "inplace", "label": "struct Request", "members": [ { - "astId": 5371, + "astId": 5480, "contract": "contracts/Marketplace.sol:Marketplace", "label": "client", "offset": 0, @@ -1845,23 +1845,23 @@ "type": "t_address" }, { - "astId": 5374, + "astId": 5483, "contract": "contracts/Marketplace.sol:Marketplace", "label": "ask", "offset": 0, "slot": "1", - "type": "t_struct(Ask)5397_storage" + "type": "t_struct(Ask)5506_storage" }, { - "astId": 5377, + "astId": 5486, "contract": "contracts/Marketplace.sol:Marketplace", "label": "content", "offset": 0, "slot": "8", - "type": "t_struct(Content)5402_storage" + "type": "t_struct(Content)5511_storage" }, { - "astId": 5379, + "astId": 5488, "contract": "contracts/Marketplace.sol:Marketplace", "label": "expiry", "offset": 0, @@ -1869,7 +1869,7 @@ "type": "t_uint256" }, { - "astId": 5381, + "astId": 5490, "contract": "contracts/Marketplace.sol:Marketplace", "label": "nonce", "offset": 0, @@ -1879,20 +1879,20 @@ ], "numberOfBytes": "384" }, - "t_struct(RequestContext)3071_storage": { + "t_struct(RequestContext)3075_storage": { "encoding": "inplace", "label": "struct Marketplace.RequestContext", "members": [ { - "astId": 3059, + "astId": 3063, "contract": "contracts/Marketplace.sol:Marketplace", "label": "state", "offset": 0, "slot": "0", - "type": "t_enum(RequestState)5408" + "type": "t_enum(RequestState)5517" }, { - "astId": 3061, + "astId": 3065, "contract": "contracts/Marketplace.sol:Marketplace", "label": "slotsFilled", "offset": 0, @@ -1900,15 +1900,15 @@ "type": "t_uint256" }, { - "astId": 3064, + "astId": 3068, "contract": "contracts/Marketplace.sol:Marketplace", - "label": "expiryFundsWithdraw", + "label": "fundsToReturnToClient", "offset": 0, "slot": "2", "type": "t_uint256" }, { - "astId": 3066, + "astId": 3070, "contract": "contracts/Marketplace.sol:Marketplace", "label": "startedAt", "offset": 0, @@ -1916,7 +1916,7 @@ "type": "t_uint256" }, { - "astId": 3068, + "astId": 3072, "contract": "contracts/Marketplace.sol:Marketplace", "label": "endsAt", "offset": 0, @@ -1924,7 +1924,7 @@ "type": "t_uint256" }, { - "astId": 3070, + "astId": 3074, "contract": "contracts/Marketplace.sol:Marketplace", "label": "expiresAt", "offset": 0, @@ -1957,28 +1957,28 @@ ], "numberOfBytes": "64" }, - "t_struct(Slot)3088_storage": { + "t_struct(Slot)3092_storage": { "encoding": "inplace", "label": "struct Marketplace.Slot", "members": [ { - "astId": 3074, + "astId": 3078, "contract": "contracts/Marketplace.sol:Marketplace", "label": "state", "offset": 0, "slot": "0", - "type": "t_enum(SlotState)5415" + "type": "t_enum(SlotState)5524" }, { - "astId": 3077, + "astId": 3081, "contract": "contracts/Marketplace.sol:Marketplace", "label": "requestId", "offset": 0, "slot": "1", - "type": "t_userDefinedValueType(RequestId)5367" + "type": "t_userDefinedValueType(RequestId)5476" }, { - "astId": 3080, + "astId": 3084, "contract": "contracts/Marketplace.sol:Marketplace", "label": "filledAt", "offset": 0, @@ -1986,7 +1986,7 @@ "type": "t_uint256" }, { - "astId": 3082, + "astId": 3086, "contract": "contracts/Marketplace.sol:Marketplace", "label": "slotIndex", "offset": 0, @@ -1994,7 +1994,7 @@ "type": "t_uint256" }, { - "astId": 3085, + "astId": 3089, "contract": "contracts/Marketplace.sol:Marketplace", "label": "currentCollateral", "offset": 0, @@ -2002,7 +2002,7 @@ "type": "t_uint256" }, { - "astId": 3087, + "astId": 3091, "contract": "contracts/Marketplace.sol:Marketplace", "label": "host", "offset": 0, @@ -2047,17 +2047,17 @@ "label": "uint8", "numberOfBytes": "1" }, - "t_userDefinedValueType(Period)4640": { + "t_userDefinedValueType(Period)4749": { "encoding": "inplace", "label": "Periods.Period", "numberOfBytes": "32" }, - "t_userDefinedValueType(RequestId)5367": { + "t_userDefinedValueType(RequestId)5476": { "encoding": "inplace", "label": "RequestId", "numberOfBytes": "32" }, - "t_userDefinedValueType(SlotId)5369": { + "t_userDefinedValueType(SlotId)5478": { "encoding": "inplace", "label": "SlotId", "numberOfBytes": "32" diff --git a/deployments/codex_testnet/solcInputs/73497e5b46b1a1eec0c64f9cd6de8fb8.json b/deployments/codex_testnet/solcInputs/73497e5b46b1a1eec0c64f9cd6de8fb8.json new file mode 100644 index 0000000..bbdc9cf --- /dev/null +++ b/deployments/codex_testnet/solcInputs/73497e5b46b1a1eec0c64f9cd6de8fb8.json @@ -0,0 +1,102 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.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.openzeppelin.com/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 `from` to `to`.\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 // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\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 unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\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 // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\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/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/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/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/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/structs/EnumerableSet.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)\n// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for managing\n * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive\n * types.\n *\n * Sets have the following properties:\n *\n * - Elements are added, removed, and checked for existence in constant time\n * (O(1)).\n * - Elements are enumerated in O(n). No guarantees are made on the ordering.\n *\n * ```\n * contract Example {\n * // Add the library methods\n * using EnumerableSet for EnumerableSet.AddressSet;\n *\n * // Declare a set state variable\n * EnumerableSet.AddressSet private mySet;\n * }\n * ```\n *\n * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)\n * and `uint256` (`UintSet`) are supported.\n *\n * [WARNING]\n * ====\n * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure\n * unusable.\n * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.\n *\n * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an\n * array of EnumerableSet.\n * ====\n */\nlibrary EnumerableSet {\n // To implement this library for multiple types with as little code\n // repetition as possible, we write it in terms of a generic Set type with\n // bytes32 values.\n // The Set implementation uses private functions, and user-facing\n // implementations (such as AddressSet) are just wrappers around the\n // underlying Set.\n // This means that we can only create new EnumerableSets for types that fit\n // in bytes32.\n\n struct Set {\n // Storage of set values\n bytes32[] _values;\n // Position of the value in the `values` array, plus 1 because index 0\n // means a value is not in the set.\n mapping(bytes32 => uint256) _indexes;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function _add(Set storage set, bytes32 value) private returns (bool) {\n if (!_contains(set, value)) {\n set._values.push(value);\n // The value is stored at length-1, but we add 1 to all indexes\n // and use 0 as a sentinel value\n set._indexes[value] = set._values.length;\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function _remove(Set storage set, bytes32 value) private returns (bool) {\n // We read and store the value's index to prevent multiple reads from the same storage slot\n uint256 valueIndex = set._indexes[value];\n\n if (valueIndex != 0) {\n // Equivalent to contains(set, value)\n // To delete an element from the _values array in O(1), we swap the element to delete with the last one in\n // the array, and then remove the last element (sometimes called as 'swap and pop').\n // This modifies the order of the array, as noted in {at}.\n\n uint256 toDeleteIndex = valueIndex - 1;\n uint256 lastIndex = set._values.length - 1;\n\n if (lastIndex != toDeleteIndex) {\n bytes32 lastValue = set._values[lastIndex];\n\n // Move the last value to the index where the value to delete is\n set._values[toDeleteIndex] = lastValue;\n // Update the index for the moved value\n set._indexes[lastValue] = valueIndex; // Replace lastValue's index to valueIndex\n }\n\n // Delete the slot where the moved value was stored\n set._values.pop();\n\n // Delete the index for the deleted slot\n delete set._indexes[value];\n\n return true;\n } else {\n return false;\n }\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function _contains(Set storage set, bytes32 value) private view returns (bool) {\n return set._indexes[value] != 0;\n }\n\n /**\n * @dev Returns the number of values on the set. O(1).\n */\n function _length(Set storage set) private view returns (uint256) {\n return set._values.length;\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function _at(Set storage set, uint256 index) private view returns (bytes32) {\n return set._values[index];\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function _values(Set storage set) private view returns (bytes32[] memory) {\n return set._values;\n }\n\n // Bytes32Set\n\n struct Bytes32Set {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _add(set._inner, value);\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {\n return _remove(set._inner, value);\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {\n return _contains(set._inner, value);\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(Bytes32Set storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {\n return _at(set._inner, index);\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {\n bytes32[] memory store = _values(set._inner);\n bytes32[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // AddressSet\n\n struct AddressSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(AddressSet storage set, address value) internal returns (bool) {\n return _add(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(AddressSet storage set, address value) internal returns (bool) {\n return _remove(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(AddressSet storage set, address value) internal view returns (bool) {\n return _contains(set._inner, bytes32(uint256(uint160(value))));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(AddressSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(AddressSet storage set, uint256 index) internal view returns (address) {\n return address(uint160(uint256(_at(set._inner, index))));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(AddressSet storage set) internal view returns (address[] memory) {\n bytes32[] memory store = _values(set._inner);\n address[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n\n // UintSet\n\n struct UintSet {\n Set _inner;\n }\n\n /**\n * @dev Add a value to a set. O(1).\n *\n * Returns true if the value was added to the set, that is if it was not\n * already present.\n */\n function add(UintSet storage set, uint256 value) internal returns (bool) {\n return _add(set._inner, bytes32(value));\n }\n\n /**\n * @dev Removes a value from a set. O(1).\n *\n * Returns true if the value was removed from the set, that is if it was\n * present.\n */\n function remove(UintSet storage set, uint256 value) internal returns (bool) {\n return _remove(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns true if the value is in the set. O(1).\n */\n function contains(UintSet storage set, uint256 value) internal view returns (bool) {\n return _contains(set._inner, bytes32(value));\n }\n\n /**\n * @dev Returns the number of values in the set. O(1).\n */\n function length(UintSet storage set) internal view returns (uint256) {\n return _length(set._inner);\n }\n\n /**\n * @dev Returns the value stored at position `index` in the set. O(1).\n *\n * Note that there are no guarantees on the ordering of values inside the\n * array, and it may change when more values are added or removed.\n *\n * Requirements:\n *\n * - `index` must be strictly less than {length}.\n */\n function at(UintSet storage set, uint256 index) internal view returns (uint256) {\n return uint256(_at(set._inner, index));\n }\n\n /**\n * @dev Return the entire set in an array\n *\n * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed\n * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that\n * this function has an unbounded cost, and using it as part of a state-changing function may render the function\n * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\n */\n function values(UintSet storage set) internal view returns (uint256[] memory) {\n bytes32[] memory store = _values(set._inner);\n uint256[] memory result;\n\n /// @solidity memory-safe-assembly\n assembly {\n result := store\n }\n\n return result;\n }\n}\n" + }, + "contracts/Configuration.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\nstruct MarketplaceConfig {\n CollateralConfig collateral;\n ProofConfig proofs;\n SlotReservationsConfig reservations;\n}\n\nstruct CollateralConfig {\n /// @dev percentage of remaining collateral slot after it has been freed\n /// (equivalent to `collateral - (collateral*maxNumberOfSlashes*slashPercentage)/100`)\n /// TODO: to be aligned more closely with actual cost of repair once bandwidth incentives are known,\n /// see https://github.com/codex-storage/codex-contracts-eth/pull/47#issuecomment-1465511949.\n uint8 repairRewardPercentage;\n uint8 maxNumberOfSlashes; // frees slot when the number of slashing reaches this value\n uint16 slashCriterion; // amount of proofs missed that lead to slashing\n uint8 slashPercentage; // percentage of the collateral that is slashed\n}\n\nstruct ProofConfig {\n uint256 period; // proofs requirements are calculated per period (in seconds)\n uint256 timeout; // mark proofs as missing before the timeout (in seconds)\n uint8 downtime; // ignore this much recent blocks for proof requirements\n string zkeyHash; // hash of the zkey file which is linked to the verifier\n // Ensures the pointer does not remain in downtime for many consecutive\n // periods. For each period increase, move the pointer `pointerProduct`\n // blocks. Should be a prime number to ensure there are no cycles.\n uint8 downtimeProduct;\n}\n\nstruct SlotReservationsConfig {\n // Number of allowed reservations per slot\n uint8 maxReservations;\n}\n" + }, + "contracts/Endian.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\ncontract Endian {\n /// reverses byte order to allow conversion between little endian and big\n /// endian integers\n function _byteSwap(bytes32 input) internal pure returns (bytes32 output) {\n output = output | bytes1(input);\n for (uint i = 1; i < 32; i++) {\n output = output >> 8;\n output = output | bytes1(input << (i * 8));\n }\n }\n}\n" + }, + "contracts/FuzzMarketplace.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"./TestToken.sol\";\nimport \"./Marketplace.sol\";\nimport \"./TestVerifier.sol\";\n\ncontract FuzzMarketplace is Marketplace {\n constructor()\n Marketplace(\n MarketplaceConfig(\n CollateralConfig(10, 5, 3, 10),\n ProofConfig(10, 5, 64, \"\", 67),\n SlotReservationsConfig(20)\n ),\n new TestToken(),\n new TestVerifier()\n )\n // solhint-disable-next-line no-empty-blocks\n {\n\n }\n\n // Properties to be tested through fuzzing\n\n MarketplaceTotals private _lastSeenTotals;\n\n function neverDecreaseTotals() public {\n assert(_marketplaceTotals.received >= _lastSeenTotals.received);\n assert(_marketplaceTotals.sent >= _lastSeenTotals.sent);\n _lastSeenTotals = _marketplaceTotals;\n }\n\n function neverLoseFunds() public view {\n uint256 total = _marketplaceTotals.received - _marketplaceTotals.sent;\n assert(token().balanceOf(address(this)) >= total);\n }\n}\n" + }, + "contracts/Groth16.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nstruct G1Point {\n uint256 x;\n uint256 y;\n}\n\n// A field element F_{p^2} encoded as `real + i * imag`.\n// We chose to not represent this as an array of 2 numbers, because both Circom\n// and Ethereum EIP-197 encode to an array, but with conflicting encodings.\nstruct Fp2Element {\n uint256 real;\n uint256 imag;\n}\n\nstruct G2Point {\n Fp2Element x;\n Fp2Element y;\n}\n\nstruct Groth16Proof {\n G1Point a;\n G2Point b;\n G1Point c;\n}\n\ninterface IGroth16Verifier {\n function verify(\n Groth16Proof calldata proof,\n uint256[] calldata pubSignals\n ) external view returns (bool);\n}\n" + }, + "contracts/Groth16Verifier.sol": { + "content": "// Copyright 2017 Christian Reitwiessner\n// Copyright 2019 OKIMS\n// Copyright 2024 Codex\n// Permission is hereby granted, free of charge, to any person obtaining a copy\n// of this software and associated documentation files (the \"Software\"), to deal\n// in the Software without restriction, including without limitation the rights\n// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n// copies of the Software, and to permit persons to whom the Software is\n// furnished to do so, subject to the following conditions:\n// The above copyright notice and this permission notice shall be included in\n// all copies or substantial portions of the Software.\n// THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n// SOFTWARE.\n// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\nimport \"./Groth16.sol\";\n\ncontract Groth16Verifier is IGroth16Verifier {\n uint256 private constant _P =\n 21888242871839275222246405745257275088696311157297823662689037894645226208583;\n uint256 private constant _R =\n 21888242871839275222246405745257275088548364400416034343698204186575808495617;\n\n VerifyingKey private _verifyingKey;\n\n struct VerifyingKey {\n G1Point alpha1;\n G2Point beta2;\n G2Point gamma2;\n G2Point delta2;\n G1Point[] ic;\n }\n\n constructor(VerifyingKey memory key) {\n _verifyingKey.alpha1 = key.alpha1;\n _verifyingKey.beta2 = key.beta2;\n _verifyingKey.gamma2 = key.gamma2;\n _verifyingKey.delta2 = key.delta2;\n for (uint i = 0; i < key.ic.length; i++) {\n _verifyingKey.ic.push(key.ic[i]);\n }\n }\n\n function _negate(G1Point memory point) private pure returns (G1Point memory) {\n return G1Point(point.x, (_P - point.y) % _P);\n }\n\n function _add(\n G1Point memory point1,\n G1Point memory point2\n ) private view returns (bool success, G1Point memory sum) {\n // Call the precompiled contract for addition on the alt_bn128 curve.\n // The call will fail if the points are not valid group elements:\n // https://eips.ethereum.org/EIPS/eip-196#exact-semantics\n\n uint256[4] memory input;\n input[0] = point1.x;\n input[1] = point1.y;\n input[2] = point2.x;\n input[3] = point2.y;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n success := staticcall(gas(), 6, input, 128, sum, 64)\n }\n }\n\n function _multiply(\n G1Point memory point,\n uint256 scalar\n ) private view returns (bool success, G1Point memory product) {\n // Call the precompiled contract for scalar multiplication on the alt_bn128\n // curve. The call will fail if the points are not valid group elements:\n // https://eips.ethereum.org/EIPS/eip-196#exact-semantics\n\n uint256[3] memory input;\n input[0] = point.x;\n input[1] = point.y;\n input[2] = scalar;\n // solhint-disable-next-line no-inline-assembly\n assembly {\n success := staticcall(gas(), 7, input, 96, product, 64)\n }\n }\n\n function _checkPairing(\n G1Point memory a1,\n G2Point memory a2,\n G1Point memory b1,\n G2Point memory b2,\n G1Point memory c1,\n G2Point memory c2,\n G1Point memory d1,\n G2Point memory d2\n ) private view returns (bool success, uint256 outcome) {\n // Call the precompiled contract for pairing check on the alt_bn128 curve.\n // The call will fail if the points are not valid group elements:\n // https://eips.ethereum.org/EIPS/eip-197#specification\n\n uint256[24] memory input; // 4 pairs of G1 and G2 points\n uint256[1] memory output;\n\n input[0] = a1.x;\n input[1] = a1.y;\n input[2] = a2.x.imag;\n input[3] = a2.x.real;\n input[4] = a2.y.imag;\n input[5] = a2.y.real;\n\n input[6] = b1.x;\n input[7] = b1.y;\n input[8] = b2.x.imag;\n input[9] = b2.x.real;\n input[10] = b2.y.imag;\n input[11] = b2.y.real;\n\n input[12] = c1.x;\n input[13] = c1.y;\n input[14] = c2.x.imag;\n input[15] = c2.x.real;\n input[16] = c2.y.imag;\n input[17] = c2.y.real;\n\n input[18] = d1.x;\n input[19] = d1.y;\n input[20] = d2.x.imag;\n input[21] = d2.x.real;\n input[22] = d2.y.imag;\n input[23] = d2.y.real;\n\n // solhint-disable-next-line no-inline-assembly\n assembly {\n success := staticcall(gas(), 8, input, 768, output, 32)\n }\n return (success, output[0]);\n }\n\n function verify(\n Groth16Proof calldata proof,\n uint256[] memory input\n ) public view returns (bool success) {\n // Check amount of public inputs\n if (input.length + 1 != _verifyingKey.ic.length) {\n return false;\n }\n // Check that public inputs are field elements\n for (uint i = 0; i < input.length; i++) {\n if (input[i] >= _R) {\n return false;\n }\n }\n // Compute the linear combination\n G1Point memory combination = _verifyingKey.ic[0];\n for (uint i = 0; i < input.length; i++) {\n G1Point memory product;\n (success, product) = _multiply(_verifyingKey.ic[i + 1], input[i]);\n if (!success) {\n return false;\n }\n (success, combination) = _add(combination, product);\n if (!success) {\n return false;\n }\n }\n // Check the pairing\n uint256 outcome;\n (success, outcome) = _checkPairing(\n _negate(proof.a),\n proof.b,\n _verifyingKey.alpha1,\n _verifyingKey.beta2,\n combination,\n _verifyingKey.gamma2,\n proof.c,\n _verifyingKey.delta2\n );\n if (!success) {\n return false;\n }\n return outcome == 1;\n }\n}\n" + }, + "contracts/Marketplace.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/utils/math/Math.sol\";\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"./Configuration.sol\";\nimport \"./Requests.sol\";\nimport \"./Proofs.sol\";\nimport \"./SlotReservations.sol\";\nimport \"./StateRetrieval.sol\";\nimport \"./Endian.sol\";\nimport \"./Groth16.sol\";\n\ncontract Marketplace is SlotReservations, Proofs, StateRetrieval, Endian {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n using EnumerableSet for EnumerableSet.AddressSet;\n using Requests for Request;\n\n IERC20 private immutable _token;\n MarketplaceConfig private _config;\n\n mapping(RequestId => Request) private _requests;\n mapping(RequestId => RequestContext) internal _requestContexts;\n mapping(SlotId => Slot) internal _slots;\n\n MarketplaceTotals internal _marketplaceTotals;\n\n struct RequestContext {\n RequestState state;\n uint256 slotsFilled;\n /// @notice Tracks how much funds should be returned to the client as not all funds might be used for hosting the request\n /// @dev The sum starts with the full reward amount for the request and is reduced every time a host fills a slot.\n /// The reduction is calculated from the duration of time between the slot being filled and the request's end.\n /// This is the amount that will be paid out to the host when the request successfully finishes.\n /// @dev fundsToReturnToClient == 0 is used to signal that after request is terminated all the remaining funds were withdrawn.\n /// This is possible, because technically it is not possible for this variable to reach 0 in \"natural\" way as\n /// that would require all the slots to be filled at the same block as the request was created.\n uint256 fundsToReturnToClient;\n uint256 startedAt;\n uint256 endsAt;\n uint256 expiresAt;\n }\n\n struct Slot {\n SlotState state;\n RequestId requestId;\n /// @notice Timestamp that signals when slot was filled\n /// @dev Used for calculating payouts as hosts are paid based on time they actually host the content\n uint256 filledAt;\n uint256 slotIndex;\n /// @notice Tracks the current amount of host's collateral that is to be payed out at the end of Slot's lifespan.\n /// @dev When Slot is filled, the collateral is collected in amount of request.ask.collateral\n /// @dev When Host is slashed for missing a proof the slashed amount is reflected in this variable\n uint256 currentCollateral;\n address host; // address used for collateral interactions and identifying hosts\n }\n\n struct ActiveSlot {\n Request request;\n uint256 slotIndex;\n }\n\n constructor(\n MarketplaceConfig memory configuration,\n IERC20 token_,\n IGroth16Verifier verifier\n )\n SlotReservations(configuration.reservations)\n Proofs(configuration.proofs, verifier)\n {\n _token = token_;\n\n require(\n configuration.collateral.repairRewardPercentage <= 100,\n \"Must be less than 100\"\n );\n require(\n configuration.collateral.slashPercentage <= 100,\n \"Must be less than 100\"\n );\n require(\n configuration.collateral.maxNumberOfSlashes *\n configuration.collateral.slashPercentage <=\n 100,\n \"Maximum slashing exceeds 100%\"\n );\n _config = configuration;\n }\n\n function config() public view returns (MarketplaceConfig memory) {\n return _config;\n }\n\n function token() public view returns (IERC20) {\n return _token;\n }\n\n function requestStorage(Request calldata request) public {\n require(request.client == msg.sender, \"Invalid client address\");\n\n RequestId id = request.id();\n require(_requests[id].client == address(0), \"Request already exists\");\n require(\n request.expiry > 0 && request.expiry < request.ask.duration,\n \"Expiry not in range\"\n );\n require(request.ask.slots > 0, \"Insufficient slots\");\n require(\n request.ask.maxSlotLoss <= request.ask.slots,\n \"maxSlotLoss exceeds slots\"\n );\n\n _requests[id] = request;\n _requestContexts[id].endsAt = block.timestamp + request.ask.duration;\n _requestContexts[id].expiresAt = block.timestamp + request.expiry;\n\n _addToMyRequests(request.client, id);\n\n uint256 amount = request.maxPrice();\n _requestContexts[id].fundsToReturnToClient = amount;\n _marketplaceTotals.received += amount;\n _transferFrom(msg.sender, amount);\n\n emit StorageRequested(id, request.ask, _requestContexts[id].expiresAt);\n }\n\n /**\n * @notice Fills a slot. Reverts if an invalid proof of the slot data is\n provided.\n * @param requestId RequestId identifying the request containing the slot to\n fill.\n * @param slotIndex Index of the slot in the request.\n * @param proof Groth16 proof procing possession of the slot data.\n */\n function fillSlot(\n RequestId requestId,\n uint256 slotIndex,\n Groth16Proof calldata proof\n ) public requestIsKnown(requestId) {\n Request storage request = _requests[requestId];\n require(slotIndex < request.ask.slots, \"Invalid slot\");\n\n SlotId slotId = Requests.slotId(requestId, slotIndex);\n require(_reservations[slotId].contains(msg.sender), \"Reservation required\");\n\n Slot storage slot = _slots[slotId];\n slot.requestId = requestId;\n slot.slotIndex = slotIndex;\n RequestContext storage context = _requestContexts[requestId];\n\n require(slotState(slotId) == SlotState.Free, \"Slot is not free\");\n\n _startRequiringProofs(slotId, request.ask.proofProbability);\n submitProof(slotId, proof);\n\n slot.host = msg.sender;\n slot.state = SlotState.Filled;\n slot.filledAt = block.timestamp;\n\n context.slotsFilled += 1;\n context.fundsToReturnToClient -= _slotPayout(requestId, slot.filledAt);\n\n // Collect collateral\n uint256 collateralAmount = request.ask.collateral;\n _transferFrom(msg.sender, collateralAmount);\n _marketplaceTotals.received += collateralAmount;\n slot.currentCollateral = collateralAmount;\n\n _addToMySlots(slot.host, slotId);\n\n emit SlotFilled(requestId, slotIndex);\n if (context.slotsFilled == request.ask.slots) {\n context.state = RequestState.Started;\n context.startedAt = block.timestamp;\n emit RequestFulfilled(requestId);\n }\n }\n\n /**\n * @notice Frees a slot, paying out rewards and returning collateral for\n finished or cancelled requests to the host that has filled the slot.\n * @param slotId id of the slot to free\n * @dev The host that filled the slot must have initiated the transaction\n (msg.sender). This overload allows `rewardRecipient` and\n `collateralRecipient` to be optional.\n */\n function freeSlot(SlotId slotId) public slotIsNotFree(slotId) {\n return freeSlot(slotId, msg.sender, msg.sender);\n }\n\n /**\n * @notice Frees a slot, paying out rewards and returning collateral for\n finished or cancelled requests.\n * @param slotId id of the slot to free\n * @param rewardRecipient address to send rewards to\n * @param collateralRecipient address to refund collateral to\n */\n function freeSlot(\n SlotId slotId,\n address rewardRecipient,\n address collateralRecipient\n ) public slotIsNotFree(slotId) {\n Slot storage slot = _slots[slotId];\n require(slot.host == msg.sender, \"Slot filled by other host\");\n SlotState state = slotState(slotId);\n require(state != SlotState.Paid, \"Already paid\");\n\n if (state == SlotState.Finished) {\n _payoutSlot(slot.requestId, slotId, rewardRecipient, collateralRecipient);\n } else if (state == SlotState.Cancelled) {\n _payoutCancelledSlot(\n slot.requestId,\n slotId,\n rewardRecipient,\n collateralRecipient\n );\n } else if (state == SlotState.Failed) {\n _removeFromMySlots(msg.sender, slotId);\n } else if (state == SlotState.Filled) {\n // free slot without returning collateral, effectively a 100% slash\n _forciblyFreeSlot(slotId);\n }\n }\n\n function _challengeToFieldElement(\n bytes32 challenge\n ) internal pure returns (uint256) {\n // use only 31 bytes of the challenge to ensure that it fits into the field\n bytes32 truncated = bytes32(bytes31(challenge));\n // convert from little endian to big endian\n bytes32 bigEndian = _byteSwap(truncated);\n // convert bytes to integer\n return uint256(bigEndian);\n }\n\n function _merkleRootToFieldElement(\n bytes32 merkleRoot\n ) internal pure returns (uint256) {\n // convert from little endian to big endian\n bytes32 bigEndian = _byteSwap(merkleRoot);\n // convert bytes to integer\n return uint256(bigEndian);\n }\n\n function submitProof(\n SlotId id,\n Groth16Proof calldata proof\n ) public requestIsKnown(_slots[id].requestId) {\n Slot storage slot = _slots[id];\n Request storage request = _requests[slot.requestId];\n uint256[] memory pubSignals = new uint256[](3);\n pubSignals[0] = _challengeToFieldElement(getChallenge(id));\n pubSignals[1] = _merkleRootToFieldElement(request.content.merkleRoot);\n pubSignals[2] = slot.slotIndex;\n _proofReceived(id, proof, pubSignals);\n }\n\n function markProofAsMissing(SlotId slotId, Period period) public {\n require(slotState(slotId) == SlotState.Filled, \"Slot not accepting proofs\");\n _markProofAsMissing(slotId, period);\n Slot storage slot = _slots[slotId];\n Request storage request = _requests[slot.requestId];\n\n // TODO: Reward for validator that calls this function\n\n if (missingProofs(slotId) % _config.collateral.slashCriterion == 0) {\n uint256 slashedAmount = (request.ask.collateral *\n _config.collateral.slashPercentage) / 100;\n slot.currentCollateral -= slashedAmount;\n if (\n missingProofs(slotId) / _config.collateral.slashCriterion >=\n _config.collateral.maxNumberOfSlashes\n ) {\n // When the number of slashings is at or above the allowed amount,\n // free the slot.\n _forciblyFreeSlot(slotId);\n }\n }\n }\n\n /**\n * @notice Abandons the slot without returning collateral, effectively slashing the\n entire collateral.\n * @param slotId SlotId of the slot to free.\n * @dev _slots[slotId] is deleted, resetting _slots[slotId].currentCollateral\n to 0.\n */\n function _forciblyFreeSlot(SlotId slotId) internal {\n Slot storage slot = _slots[slotId];\n RequestId requestId = slot.requestId;\n RequestContext storage context = _requestContexts[requestId];\n\n // We need to refund the amount of payout of the current node to the `fundsToReturnToClient` so\n // we keep correctly the track of the funds that needs to be returned at the end.\n context.fundsToReturnToClient += _slotPayout(requestId, slot.filledAt);\n\n _removeFromMySlots(slot.host, slotId);\n uint256 slotIndex = slot.slotIndex;\n delete _slots[slotId];\n context.slotsFilled -= 1;\n emit SlotFreed(requestId, slotIndex);\n _resetMissingProofs(slotId);\n\n Request storage request = _requests[requestId];\n uint256 slotsLost = request.ask.slots - context.slotsFilled;\n if (\n slotsLost > request.ask.maxSlotLoss &&\n context.state == RequestState.Started\n ) {\n context.state = RequestState.Failed;\n context.endsAt = block.timestamp - 1;\n emit RequestFailed(requestId);\n }\n }\n\n function _payoutSlot(\n RequestId requestId,\n SlotId slotId,\n address rewardRecipient,\n address collateralRecipient\n ) private requestIsKnown(requestId) {\n RequestContext storage context = _requestContexts[requestId];\n Request storage request = _requests[requestId];\n context.state = RequestState.Finished;\n Slot storage slot = _slots[slotId];\n\n _removeFromMyRequests(request.client, requestId);\n _removeFromMySlots(slot.host, slotId);\n\n uint256 payoutAmount = _slotPayout(requestId, slot.filledAt);\n uint256 collateralAmount = slot.currentCollateral;\n _marketplaceTotals.sent += (payoutAmount + collateralAmount);\n slot.state = SlotState.Paid;\n assert(_token.transfer(rewardRecipient, payoutAmount));\n assert(_token.transfer(collateralRecipient, collateralAmount));\n }\n\n /**\n * @notice Pays out a host for duration of time that the slot was filled, and\n returns the collateral.\n * @dev The payouts are sent to the rewardRecipient, and collateral is returned\n to the host address.\n * @param requestId RequestId of the request that contains the slot to be paid\n out.\n * @param slotId SlotId of the slot to be paid out.\n */\n function _payoutCancelledSlot(\n RequestId requestId,\n SlotId slotId,\n address rewardRecipient,\n address collateralRecipient\n ) private requestIsKnown(requestId) {\n Slot storage slot = _slots[slotId];\n _removeFromMySlots(slot.host, slotId);\n\n uint256 payoutAmount = _slotPayout(\n requestId,\n slot.filledAt,\n requestExpiry(requestId)\n );\n uint256 collateralAmount = slot.currentCollateral;\n _marketplaceTotals.sent += (payoutAmount + collateralAmount);\n slot.state = SlotState.Paid;\n assert(_token.transfer(rewardRecipient, payoutAmount));\n assert(_token.transfer(collateralRecipient, collateralAmount));\n }\n\n /**\n * @notice Withdraws remaining storage request funds back to the client that\n deposited them.\n * @dev Request must be cancelled, failed or finished, and the\n transaction must originate from the depositor address.\n * @param requestId the id of the request\n */\n function withdrawFunds(RequestId requestId) public {\n withdrawFunds(requestId, msg.sender);\n }\n\n /**\n * @notice Withdraws storage request funds to the provided address.\n * @dev Request must be expired, must be in RequestState.New, and the\n transaction must originate from the depositer address.\n * @param requestId the id of the request\n * @param withdrawRecipient address to return the remaining funds to\n */\n function withdrawFunds(\n RequestId requestId,\n address withdrawRecipient\n ) public {\n Request storage request = _requests[requestId];\n require(request.client == msg.sender, \"Invalid client address\");\n RequestContext storage context = _requestContexts[requestId];\n RequestState state = requestState(requestId);\n require(\n state == RequestState.Cancelled ||\n state == RequestState.Failed ||\n state == RequestState.Finished,\n \"Invalid state\"\n );\n\n // fundsToReturnToClient == 0 is used for \"double-spend\" protection, once the funds are withdrawn\n // then this variable is set to 0.\n require(context.fundsToReturnToClient != 0, \"Nothing to withdraw\");\n\n if (state == RequestState.Cancelled) {\n context.state = RequestState.Cancelled;\n emit RequestCancelled(requestId);\n\n // `fundsToReturnToClient` currently tracks funds to be returned for requests that successfully finish.\n // When requests are cancelled, funds earmarked for payment for the duration\n // between request expiry and request end (for every slot that was filled), should be returned to the client.\n // Update `fundsToReturnToClient` to reflect this.\n context.fundsToReturnToClient +=\n context.slotsFilled *\n _slotPayout(requestId, requestExpiry(requestId));\n } else if (state == RequestState.Failed) {\n // For Failed requests the client is refunded whole amount.\n context.fundsToReturnToClient = request.maxPrice();\n } else {\n context.state = RequestState.Finished;\n }\n\n _removeFromMyRequests(request.client, requestId);\n\n uint256 amount = context.fundsToReturnToClient;\n _marketplaceTotals.sent += amount;\n assert(_token.transfer(withdrawRecipient, amount));\n\n // We zero out the funds tracking in order to prevent double-spends\n context.fundsToReturnToClient = 0;\n }\n\n function getActiveSlot(\n SlotId slotId\n ) public view slotIsNotFree(slotId) returns (ActiveSlot memory) {\n Slot storage slot = _slots[slotId];\n ActiveSlot memory activeSlot;\n activeSlot.request = _requests[slot.requestId];\n activeSlot.slotIndex = slot.slotIndex;\n return activeSlot;\n }\n\n modifier requestIsKnown(RequestId requestId) {\n require(_requests[requestId].client != address(0), \"Unknown request\");\n _;\n }\n\n function getRequest(\n RequestId requestId\n ) public view requestIsKnown(requestId) returns (Request memory) {\n return _requests[requestId];\n }\n\n modifier slotIsNotFree(SlotId slotId) {\n require(_slots[slotId].state != SlotState.Free, \"Slot is free\");\n _;\n }\n\n function requestEnd(RequestId requestId) public view returns (uint256) {\n uint256 end = _requestContexts[requestId].endsAt;\n RequestState state = requestState(requestId);\n if (state == RequestState.New || state == RequestState.Started) {\n return end;\n } else {\n return Math.min(end, block.timestamp - 1);\n }\n }\n\n function requestExpiry(RequestId requestId) public view returns (uint256) {\n return _requestContexts[requestId].expiresAt;\n }\n\n /**\n * @notice Calculates the amount that should be paid out to a host that successfully finished the request\n * @param requestId RequestId of the request used to calculate the payout\n * amount.\n * @param startingTimestamp timestamp indicating when a host filled a slot and\n * started providing proofs.\n */\n function _slotPayout(\n RequestId requestId,\n uint256 startingTimestamp\n ) private view returns (uint256) {\n return\n _slotPayout(\n requestId,\n startingTimestamp,\n _requestContexts[requestId].endsAt\n );\n }\n\n /// @notice Calculates the amount that should be paid out to a host based on the specified time frame.\n function _slotPayout(\n RequestId requestId,\n uint256 startingTimestamp,\n uint256 endingTimestamp\n ) private view returns (uint256) {\n Request storage request = _requests[requestId];\n require(startingTimestamp < endingTimestamp, \"Start not before expiry\");\n\n return (endingTimestamp - startingTimestamp) * request.ask.reward;\n }\n\n function getHost(SlotId slotId) public view returns (address) {\n return _slots[slotId].host;\n }\n\n function requestState(\n RequestId requestId\n ) public view requestIsKnown(requestId) returns (RequestState) {\n RequestContext storage context = _requestContexts[requestId];\n if (\n context.state == RequestState.New &&\n block.timestamp > requestExpiry(requestId)\n ) {\n return RequestState.Cancelled;\n } else if (\n (context.state == RequestState.Started ||\n context.state == RequestState.New) && block.timestamp > context.endsAt\n ) {\n return RequestState.Finished;\n } else {\n return context.state;\n }\n }\n\n function slotState(SlotId slotId) public view override returns (SlotState) {\n Slot storage slot = _slots[slotId];\n if (RequestId.unwrap(slot.requestId) == 0) {\n return SlotState.Free;\n }\n RequestState reqState = requestState(slot.requestId);\n if (slot.state == SlotState.Paid) {\n return SlotState.Paid;\n }\n if (reqState == RequestState.Cancelled) {\n return SlotState.Cancelled;\n }\n if (reqState == RequestState.Finished) {\n return SlotState.Finished;\n }\n if (reqState == RequestState.Failed) {\n return SlotState.Failed;\n }\n return slot.state;\n }\n\n function _transferFrom(address sender, uint256 amount) internal {\n address receiver = address(this);\n require(_token.transferFrom(sender, receiver, amount), \"Transfer failed\");\n }\n\n event StorageRequested(RequestId requestId, Ask ask, uint256 expiry);\n event RequestFulfilled(RequestId indexed requestId);\n event RequestFailed(RequestId indexed requestId);\n event SlotFilled(RequestId indexed requestId, uint256 slotIndex);\n event SlotFreed(RequestId indexed requestId, uint256 slotIndex);\n event RequestCancelled(RequestId indexed requestId);\n\n struct MarketplaceTotals {\n uint256 received;\n uint256 sent;\n }\n}\n" + }, + "contracts/Periods.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\ncontract Periods {\n type Period is uint256;\n\n uint256 internal immutable _secondsPerPeriod;\n\n constructor(uint256 secondsPerPeriod) {\n _secondsPerPeriod = secondsPerPeriod;\n }\n\n function _periodOf(uint256 timestamp) internal view returns (Period) {\n return Period.wrap(timestamp / _secondsPerPeriod);\n }\n\n function _blockPeriod() internal view returns (Period) {\n return _periodOf(block.timestamp);\n }\n\n function _nextPeriod(Period period) internal pure returns (Period) {\n return Period.wrap(Period.unwrap(period) + 1);\n }\n\n function _periodStart(Period period) internal view returns (uint256) {\n return Period.unwrap(period) * _secondsPerPeriod;\n }\n\n function _periodEnd(Period period) internal view returns (uint256) {\n return _periodStart(_nextPeriod(period));\n }\n\n function _isBefore(Period a, Period b) internal pure returns (bool) {\n return Period.unwrap(a) < Period.unwrap(b);\n }\n\n function _isAfter(Period a, Period b) internal pure returns (bool) {\n return _isBefore(b, a);\n }\n}\n" + }, + "contracts/Proofs.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nimport \"./Configuration.sol\";\nimport \"./Requests.sol\";\nimport \"./Periods.sol\";\nimport \"./Groth16.sol\";\n\n/**\n * @title Proofs\n * @notice Abstract contract that handles proofs tracking, validation and reporting functionality\n */\nabstract contract Proofs is Periods {\n ProofConfig private _config;\n IGroth16Verifier private _verifier;\n\n /**\n * Creation of the contract requires at least 256 mined blocks!\n * @param config Proving configuration\n */\n constructor(\n ProofConfig memory config,\n IGroth16Verifier verifier\n ) Periods(config.period) {\n require(block.number > 256, \"Insufficient block height\");\n _config = config;\n _verifier = verifier;\n }\n\n mapping(SlotId => uint256) private _slotStarts; // TODO: Should be smaller than uint256\n mapping(SlotId => uint256) private _probabilities;\n mapping(SlotId => uint256) private _missed; // TODO: Should be smaller than uint256\n mapping(SlotId => mapping(Period => bool)) private _received;\n mapping(SlotId => mapping(Period => bool)) private _missing;\n\n function slotState(SlotId id) public view virtual returns (SlotState);\n\n /**\n * @return Number of missed proofs since Slot was Filled\n */\n function missingProofs(SlotId slotId) public view returns (uint256) {\n return _missed[slotId];\n }\n\n /**\n * @param slotId Slot's ID for which the proofs should be reset\n * @notice Resets the missing proofs counter to zero\n */\n function _resetMissingProofs(SlotId slotId) internal {\n _missed[slotId] = 0;\n }\n\n /**\n * @param id Slot's ID for which the proofs should be started to require\n * @param probability Integer which specifies the probability of how often the proofs will be required. Lower number means higher probability.\n * @notice Notes down the block's timestamp as Slot's starting time for requiring proofs\n * and saves the required probability.\n */\n function _startRequiringProofs(SlotId id, uint256 probability) internal {\n _slotStarts[id] = block.timestamp;\n _probabilities[id] = probability;\n }\n\n /**\n * @param id Slot's ID for which the pointer should be calculated\n * @param period Period for which the pointer should be calculated\n * @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\n * @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\n */\n function _getPointer(SlotId id, Period period) internal view returns (uint8) {\n uint256 blockNumber = block.number % 256;\n uint256 periodNumber = (Period.unwrap(period) * _config.downtimeProduct) %\n 256;\n uint256 idOffset = uint256(SlotId.unwrap(id)) % 256;\n uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;\n return uint8(pointer);\n }\n\n /**\n * @param id Slot's ID for which the pointer should be calculated\n * @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\n * @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)\n */\n function getPointer(SlotId id) public view returns (uint8) {\n return _getPointer(id, _blockPeriod());\n }\n\n /**\n * @param pointer Integer [0-255] that indicates an offset of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.\n * @return Challenge that should be used for generation of proofs\n */\n function _getChallenge(uint8 pointer) internal view returns (bytes32) {\n bytes32 hash = blockhash(block.number - 1 - pointer);\n assert(uint256(hash) != 0);\n return keccak256(abi.encode(hash));\n }\n\n /**\n * @param id Slot's ID for which the challenge should be calculated\n * @param period Period for which the challenge should be calculated\n * @return Challenge that should be used for generation of proofs\n */\n function _getChallenge(\n SlotId id,\n Period period\n ) internal view returns (bytes32) {\n return _getChallenge(_getPointer(id, period));\n }\n\n /**\n * @param id Slot's ID for which the challenge should be calculated\n * @return Challenge for current Period that should be used for generation of proofs\n */\n function getChallenge(SlotId id) public view returns (bytes32) {\n return _getChallenge(id, _blockPeriod());\n }\n\n /**\n * @param id Slot's ID for which the requirements are gathered. If the Slot's state is other than Filled, `false` is always returned.\n * @param period Period for which the requirements are gathered.\n */\n function _getProofRequirement(\n SlotId id,\n Period period\n ) internal view returns (bool isRequired, uint8 pointer) {\n SlotState state = slotState(id);\n Period start = _periodOf(_slotStarts[id]);\n if (state != SlotState.Filled || !_isAfter(period, start)) {\n return (false, 0);\n }\n pointer = _getPointer(id, period);\n bytes32 challenge = _getChallenge(pointer);\n\n /// Scaling of the probability according the downtime configuration\n /// See: https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime\n uint256 probability = (_probabilities[id] * (256 - _config.downtime)) / 256;\n isRequired = probability == 0 || uint256(challenge) % probability == 0;\n }\n\n /**\n * See isProofRequired\n */\n function _isProofRequired(\n SlotId id,\n Period period\n ) internal view returns (bool) {\n bool isRequired;\n uint8 pointer;\n (isRequired, pointer) = _getProofRequirement(id, period);\n return isRequired && pointer >= _config.downtime;\n }\n\n /**\n * @param id Slot's ID for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\n * @return bool indicating if proof is required for current period\n */\n function isProofRequired(SlotId id) public view returns (bool) {\n return _isProofRequired(id, _blockPeriod());\n }\n\n /**\n * Proof Downtime specifies part of the Period when the proof is not required even\n * if the proof should be required. This function returns true if the pointer is\n * in downtime (hence no proof required now) and at the same time the proof\n * will be required later on in the Period.\n *\n * @dev for more info about downtime see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime)\n * @param id SlotId for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.\n * @return bool\n */\n function willProofBeRequired(SlotId id) public view returns (bool) {\n bool isRequired;\n uint8 pointer;\n (isRequired, pointer) = _getProofRequirement(id, _blockPeriod());\n return isRequired && pointer < _config.downtime;\n }\n\n /**\n * Function used for submitting and verification of the proofs.\n *\n * @dev Reverts when proof is invalid or had been already submitted.\n * @dev Emits ProofSubmitted event.\n * @param id Slot's ID for which the proof requirements should be checked\n * @param proof Groth16 proof\n * @param pubSignals Proofs public input\n */\n function _proofReceived(\n SlotId id,\n Groth16Proof calldata proof,\n uint[] memory pubSignals\n ) internal {\n require(!_received[id][_blockPeriod()], \"Proof already submitted\");\n require(_verifier.verify(proof, pubSignals), \"Invalid proof\");\n _received[id][_blockPeriod()] = true;\n emit ProofSubmitted(id);\n }\n\n /**\n * Function used to mark proof as missing.\n *\n * @param id Slot's ID for which the proof is missing\n * @param missedPeriod Period for which the proof was missed\n * @dev Reverts when:\n * - missedPeriod has not ended yet ended\n * - missing proof was time-barred\n * - proof was submitted\n * - proof was not required for missedPeriod period\n * - proof was already marked as missing\n */\n function _markProofAsMissing(SlotId id, Period missedPeriod) internal {\n uint256 end = _periodEnd(missedPeriod);\n require(end < block.timestamp, \"Period has not ended yet\");\n require(block.timestamp < end + _config.timeout, \"Validation timed out\");\n require(!_received[id][missedPeriod], \"Proof was submitted, not missing\");\n require(_isProofRequired(id, missedPeriod), \"Proof was not required\");\n require(!_missing[id][missedPeriod], \"Proof already marked as missing\");\n _missing[id][missedPeriod] = true;\n _missed[id] += 1;\n }\n\n event ProofSubmitted(SlotId id);\n}\n" + }, + "contracts/Requests.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\ntype RequestId is bytes32;\ntype SlotId is bytes32;\n\nstruct Request {\n address client;\n Ask ask;\n Content content;\n uint256 expiry; // amount of seconds since start of the request at which this request expires\n bytes32 nonce; // random nonce to differentiate between similar requests\n}\n\nstruct Ask {\n uint64 slots; // the number of requested slots\n uint256 slotSize; // amount of storage per slot (in number of bytes)\n uint256 duration; // how long content should be stored (in seconds)\n uint256 proofProbability; // how often storage proofs are required\n uint256 reward; // amount of tokens paid per second per slot to hosts\n uint256 collateral; // amount of tokens required to be deposited by the hosts in order to fill the slot\n uint64 maxSlotLoss; // Max slots that can be lost without data considered to be lost\n}\n\nstruct Content {\n string cid; // content id, used to download the dataset\n bytes32 merkleRoot; // merkle root of the dataset, used to verify storage proofs\n}\n\nenum RequestState {\n New, // [default] waiting to fill slots\n Started, // all slots filled, accepting regular proofs\n Cancelled, // not enough slots filled before expiry\n Finished, // successfully completed\n Failed // too many nodes have failed to provide proofs, data lost\n}\n\nenum SlotState {\n Free, // [default] not filled yet, or host has vacated the slot\n Filled, // host has filled slot\n Finished, // successfully completed\n Failed, // the request has failed\n Paid, // host has been paid\n Cancelled // when request was cancelled then slot is cancelled as well\n}\n\nlibrary Requests {\n function id(Request memory request) internal pure returns (RequestId) {\n return RequestId.wrap(keccak256(abi.encode(request)));\n }\n\n function slotId(\n RequestId requestId,\n uint256 slotIndex\n ) internal pure returns (SlotId) {\n return SlotId.wrap(keccak256(abi.encode(requestId, slotIndex)));\n }\n\n function toRequestIds(\n bytes32[] memory ids\n ) internal pure returns (RequestId[] memory result) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := ids\n }\n }\n\n function toSlotIds(\n bytes32[] memory ids\n ) internal pure returns (SlotId[] memory result) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n result := ids\n }\n }\n\n function maxPrice(Request memory request) internal pure returns (uint256) {\n return request.ask.slots * request.ask.duration * request.ask.reward;\n }\n}\n" + }, + "contracts/SlotReservations.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"./Requests.sol\";\nimport \"./Configuration.sol\";\n\ncontract SlotReservations {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n mapping(SlotId => EnumerableSet.AddressSet) internal _reservations;\n SlotReservationsConfig private _config;\n\n constructor(SlotReservationsConfig memory config) {\n _config = config;\n }\n\n function reserveSlot(RequestId requestId, uint256 slotIndex) public {\n require(canReserveSlot(requestId, slotIndex), \"Reservation not allowed\");\n\n SlotId slotId = Requests.slotId(requestId, slotIndex);\n _reservations[slotId].add(msg.sender);\n\n if (_reservations[slotId].length() == _config.maxReservations) {\n emit SlotReservationsFull(requestId, slotIndex);\n }\n }\n\n function canReserveSlot(\n RequestId requestId,\n uint256 slotIndex\n ) public view returns (bool) {\n address host = msg.sender;\n SlotId slotId = Requests.slotId(requestId, slotIndex);\n return\n // TODO: add in check for address inside of expanding window\n (_reservations[slotId].length() < _config.maxReservations) &&\n (!_reservations[slotId].contains(host));\n }\n\n event SlotReservationsFull(RequestId indexed requestId, uint256 slotIndex);\n}\n" + }, + "contracts/StateRetrieval.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nimport \"@openzeppelin/contracts/utils/structs/EnumerableSet.sol\";\nimport \"./Requests.sol\";\n\ncontract StateRetrieval {\n using EnumerableSet for EnumerableSet.Bytes32Set;\n using Requests for bytes32[];\n\n mapping(address => EnumerableSet.Bytes32Set) private _requestsPerClient;\n mapping(address => EnumerableSet.Bytes32Set) private _slotsPerHost;\n\n function myRequests() public view returns (RequestId[] memory) {\n return _requestsPerClient[msg.sender].values().toRequestIds();\n }\n\n function mySlots() public view returns (SlotId[] memory) {\n return _slotsPerHost[msg.sender].values().toSlotIds();\n }\n\n function _hasSlots(address host) internal view returns (bool) {\n return _slotsPerHost[host].length() > 0;\n }\n\n function _addToMyRequests(address client, RequestId requestId) internal {\n _requestsPerClient[client].add(RequestId.unwrap(requestId));\n }\n\n function _addToMySlots(address host, SlotId slotId) internal {\n _slotsPerHost[host].add(SlotId.unwrap(slotId));\n }\n\n function _removeFromMyRequests(address client, RequestId requestId) internal {\n _requestsPerClient[client].remove(RequestId.unwrap(requestId));\n }\n\n function _removeFromMySlots(address host, SlotId slotId) internal {\n _slotsPerHost[host].remove(SlotId.unwrap(slotId));\n }\n}\n" + }, + "contracts/TestEndian.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"./Endian.sol\";\n\ncontract TestEndian is Endian {\n function byteSwap(bytes32 input) public pure returns (bytes32) {\n return _byteSwap(input);\n }\n}\n" + }, + "contracts/TestMarketplace.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"./Marketplace.sol\";\n\n// exposes internal functions of Marketplace for testing\ncontract TestMarketplace is Marketplace {\n constructor(\n MarketplaceConfig memory config,\n IERC20 token,\n IGroth16Verifier verifier\n )\n Marketplace(config, token, verifier) // solhint-disable-next-line no-empty-blocks\n {}\n\n function forciblyFreeSlot(SlotId slotId) public {\n _forciblyFreeSlot(slotId);\n }\n\n function getSlotCollateral(SlotId slotId) public view returns (uint256) {\n return _slots[slotId].currentCollateral;\n }\n\n function challengeToFieldElement(\n bytes32 challenge\n ) public pure returns (uint256) {\n return _challengeToFieldElement(challenge);\n }\n\n function merkleRootToFieldElement(\n bytes32 merkleRoot\n ) public pure returns (uint256) {\n return _merkleRootToFieldElement(merkleRoot);\n }\n}\n" + }, + "contracts/TestProofs.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"./Proofs.sol\";\n\n// exposes internal functions of Proofs for testing\ncontract TestProofs is Proofs {\n mapping(SlotId => SlotState) private _states;\n\n constructor(\n ProofConfig memory config,\n IGroth16Verifier verifier\n ) Proofs(config, verifier) {} // solhint-disable-line no-empty-blocks\n\n function slotState(SlotId slotId) public view override returns (SlotState) {\n return _states[slotId];\n }\n\n function startRequiringProofs(SlotId slot, uint256 probability) public {\n _startRequiringProofs(slot, probability);\n }\n\n function markProofAsMissing(SlotId id, Period period) public {\n _markProofAsMissing(id, period);\n }\n\n function proofReceived(\n SlotId id,\n Groth16Proof calldata proof,\n uint[] memory pubSignals\n ) public {\n _proofReceived(id, proof, pubSignals);\n }\n\n function setSlotState(SlotId id, SlotState state) public {\n _states[id] = state;\n }\n}\n" + }, + "contracts/TestSlotReservations.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"./SlotReservations.sol\";\n\ncontract TestSlotReservations is SlotReservations {\n using EnumerableSet for EnumerableSet.AddressSet;\n\n // solhint-disable-next-line no-empty-blocks\n constructor(SlotReservationsConfig memory config) SlotReservations(config) {}\n\n function contains(SlotId slotId, address host) public view returns (bool) {\n return _reservations[slotId].contains(host);\n }\n\n function length(SlotId slotId) public view returns (uint256) {\n return _reservations[slotId].length();\n }\n}\n" + }, + "contracts/TestToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.23;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestToken is ERC20 {\n // solhint-disable-next-line no-empty-blocks\n constructor() ERC20(\"TestToken\", \"TST\") {}\n\n function mint(address holder, uint256 amount) public {\n _mint(holder, amount);\n }\n}\n" + }, + "contracts/TestVerifier.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.23;\n\nimport \"./Groth16.sol\";\n\ncontract TestVerifier is IGroth16Verifier {\n function verify(\n Groth16Proof calldata proof,\n uint[] calldata\n ) external pure returns (bool) {\n // accepts any proof, except the proof with all zero values\n return\n !(proof.a.x == 0 &&\n proof.a.y == 0 &&\n proof.b.x.real == 0 &&\n proof.b.x.imag == 0 &&\n proof.b.y.real == 0 &&\n proof.b.y.imag == 0 &&\n proof.c.x == 0 &&\n proof.c.y == 0);\n }\n}\n" + } + }, + "settings": { + "evmVersion": "paris", + "optimizer": { + "enabled": true, + "runs": 1000 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file