From 849b639f9731512c03271c8af7a4edac7bbbf11a Mon Sep 17 00:00:00 2001 From: Seth Hrbek Date: Tue, 21 Nov 2023 09:16:41 -0500 Subject: [PATCH] add arbitrum deployment --- .env.example | 11 +- contracts/storage/LibAppStorage.sol | 1 - deploy/001_sarcophagus_facets.ts | 34 +- deployments/arbitrum/.chainId | 1 + deployments/arbitrum/AdminFacet.json | 363 +++++++++ .../AppStorageInit.json | 26 +- deployments/arbitrum/ArchaeologistFacet.json | 635 +++++++++++++++ deployments/arbitrum/EmbalmerFacet.json | 722 ++++++++++++++++++ .../Sarcophagus_V2.json | 112 ++- .../Sarcophagus_V2_DiamondProxy.json | 96 ++- deployments/arbitrum/ThirdPartyFacet.json | 473 ++++++++++++ .../ViewStateFacet.json | 26 +- .../_DefaultDiamondCutFacet.json | 16 - .../_DefaultDiamondERC165Init.json | 16 - .../_DefaultDiamondLoupeFacet.json | 16 - .../_DefaultDiamondOwnershipFacet.json | 16 - .../3fe12e823553336a8d0f950a5a792ac9.json | 0 .../69b6ccc89b7eaa4e346529a9a529edba.json | 95 +++ deployments/baseGoerli/.chainId | 1 - deployments/baseGoerli/AdminFacet.json | 326 -------- .../baseGoerli/ArchaeologistFacet.json | 635 --------------- deployments/baseGoerli/EmbalmerFacet.json | 722 ------------------ deployments/baseGoerli/ThirdPartyFacet.json | 473 ------------ .../b7fcd450a9977c08df561a1e7df764e7.json | 110 --- hardhat.config.ts | 40 +- 25 files changed, 2483 insertions(+), 2483 deletions(-) create mode 100644 deployments/arbitrum/.chainId create mode 100644 deployments/arbitrum/AdminFacet.json rename deployments/{baseGoerli => arbitrum}/AppStorageInit.json (79%) create mode 100644 deployments/arbitrum/ArchaeologistFacet.json create mode 100644 deployments/arbitrum/EmbalmerFacet.json rename deployments/{baseGoerli => arbitrum}/Sarcophagus_V2.json (96%) rename deployments/{baseGoerli => arbitrum}/Sarcophagus_V2_DiamondProxy.json (96%) create mode 100644 deployments/arbitrum/ThirdPartyFacet.json rename deployments/{baseGoerli => arbitrum}/ViewStateFacet.json (53%) rename deployments/{baseGoerli => arbitrum}/_DefaultDiamondCutFacet.json (97%) rename deployments/{baseGoerli => arbitrum}/_DefaultDiamondERC165Init.json (95%) rename deployments/{baseGoerli => arbitrum}/_DefaultDiamondLoupeFacet.json (96%) rename deployments/{baseGoerli => arbitrum}/_DefaultDiamondOwnershipFacet.json (94%) rename deployments/{baseGoerli => arbitrum}/solcInputs/3fe12e823553336a8d0f950a5a792ac9.json (100%) create mode 100644 deployments/arbitrum/solcInputs/69b6ccc89b7eaa4e346529a9a529edba.json delete mode 100644 deployments/baseGoerli/.chainId delete mode 100644 deployments/baseGoerli/AdminFacet.json delete mode 100644 deployments/baseGoerli/ArchaeologistFacet.json delete mode 100644 deployments/baseGoerli/EmbalmerFacet.json delete mode 100644 deployments/baseGoerli/ThirdPartyFacet.json delete mode 100644 deployments/baseGoerli/solcInputs/b7fcd450a9977c08df561a1e7df764e7.json diff --git a/.env.example b/.env.example index 26896e2..27ba550 100644 --- a/.env.example +++ b/.env.example @@ -4,17 +4,11 @@ MAINNET_DEPLOYER_PRIVATE_KEY= POLYGON_PROVIDER= POLYGON_DEPLOYER_PRIVATE_KEY= -BASE_PROVIDER= -BASE_DEPLOYER_PRIVATE_KEY= - -BASE_GOERLI_PROVIDER= -BASE_GOERLI_DEPLOYER_PRIVATE_KEY= - POLYGON_MUMBAI_PROVIDER= POLYGON_MUMBAI_DEPLOYER_PRIVATE_KEY= -GOERLI_PROVIDER= -GOERLI_DEPLOYER_PRIVATE_KEY= +ARBITRUM_PROVIDER= +ARBITRUM_DEPLOYER_PRIVATE_KEY= SEPOLIA_PROVIDER= SEPOLIA_DEPLOYER_PRIVATE_KEY= @@ -22,5 +16,6 @@ SEPOLIA_DEPLOYER_PRIVATE_KEY= ETHERSCAN_API_KEY= POLYGONSCAN_API_KEY= BASESCAN_API_KEY= +ARBISCAN_API_KEY= REPORT_GAS=true diff --git a/contracts/storage/LibAppStorage.sol b/contracts/storage/LibAppStorage.sol index 1f1132a..fb86849 100644 --- a/contracts/storage/LibAppStorage.sol +++ b/contracts/storage/LibAppStorage.sol @@ -7,7 +7,6 @@ import "../libraries/LibTypes.sol"; /** * Global diamond storage struct to be shared across facets - * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs */ struct AppStorage { // SARCO token contract diff --git a/deploy/001_sarcophagus_facets.ts b/deploy/001_sarcophagus_facets.ts index 0886d83..775c87d 100644 --- a/deploy/001_sarcophagus_facets.ts +++ b/deploy/001_sarcophagus_facets.ts @@ -23,8 +23,6 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { log: true, }); sarcoTokenAddress = sarcoTokenMock.address; - } else if (["goerli", "goerli-fork"].includes(hre.hardhatArguments.network)) { - sarcoTokenAddress = "0x4633b43990b41B57b3678c6F3Ac35bA75C3D8436"; } else if (["sepolia"].includes(hre.hardhatArguments.network)) { sarcoTokenAddress = "0xfa1FA4d51FB2babf59e402c83327Ab5087441289"; } else if ( @@ -35,8 +33,8 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { sarcoTokenAddress = "0x2BC9019e6d9e6a26D7D8d8CDDa4e5dE9B787D7bb"; } else if (["polygon"].includes(hre.hardhatArguments.network)) { sarcoTokenAddress = "0x80Ae3B3847E4e8Bd27A389f7686486CAC9C3f3e8"; - } else if (["baseGoerli"].includes(hre.hardhatArguments.network)) { - sarcoTokenAddress = "0x2BC9019e6d9e6a26D7D8d8CDDa4e5dE9B787D7bb"; + } else if (["arbitrum"].includes(hre.hardhatArguments.network)) { + sarcoTokenAddress = "0x82155Ab6b6c1113CFb352c7573B010a88f5974bD"; } else { throw Error( `Sarcophagus is not set up for this network: ${hre.hardhatArguments.network}` @@ -68,20 +66,20 @@ const func: DeployFunction = async function (hre: HardhatRuntimeEnvironment) { "ViewStateFacet", "AdminFacet", ], - // Uncomment if fresh deploy and not upgrading - // execute: { - // contract: "AppStorageInit", - // methodName: "init", - // args: [ - // sarcoTokenAddress, - // daoAgentAddress, - // protocolFeeBasePercentage, - // cursedBondPercentage, - // gracePeriod, - // embalmerClaimWindow, - // expirationThreshold, - // ], - // }, + // Comment out if upgrading + execute: { + contract: "AppStorageInit", + methodName: "init", + args: [ + sarcoTokenAddress, + daoAgentAddress, + protocolFeeBasePercentage, + cursedBondPercentage, + gracePeriod, + embalmerClaimWindow, + expirationThreshold, + ], + }, log: true, }); }; diff --git a/deployments/arbitrum/.chainId b/deployments/arbitrum/.chainId new file mode 100644 index 0000000..7df83ec --- /dev/null +++ b/deployments/arbitrum/.chainId @@ -0,0 +1 @@ +42161 \ No newline at end of file diff --git a/deployments/arbitrum/AdminFacet.json b/deployments/arbitrum/AdminFacet.json new file mode 100644 index 0000000..5e2b3ce --- /dev/null +++ b/deployments/arbitrum/AdminFacet.json @@ -0,0 +1,363 @@ +{ + "address": "0x941B0319c0B1090810fbA842b372E9F0795B2A96", + "abi": [ + { + "inputs": [], + "name": "CallerIsNotAdminOrOwner", + "type": "error" + }, + { + "inputs": [], + "name": "CannotSetZeroValue", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "cursedBondPercentage", + "type": "uint256" + } + ], + "name": "SetCursedBondPercentage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "embalmerClaimWindow", + "type": "uint256" + } + ], + "name": "SetEmbalmerClaimWindow", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "expirationThreshold", + "type": "uint256" + } + ], + "name": "SetExpirationThreshold", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "gracePeriod", + "type": "uint256" + } + ], + "name": "SetGracePeriod", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "protocolFeeBasePercentage", + "type": "uint256" + } + ], + "name": "SetProtocolFeeBasePercentage", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "totalProtocolFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "withdrawalAddress", + "type": "address" + } + ], + "name": "WithdrawProtocolFees", + "type": "event" + }, + { + "inputs": [], + "name": "getDiamondOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "cursedBondPercentage", + "type": "uint256" + } + ], + "name": "setCursedBondPercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "embalmerClaimWindow", + "type": "uint256" + } + ], + "name": "setEmbalmerClaimWindow", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "expirationThreshold", + "type": "uint256" + } + ], + "name": "setExpirationThreshold", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "gracePeriod", + "type": "uint256" + } + ], + "name": "setGracePeriod", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "protocolFeeBasePercentage", + "type": "uint256" + } + ], + "name": "setProtocolFeeBasePercentage", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "transferAdmin", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferDiamondOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "withdrawalAddress", + "type": "address" + } + ], + "name": "withdrawProtocolFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x858cfdedbad263ab76e3d8f7444469b9a635bd52031ecf635d45c7dc37813b7f", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", + "contractAddress": null, + "transactionIndex": 11, + "gasUsed": "10581649", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0xaf3c1313630144d9aca287fa512e267f53eebfda87a5329309173326195c9127", + "transactionHash": "0x858cfdedbad263ab76e3d8f7444469b9a635bd52031ecf635d45c7dc37813b7f", + "logs": [], + "blockNumber": 152626982, + "cumulativeGasUsed": "27122989", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "69b6ccc89b7eaa4e346529a9a529edba", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CallerIsNotAdminOrOwner\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSetZeroValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"}],\"name\":\"SetCursedBondPercentage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindow\",\"type\":\"uint256\"}],\"name\":\"SetEmbalmerClaimWindow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expirationThreshold\",\"type\":\"uint256\"}],\"name\":\"SetExpirationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gracePeriod\",\"type\":\"uint256\"}],\"name\":\"SetGracePeriod\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"protocolFeeBasePercentage\",\"type\":\"uint256\"}],\"name\":\"SetProtocolFeeBasePercentage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalProtocolFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawalAddress\",\"type\":\"address\"}],\"name\":\"WithdrawProtocolFees\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"getDiamondOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"}],\"name\":\"setCursedBondPercentage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindow\",\"type\":\"uint256\"}],\"name\":\"setEmbalmerClaimWindow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expirationThreshold\",\"type\":\"uint256\"}],\"name\":\"setExpirationThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gracePeriod\",\"type\":\"uint256\"}],\"name\":\"setGracePeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"protocolFeeBasePercentage\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeBasePercentage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"transferAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferDiamondOwner\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"withdrawalAddress\",\"type\":\"address\"}],\"name\":\"withdrawProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"setCursedBondPercentage(uint256)\":{\"params\":{\"cursedBondPercentage\":\"ratio to set.\"}},\"setEmbalmerClaimWindow(uint256)\":{\"params\":{\"embalmerClaimWindow\":\"to set\"}},\"setExpirationThreshold(uint256)\":{\"params\":{\"expirationThreshold\":\"to set\"}},\"setGracePeriod(uint256)\":{\"params\":{\"gracePeriod\":\"to set\"}},\"setProtocolFeeBasePercentage(uint256)\":{\"params\":{\"protocolFeeBasePercentage\":\"percentage to set\"}},\"transferAdmin(address)\":{\"params\":{\"newAdmin\":\"to set\"}},\"transferDiamondOwner(address)\":{\"params\":{\"newOwner\":\"to set\"}},\"withdrawProtocolFees(address)\":{\"params\":{\"withdrawalAddress\":\"- the address to withdraw funds to\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"CallerIsNotAdminOrOwner()\":[{\"notice\":\"Caller must be the admin address\"}],\"CannotSetZeroValue()\":[{\"notice\":\"Admin has attempted to set a zero value\"}],\"ZeroAddress()\":[{\"notice\":\"Provided address cannot be zero address\"}]},\"kind\":\"user\",\"methods\":{\"getDiamondOwner()\":{\"notice\":\"Returns current owner of Diamond contract.\"},\"setCursedBondPercentage(uint256)\":{\"notice\":\"Sets the digging fee / cursed bond ratioThe denominator is 10000 used to calculate how much bond archaeologists must lock per curse.\"},\"setEmbalmerClaimWindow(uint256)\":{\"notice\":\"Updates the embalmerClaimWindowDenominated in seconds\"},\"setExpirationThreshold(uint256)\":{\"notice\":\"Updates the expirationThreshold used during sarcophagus creationDenominated in seconds\"},\"setGracePeriod(uint256)\":{\"notice\":\"Updates the resurrection grace periodDenominated in seconds\"},\"setProtocolFeeBasePercentage(uint256)\":{\"notice\":\"Sets the protocol fee base percentage, used to calculate protocol feesThe denominator is 10000\"},\"transferAdmin(address)\":{\"notice\":\"Transfers admin address to newAdmin.\"},\"transferDiamondOwner(address)\":{\"notice\":\"Transfers diamond owner to new owner.\"},\"withdrawProtocolFees(address)\":{\"notice\":\"Withdraws the total protocol fee amount from the contract to the specified address\"}},\"notice\":\"Caller of any function in this facet must be the admin address\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/AdminFacet.sol\":\"AdminFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"contracts/facets/AdminFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\n\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\n\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\n\\n/// @notice Caller of any function in this facet must be the admin address\\ncontract AdminFacet {\\n event SetProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage);\\n event SetCursedBondPercentage(uint256 cursedBondPercentage);\\n event WithdrawProtocolFees(uint256 totalProtocolFees, address withdrawalAddress);\\n event SetGracePeriod(uint256 gracePeriod);\\n event SetEmbalmerClaimWindow(uint256 embalmerClaimWindow);\\n event SetExpirationThreshold(uint256 expirationThreshold);\\n event AdminTransferred(address indexed previousAdmin, address indexed newAdmin);\\n\\n /// @notice Admin has attempted to set a zero value\\n error CannotSetZeroValue();\\n\\n /// @notice Caller must be the admin address\\n error CallerIsNotAdminOrOwner();\\n\\n /// @notice Provided address cannot be zero address\\n error ZeroAddress();\\n\\n /// @notice Modifier to enforce caller is admin or contract owner\\n modifier onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n if (msg.sender != s.admin && msg.sender != LibDiamond.contractOwner()) {\\n revert CallerIsNotAdminOrOwner();\\n }\\n _;\\n }\\n\\n /// @notice Withdraws the total protocol fee amount from the contract to the specified address\\n /// @param withdrawalAddress - the address to withdraw funds to\\n function withdrawProtocolFees(address withdrawalAddress) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n // Get the total protocol fees from storage\\n uint256 totalProtocolFees = s.totalProtocolFees;\\n // Set the total protocol fees to 0 before the transfer to avoid reentrancy\\n s.totalProtocolFees = 0;\\n // Transfer the protocol fee amount to the sender after setting state\\n s.sarcoToken.transfer(withdrawalAddress, totalProtocolFees);\\n emit WithdrawProtocolFees(totalProtocolFees, withdrawalAddress);\\n }\\n\\n /// @notice Sets the protocol fee base percentage, used to calculate protocol fees\\n /// @notice The denominator is 10000\\n /// @param protocolFeeBasePercentage percentage to set\\n function setProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\\n emit SetProtocolFeeBasePercentage(protocolFeeBasePercentage);\\n }\\n\\n /// @notice Sets the digging fee / cursed bond ratio\\n /// @notice The denominator is 10000\\n /// used to calculate how much bond archaeologists must lock per curse.\\n /// @param cursedBondPercentage ratio to set.\\n function setCursedBondPercentage(uint256 cursedBondPercentage) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n if (cursedBondPercentage == 0) {\\n revert CannotSetZeroValue();\\n }\\n s.cursedBondPercentage = cursedBondPercentage;\\n emit SetCursedBondPercentage(cursedBondPercentage);\\n }\\n\\n /// @notice Updates the resurrection grace period\\n /// @notice Denominated in seconds\\n /// @param gracePeriod to set\\n function setGracePeriod(uint256 gracePeriod) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n s.gracePeriod = gracePeriod;\\n emit SetGracePeriod(gracePeriod);\\n }\\n\\n /// @notice Updates the embalmerClaimWindow\\n /// @notice Denominated in seconds\\n /// @param embalmerClaimWindow to set\\n function setEmbalmerClaimWindow(uint256 embalmerClaimWindow) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n s.embalmerClaimWindow = embalmerClaimWindow;\\n emit SetEmbalmerClaimWindow(embalmerClaimWindow);\\n }\\n\\n /// @notice Updates the expirationThreshold used during sarcophagus creation\\n /// @notice Denominated in seconds\\n /// @param expirationThreshold to set\\n function setExpirationThreshold(uint256 expirationThreshold) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n s.expirationThreshold = expirationThreshold;\\n emit SetExpirationThreshold(expirationThreshold);\\n }\\n\\n /// @notice Transfers admin address to newAdmin.\\n /// @param newAdmin to set\\n function transferAdmin(address newAdmin) external onlyAdmin {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n if (newAdmin == address(0)) {\\n revert ZeroAddress();\\n }\\n s.admin = newAdmin;\\n emit AdminTransferred(msg.sender, newAdmin);\\n }\\n\\n /// @notice Transfers diamond owner to new owner.\\n /// @param newOwner to set\\n function transferDiamondOwner(address newOwner) external {\\n LibDiamond.enforceIsContractOwner();\\n LibDiamond.setContractOwner(newOwner);\\n }\\n\\n /// @notice Returns current owner of Diamond contract.\\n function getDiamondOwner() external view returns (address) {\\n return LibDiamond.contractOwner();\\n }\\n}\\n\",\"keccak256\":\"0x7f15bab495edc2a4d33248a1c001fe22881e3a2d6925fd4a040a8918676996cc\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Types shared across facets for the Sarcophagus diamond\\n */\\nlibrary LibTypes {\\n struct Sarcophagus {\\n // Also used for existence checks -- does not exist if 0\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\n bool isCompromised;\\n bool isCleaned;\\n bool isRewrapped;\\n uint8 threshold;\\n string name;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] cursedArchaeologistAddresses;\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\n uint256 cursedBondPercentage;\\n }\\n\\n struct CursedArchaeologist {\\n uint256 diggingFeePerSecond;\\n // Also used for publish checks -- has not published if 0\\n bytes32 privateKey;\\n // Also used for curse checks -- is not bonded if length is 0\\n bytes publicKey;\\n bool isAccused;\\n uint256 curseFee;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n struct ArchaeologistProfile {\\n // Also used for existence checks -- does not exist if 0\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string peerId;\\n uint256 minimumDiggingFeePerSecond;\\n uint256 freeBond;\\n uint256 cursedBond;\\n uint256 curseFee;\\n }\\n}\\n\",\"keccak256\":\"0x1b2f2f8c309ec6d6f4895143d290b5d99daacfee6bfd2443dfe74dc0f29e8678\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\n/**\\n * Global diamond storage struct to be shared across facets\\n */\\nstruct AppStorage {\\n // SARCO token contract\\n IERC20 sarcoToken;\\n // The Admin address allowed to call Admin Facet functions\\n address admin;\\n // total protocol fees available to be withdrawn by the admin\\n uint256 totalProtocolFees;\\n /**\\n * Protocol level admin configurations\\n */\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\n uint256 protocolFeeBasePercentage;\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\n uint256 cursedBondPercentage;\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\n uint256 gracePeriod;\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\n uint256 expirationThreshold;\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\n uint256 embalmerClaimWindow;\\n // registered archaeologist addresses\\n address[] archaeologistProfileAddresses;\\n // public key => archaeologist address\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\n // sarcophagus id => sarcophagus object\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\n // archaeologist address => profile\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\n // current balance of rewards available for the archaeologist to withdraw\\n mapping(address => uint256) archaeologistRewards;\\n}\\n\\nlibrary LibAppStorage {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\n\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n s.slot := position\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07df02177bdd1ecc43723d2c46b8d81ecc84b49c40b7c85478ef4c4650b02335\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b5061104d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063682e4e5f11610066578063682e4e5f1461010857806375829def146101265780638a5b569014610142578063a828c4791461015e578063f2f659601461017a57610093565b8063274f255e146100985780632d80caa5146100b45780633a805a3c146100d05780636430ae6a146100ec575b600080fd5b6100b260048036038101906100ad9190610db1565b610196565b005b6100ce60048036038101906100c99190610e3c565b6102bd565b005b6100ea60048036038101906100e59190610e3c565b610494565b005b61010660048036038101906101019190610db1565b6104a8565b005b610110610609565b60405161011d9190610e78565b60405180910390f35b610140600480360381019061013b9190610e3c565b610618565b005b61015c60048036038101906101579190610db1565b610802565b005b61017860048036038101906101739190610db1565b610929565b005b610194600480360381019061018f9190610db1565b610a50565b005b60006101a0610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156102355750610205610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b1561026c576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610276610b77565b90508281600701819055507f3d58bff47ca074037a5dcd57740255670d45843115cca9c9bc442eb6d3f0ad78836040516102b09190610ea2565b60405180910390a1505050565b60006102c7610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561035c575061032c610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610393576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061039d610b77565b9050600081600201549050600082600201819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836040518363ffffffff1660e01b8152600401610411929190610ebd565b6020604051808303816000875af1158015610430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104549190610f1e565b507f7baf2b6a1777e2a34a2dcddad43c098eb5ab5b5c7a1f3c8ec4872863265244f48185604051610486929190610f4b565b60405180910390a150505050565b61049c610bd7565b6104a581610c72565b50565b60006104b2610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156105475750610517610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b1561057e576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610588610b77565b9050600083036105c4576040517f4a8fadb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8281600401819055507f4aeca9f26d25b33ee1b2c061ab4a849de97bfb592e7dfb276c9ded12d0ad56a2836040516105fc9190610ea2565b60405180910390a1505050565b6000610613610ba4565b905090565b6000610622610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156106b75750610687610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156106ee576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106f8610b77565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610760576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec660405160405180910390a3505050565b600061080c610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108a15750610871610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108d8576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108e2610b77565b90508281600301819055507f4768bb3a79cb8de7ec3c4c950f9f76fbe4588407c214998efbf648001c858e9b8360405161091c9190610ea2565b60405180910390a1505050565b6000610933610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156109c85750610998610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156109ff576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a09610b77565b90508281600601819055507f047ca17cdae34ccbd8db62138d05e11962458ffd86009620909ba6ad606282ad83604051610a439190610ea2565b60405180910390a1505050565b6000610a5a610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aef5750610abf610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610b26576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b30610b77565b90508281600501819055507f848ba7852320e491d84ddc22f1f12fe48672aa22757fc4452703c9046d9982d783604051610b6a9190610ea2565b60405180910390a1505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000610bae610d49565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610bdf610d49565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6790610ff7565b60405180910390fd5b565b6000610c7c610d49565b905060008160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b600080fd5b6000819050919050565b610d8e81610d7b565b8114610d9957600080fd5b50565b600081359050610dab81610d85565b92915050565b600060208284031215610dc757610dc6610d76565b5b6000610dd584828501610d9c565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e0982610dde565b9050919050565b610e1981610dfe565b8114610e2457600080fd5b50565b600081359050610e3681610e10565b92915050565b600060208284031215610e5257610e51610d76565b5b6000610e6084828501610e27565b91505092915050565b610e7281610dfe565b82525050565b6000602082019050610e8d6000830184610e69565b92915050565b610e9c81610d7b565b82525050565b6000602082019050610eb76000830184610e93565b92915050565b6000604082019050610ed26000830185610e69565b610edf6020830184610e93565b9392505050565b60008115159050919050565b610efb81610ee6565b8114610f0657600080fd5b50565b600081519050610f1881610ef2565b92915050565b600060208284031215610f3457610f33610d76565b5b6000610f4284828501610f09565b91505092915050565b6000604082019050610f606000830185610e93565b610f6d6020830184610e69565b9392505050565b600082825260208201905092915050565b7f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000610fe1602283610f74565b9150610fec82610f85565b604082019050919050565b6000602082019050818103600083015261101081610fd4565b905091905056fea2646970667358221220c1ee567769cc75d5c64970b29b4fd9c8e28d7768ced7de766c8f75c9ac317ec864736f6c63430008120033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063682e4e5f11610066578063682e4e5f1461010857806375829def146101265780638a5b569014610142578063a828c4791461015e578063f2f659601461017a57610093565b8063274f255e146100985780632d80caa5146100b45780633a805a3c146100d05780636430ae6a146100ec575b600080fd5b6100b260048036038101906100ad9190610db1565b610196565b005b6100ce60048036038101906100c99190610e3c565b6102bd565b005b6100ea60048036038101906100e59190610e3c565b610494565b005b61010660048036038101906101019190610db1565b6104a8565b005b610110610609565b60405161011d9190610e78565b60405180910390f35b610140600480360381019061013b9190610e3c565b610618565b005b61015c60048036038101906101579190610db1565b610802565b005b61017860048036038101906101739190610db1565b610929565b005b610194600480360381019061018f9190610db1565b610a50565b005b60006101a0610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156102355750610205610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b1561026c576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610276610b77565b90508281600701819055507f3d58bff47ca074037a5dcd57740255670d45843115cca9c9bc442eb6d3f0ad78836040516102b09190610ea2565b60405180910390a1505050565b60006102c7610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561035c575061032c610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610393576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061039d610b77565b9050600081600201549050600082600201819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836040518363ffffffff1660e01b8152600401610411929190610ebd565b6020604051808303816000875af1158015610430573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906104549190610f1e565b507f7baf2b6a1777e2a34a2dcddad43c098eb5ab5b5c7a1f3c8ec4872863265244f48185604051610486929190610f4b565b60405180910390a150505050565b61049c610bd7565b6104a581610c72565b50565b60006104b2610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156105475750610517610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b1561057e576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610588610b77565b9050600083036105c4576040517f4a8fadb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8281600401819055507f4aeca9f26d25b33ee1b2c061ab4a849de97bfb592e7dfb276c9ded12d0ad56a2836040516105fc9190610ea2565b60405180910390a1505050565b6000610613610ba4565b905090565b6000610622610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156106b75750610687610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156106ee576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006106f8610b77565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610760576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec660405160405180910390a3505050565b600061080c610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156108a15750610871610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156108d8576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108e2610b77565b90508281600301819055507f4768bb3a79cb8de7ec3c4c950f9f76fbe4588407c214998efbf648001c858e9b8360405161091c9190610ea2565b60405180910390a1505050565b6000610933610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16141580156109c85750610998610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156109ff576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610a09610b77565b90508281600601819055507f047ca17cdae34ccbd8db62138d05e11962458ffd86009620909ba6ad606282ad83604051610a439190610ea2565b60405180910390a1505050565b6000610a5a610b77565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614158015610aef5750610abf610ba4565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b15610b26576040517fe94bce8700000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000610b30610b77565b90508281600501819055507f848ba7852320e491d84ddc22f1f12fe48672aa22757fc4452703c9046d9982d783604051610b6a9190610ea2565b60405180910390a1505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000610bae610d49565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b610bdf610d49565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610c70576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c6790610ff7565b60405180910390fd5b565b6000610c7c610d49565b905060008160040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050828260040160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a3505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b600080fd5b6000819050919050565b610d8e81610d7b565b8114610d9957600080fd5b50565b600081359050610dab81610d85565b92915050565b600060208284031215610dc757610dc6610d76565b5b6000610dd584828501610d9c565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000610e0982610dde565b9050919050565b610e1981610dfe565b8114610e2457600080fd5b50565b600081359050610e3681610e10565b92915050565b600060208284031215610e5257610e51610d76565b5b6000610e6084828501610e27565b91505092915050565b610e7281610dfe565b82525050565b6000602082019050610e8d6000830184610e69565b92915050565b610e9c81610d7b565b82525050565b6000602082019050610eb76000830184610e93565b92915050565b6000604082019050610ed26000830185610e69565b610edf6020830184610e93565b9392505050565b60008115159050919050565b610efb81610ee6565b8114610f0657600080fd5b50565b600081519050610f1881610ef2565b92915050565b600060208284031215610f3457610f33610d76565b5b6000610f4284828501610f09565b91505092915050565b6000604082019050610f606000830185610e93565b610f6d6020830184610e69565b9392505050565b600082825260208201905092915050565b7f4c69624469616d6f6e643a204d75737420626520636f6e7472616374206f776e60008201527f6572000000000000000000000000000000000000000000000000000000000000602082015250565b6000610fe1602283610f74565b9150610fec82610f85565b604082019050919050565b6000602082019050818103600083015261101081610fd4565b905091905056fea2646970667358221220c1ee567769cc75d5c64970b29b4fd9c8e28d7768ced7de766c8f75c9ac317ec864736f6c63430008120033", + "devdoc": { + "kind": "dev", + "methods": { + "setCursedBondPercentage(uint256)": { + "params": { + "cursedBondPercentage": "ratio to set." + } + }, + "setEmbalmerClaimWindow(uint256)": { + "params": { + "embalmerClaimWindow": "to set" + } + }, + "setExpirationThreshold(uint256)": { + "params": { + "expirationThreshold": "to set" + } + }, + "setGracePeriod(uint256)": { + "params": { + "gracePeriod": "to set" + } + }, + "setProtocolFeeBasePercentage(uint256)": { + "params": { + "protocolFeeBasePercentage": "percentage to set" + } + }, + "transferAdmin(address)": { + "params": { + "newAdmin": "to set" + } + }, + "transferDiamondOwner(address)": { + "params": { + "newOwner": "to set" + } + }, + "withdrawProtocolFees(address)": { + "params": { + "withdrawalAddress": "- the address to withdraw funds to" + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "CallerIsNotAdminOrOwner()": [ + { + "notice": "Caller must be the admin address" + } + ], + "CannotSetZeroValue()": [ + { + "notice": "Admin has attempted to set a zero value" + } + ], + "ZeroAddress()": [ + { + "notice": "Provided address cannot be zero address" + } + ] + }, + "kind": "user", + "methods": { + "getDiamondOwner()": { + "notice": "Returns current owner of Diamond contract." + }, + "setCursedBondPercentage(uint256)": { + "notice": "Sets the digging fee / cursed bond ratioThe denominator is 10000 used to calculate how much bond archaeologists must lock per curse." + }, + "setEmbalmerClaimWindow(uint256)": { + "notice": "Updates the embalmerClaimWindowDenominated in seconds" + }, + "setExpirationThreshold(uint256)": { + "notice": "Updates the expirationThreshold used during sarcophagus creationDenominated in seconds" + }, + "setGracePeriod(uint256)": { + "notice": "Updates the resurrection grace periodDenominated in seconds" + }, + "setProtocolFeeBasePercentage(uint256)": { + "notice": "Sets the protocol fee base percentage, used to calculate protocol feesThe denominator is 10000" + }, + "transferAdmin(address)": { + "notice": "Transfers admin address to newAdmin." + }, + "transferDiamondOwner(address)": { + "notice": "Transfers diamond owner to new owner." + }, + "withdrawProtocolFees(address)": { + "notice": "Withdraws the total protocol fee amount from the contract to the specified address" + } + }, + "notice": "Caller of any function in this facet must be the admin address", + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/baseGoerli/AppStorageInit.json b/deployments/arbitrum/AppStorageInit.json similarity index 79% rename from deployments/baseGoerli/AppStorageInit.json rename to deployments/arbitrum/AppStorageInit.json index 851b530..dee75b8 100644 --- a/deployments/baseGoerli/AppStorageInit.json +++ b/deployments/arbitrum/AppStorageInit.json @@ -1,5 +1,5 @@ { - "address": "0xe14E811e93B36a5Cb0D74102919D19748cfB14CA", + "address": "0x8B54aF0d46B57D219e5f41F78ad7569E28eaE793", "abi": [ { "inputs": [ @@ -45,28 +45,28 @@ "type": "function" } ], - "transactionHash": "0x20500ec8555c675881a84e8f3765b8688b90726c53e5de8a723d55d6852a2a07", + "transactionHash": "0x731d548606ab31f1d17b7539720a4420e6ceefa746a7bee8f10f2bd2d546ec77", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "216374", + "transactionIndex": 3, + "gasUsed": "3777002", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x6d8348c827de88c49e5decd4bf7c7e85a76651aaa83d3d05f8311d5c22a0e2c5", - "transactionHash": "0x20500ec8555c675881a84e8f3765b8688b90726c53e5de8a723d55d6852a2a07", + "blockHash": "0xbb188db4c66521dabac24edb4566c25b560d2fe4ccac315bcc59324a482464a8", + "transactionHash": "0x731d548606ab31f1d17b7539720a4420e6ceefa746a7bee8f10f2bd2d546ec77", "logs": [], - "blockNumber": 9669989, - "cumulativeGasUsed": "263215", + "blockNumber": 152626987, + "cumulativeGasUsed": "5576050", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "b7fcd450a9977c08df561a1e7df764e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"sarcoToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"protocolFeeBasePercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gracePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindow\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expirationThreshold\",\"type\":\"uint256\"}],\"name\":\"init\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"init(address,address,uint256,uint256,uint256,uint256,uint256)\":{\"details\":\"Add any AppStorage struct properties here to initialize values\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"init(address,address,uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Initializes the app with default state values\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/storage/AppStorageInit.sol\":\"AppStorageInit\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Types shared across facets for the Sarcophagus diamond\\r\\n */\\r\\nlibrary LibTypes {\\r\\n struct Sarcophagus {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n bool isRewrapped;\\r\\n uint8 threshold;\\r\\n string name;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] cursedArchaeologistAddresses;\\r\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\r\\n uint256 cursedBondPercentage;\\r\\n }\\r\\n\\r\\n struct CursedArchaeologist {\\r\\n uint256 diggingFeePerSecond;\\r\\n // Also used for publish checks -- has not published if 0\\r\\n bytes32 privateKey;\\r\\n // Also used for curse checks -- is not bonded if length is 0\\r\\n bytes publicKey;\\r\\n bool isAccused;\\r\\n uint256 curseFee;\\r\\n }\\r\\n\\r\\n struct Signature {\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n struct ArchaeologistProfile {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string peerId;\\r\\n uint256 minimumDiggingFeePerSecond;\\r\\n uint256 freeBond;\\r\\n uint256 cursedBond;\\r\\n uint256 curseFee;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x096d9660852c5179b16d71abe3a818282db9e980fdc431efa77bd92577d60fb8\",\"license\":\"Unlicense\"},\"contracts/storage/AppStorageInit.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"./LibAppStorage.sol\\\";\\r\\n\\r\\ncontract AppStorageInit {\\r\\n /// @notice Initializes the app with default state values\\r\\n /// @dev Add any AppStorage struct properties here to initialize values\\r\\n function init(\\r\\n IERC20 sarcoToken,\\r\\n address admin,\\r\\n uint256 protocolFeeBasePercentage,\\r\\n uint256 cursedBondPercentage,\\r\\n uint256 gracePeriod,\\r\\n uint256 embalmerClaimWindow,\\r\\n uint256 expirationThreshold\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n s.sarcoToken = sarcoToken;\\r\\n s.admin = admin;\\r\\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\\r\\n s.cursedBondPercentage = cursedBondPercentage;\\r\\n s.gracePeriod = gracePeriod;\\r\\n s.embalmerClaimWindow = embalmerClaimWindow;\\r\\n s.expirationThreshold = expirationThreshold;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x3b30c5e9b2476d117ec0d897ffe3e77c6ac621a59a996a59038567319fb606a1\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\n/**\\r\\n * Global diamond storage struct to be shared across facets\\r\\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\\r\\n */\\r\\nstruct AppStorage {\\r\\n // SARCO token contract\\r\\n IERC20 sarcoToken;\\r\\n // The Admin address allowed to call Admin Facet functions\\r\\n address admin;\\r\\n // total protocol fees available to be withdrawn by the admin\\r\\n uint256 totalProtocolFees;\\r\\n /**\\r\\n * Protocol level admin configurations\\r\\n */\\r\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\r\\n uint256 protocolFeeBasePercentage;\\r\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\r\\n uint256 cursedBondPercentage;\\r\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\r\\n uint256 gracePeriod;\\r\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\r\\n uint256 expirationThreshold;\\r\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\r\\n uint256 embalmerClaimWindow;\\r\\n // registered archaeologist addresses\\r\\n address[] archaeologistProfileAddresses;\\r\\n // public key => archaeologist address\\r\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\r\\n // sarcophagus id => sarcophagus object\\r\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\r\\n // archaeologist address => profile\\r\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\r\\n // current balance of rewards available for the archaeologist to withdraw\\r\\n mapping(address => uint256) archaeologistRewards;\\r\\n}\\r\\n\\r\\nlibrary LibAppStorage {\\r\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\r\\n\\r\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n assembly {\\r\\n s.slot := position\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x66f7100a037fcc417379e68914a8831d867f3701c39419f8f04a3af27008438c\",\"license\":\"Unlicense\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506102f1806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b36a27e714610030575b600080fd5b61004a60048036038101906100459190610219565b61004c565b005b6000610056610115565b9050878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550868160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508581600301819055508481600401819055508381600501819055508281600701819055508181600601819055505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017282610147565b9050919050565b600061018482610167565b9050919050565b61019481610179565b811461019f57600080fd5b50565b6000813590506101b18161018b565b92915050565b6101c081610167565b81146101cb57600080fd5b50565b6000813590506101dd816101b7565b92915050565b6000819050919050565b6101f6816101e3565b811461020157600080fd5b50565b600081359050610213816101ed565b92915050565b600080600080600080600060e0888a03121561023857610237610142565b5b60006102468a828b016101a2565b97505060206102578a828b016101ce565b96505060406102688a828b01610204565b95505060606102798a828b01610204565b945050608061028a8a828b01610204565b93505060a061029b8a828b01610204565b92505060c06102ac8a828b01610204565b9150509295989194975092955056fea2646970667358221220201abb50b120112566583840382d91f6bb36e24502ac1283ac499271b1da590a64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b36a27e714610030575b600080fd5b61004a60048036038101906100459190610219565b61004c565b005b6000610056610115565b9050878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550868160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508581600301819055508481600401819055508381600501819055508281600701819055508181600601819055505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017282610147565b9050919050565b600061018482610167565b9050919050565b61019481610179565b811461019f57600080fd5b50565b6000813590506101b18161018b565b92915050565b6101c081610167565b81146101cb57600080fd5b50565b6000813590506101dd816101b7565b92915050565b6000819050919050565b6101f6816101e3565b811461020157600080fd5b50565b600081359050610213816101ed565b92915050565b600080600080600080600060e0888a03121561023857610237610142565b5b60006102468a828b016101a2565b97505060206102578a828b016101ce565b96505060406102688a828b01610204565b95505060606102798a828b01610204565b945050608061028a8a828b01610204565b93505060a061029b8a828b01610204565b92505060c06102ac8a828b01610204565b9150509295989194975092955056fea2646970667358221220201abb50b120112566583840382d91f6bb36e24502ac1283ac499271b1da590a64736f6c63430008120033", + "solcInputHash": "69b6ccc89b7eaa4e346529a9a529edba", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"contract IERC20\",\"name\":\"sarcoToken\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"protocolFeeBasePercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"gracePeriod\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindow\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"expirationThreshold\",\"type\":\"uint256\"}],\"name\":\"init\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"init(address,address,uint256,uint256,uint256,uint256,uint256)\":{\"details\":\"Add any AppStorage struct properties here to initialize values\"}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"init(address,address,uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Initializes the app with default state values\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/storage/AppStorageInit.sol\":\"AppStorageInit\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Types shared across facets for the Sarcophagus diamond\\n */\\nlibrary LibTypes {\\n struct Sarcophagus {\\n // Also used for existence checks -- does not exist if 0\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\n bool isCompromised;\\n bool isCleaned;\\n bool isRewrapped;\\n uint8 threshold;\\n string name;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] cursedArchaeologistAddresses;\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\n uint256 cursedBondPercentage;\\n }\\n\\n struct CursedArchaeologist {\\n uint256 diggingFeePerSecond;\\n // Also used for publish checks -- has not published if 0\\n bytes32 privateKey;\\n // Also used for curse checks -- is not bonded if length is 0\\n bytes publicKey;\\n bool isAccused;\\n uint256 curseFee;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n struct ArchaeologistProfile {\\n // Also used for existence checks -- does not exist if 0\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string peerId;\\n uint256 minimumDiggingFeePerSecond;\\n uint256 freeBond;\\n uint256 cursedBond;\\n uint256 curseFee;\\n }\\n}\\n\",\"keccak256\":\"0x1b2f2f8c309ec6d6f4895143d290b5d99daacfee6bfd2443dfe74dc0f29e8678\",\"license\":\"Unlicense\"},\"contracts/storage/AppStorageInit.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"./LibAppStorage.sol\\\";\\n\\ncontract AppStorageInit {\\n /// @notice Initializes the app with default state values\\n /// @dev Add any AppStorage struct properties here to initialize values\\n function init(\\n IERC20 sarcoToken,\\n address admin,\\n uint256 protocolFeeBasePercentage,\\n uint256 cursedBondPercentage,\\n uint256 gracePeriod,\\n uint256 embalmerClaimWindow,\\n uint256 expirationThreshold\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n s.sarcoToken = sarcoToken;\\n s.admin = admin;\\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\\n s.cursedBondPercentage = cursedBondPercentage;\\n s.gracePeriod = gracePeriod;\\n s.embalmerClaimWindow = embalmerClaimWindow;\\n s.expirationThreshold = expirationThreshold;\\n }\\n}\\n\",\"keccak256\":\"0x300c83fefc07bc312a6a1efd658f3cd1a6ff5fbf78dd648fdbae0c188d875fe9\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\n/**\\n * Global diamond storage struct to be shared across facets\\n */\\nstruct AppStorage {\\n // SARCO token contract\\n IERC20 sarcoToken;\\n // The Admin address allowed to call Admin Facet functions\\n address admin;\\n // total protocol fees available to be withdrawn by the admin\\n uint256 totalProtocolFees;\\n /**\\n * Protocol level admin configurations\\n */\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\n uint256 protocolFeeBasePercentage;\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\n uint256 cursedBondPercentage;\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\n uint256 gracePeriod;\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\n uint256 expirationThreshold;\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\n uint256 embalmerClaimWindow;\\n // registered archaeologist addresses\\n address[] archaeologistProfileAddresses;\\n // public key => archaeologist address\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\n // sarcophagus id => sarcophagus object\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\n // archaeologist address => profile\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\n // current balance of rewards available for the archaeologist to withdraw\\n mapping(address => uint256) archaeologistRewards;\\n}\\n\\nlibrary LibAppStorage {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\n\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n s.slot := position\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07df02177bdd1ecc43723d2c46b8d81ecc84b49c40b7c85478ef4c4650b02335\",\"license\":\"Unlicense\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b506102f1806100206000396000f3fe608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b36a27e714610030575b600080fd5b61004a60048036038101906100459190610219565b61004c565b005b6000610056610115565b9050878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550868160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508581600301819055508481600401819055508381600501819055508281600701819055508181600601819055505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017282610147565b9050919050565b600061018482610167565b9050919050565b61019481610179565b811461019f57600080fd5b50565b6000813590506101b18161018b565b92915050565b6101c081610167565b81146101cb57600080fd5b50565b6000813590506101dd816101b7565b92915050565b6000819050919050565b6101f6816101e3565b811461020157600080fd5b50565b600081359050610213816101ed565b92915050565b600080600080600080600060e0888a03121561023857610237610142565b5b60006102468a828b016101a2565b97505060206102578a828b016101ce565b96505060406102688a828b01610204565b95505060606102798a828b01610204565b945050608061028a8a828b01610204565b93505060a061029b8a828b01610204565b92505060c06102ac8a828b01610204565b9150509295989194975092955056fea264697066735822122088ad1a18d9d41511e5506430e27182e6a016cdc2b1bb07f093288681990f3dd064736f6c63430008120033", + "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061002b5760003560e01c8063b36a27e714610030575b600080fd5b61004a60048036038101906100459190610219565b61004c565b005b6000610056610115565b9050878160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550868160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508581600301819055508481600401819055508381600501819055508281600701819055508181600601819055505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061017282610147565b9050919050565b600061018482610167565b9050919050565b61019481610179565b811461019f57600080fd5b50565b6000813590506101b18161018b565b92915050565b6101c081610167565b81146101cb57600080fd5b50565b6000813590506101dd816101b7565b92915050565b6000819050919050565b6101f6816101e3565b811461020157600080fd5b50565b600081359050610213816101ed565b92915050565b600080600080600080600060e0888a03121561023857610237610142565b5b60006102468a828b016101a2565b97505060206102578a828b016101ce565b96505060406102688a828b01610204565b95505060606102798a828b01610204565b945050608061028a8a828b01610204565b93505060a061029b8a828b01610204565b92505060c06102ac8a828b01610204565b9150509295989194975092955056fea264697066735822122088ad1a18d9d41511e5506430e27182e6a016cdc2b1bb07f093288681990f3dd064736f6c63430008120033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/arbitrum/ArchaeologistFacet.json b/deployments/arbitrum/ArchaeologistFacet.json new file mode 100644 index 0000000..a3d25f8 --- /dev/null +++ b/deployments/arbitrum/ArchaeologistFacet.json @@ -0,0 +1,635 @@ +{ + "address": "0xf375135d20D8098287a3D6961BDDF78062486551", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "archaeologistAddress", + "type": "address" + } + ], + "name": "ArchaeologistAlreadyPublishedPrivateKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "archaeologistAddress", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "ArchaeologistHasBeenAccused", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "archaeologist", + "type": "address" + } + ], + "name": "ArchaeologistNotOnSarcophagus", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "address", + "name": "archaeologist", + "type": "address" + } + ], + "name": "ArchaeologistProfileExistsShouldBe", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "archaeologistAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "bytes32", + "name": "privateKey", + "type": "bytes32" + } + ], + "name": "ArchaeologistPublishedIncorrectPrivateKey", + "type": "error" + }, + { + "inputs": [], + "name": "CannotSetZeroProfileValue", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusCompromised", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + } + ], + "name": "TooEarlyForPublish", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "publishDeadline", + "type": "uint256" + } + ], + "name": "TooLateForPublish", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "archaeologist", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "depositedBond", + "type": "uint256" + } + ], + "name": "DepositFreeBond", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "privateKey", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "archaeologist", + "type": "address" + } + ], + "name": "PublishPrivateKey", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "archaeologist", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "peerId", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minimumDiggingFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maximumRewrapInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "freeBond", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maximumResurrectionTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curseFee", + "type": "uint256" + } + ], + "name": "RegisterArchaeologist", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "archaeologist", + "type": "address" + }, + { + "indexed": false, + "internalType": "string", + "name": "peerId", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "minimumDiggingFee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maximumRewrapInterval", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "freeBond", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "maximumResurrectionTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "curseFee", + "type": "uint256" + } + ], + "name": "UpdateArchaeologist", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "archaeologist", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnBond", + "type": "uint256" + } + ], + "name": "WithdrawFreeBond", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "archaeologist", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "withdrawnReward", + "type": "uint256" + } + ], + "name": "WithdrawReward", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "depositFreeBond", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "privateKey", + "type": "bytes32" + } + ], + "name": "publishPrivateKey", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "peerId", + "type": "string" + }, + { + "internalType": "uint256", + "name": "minimumDiggingFeePerSecond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumRewrapInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "freeBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumResurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "curseFee", + "type": "uint256" + } + ], + "name": "registerArchaeologist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "string", + "name": "peerId", + "type": "string" + }, + { + "internalType": "uint256", + "name": "minimumDiggingFeePerSecond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumRewrapInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "freeBond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumResurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "curseFee", + "type": "uint256" + } + ], + "name": "updateArchaeologist", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "withdrawFreeBond", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "withdrawReward", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x5b43fe2f967b64d212d8bad5a01d19779bedeaff80ef21dd56885607e41e1fce", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", + "contractAddress": null, + "transactionIndex": 3, + "gasUsed": "22299288", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x7003ebb6ad913ad48e7d3f2e1a7e3f47b4bad632189c4c1fb016224c7506825a", + "transactionHash": "0x5b43fe2f967b64d212d8bad5a01d19779bedeaff80ef21dd56885607e41e1fce", + "logs": [], + "blockNumber": 152626937, + "cumulativeGasUsed": "23827390", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "69b6ccc89b7eaa4e346529a9a529edba", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"}],\"name\":\"ArchaeologistAlreadyPublishedPrivateKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"ArchaeologistHasBeenAccused\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistNotOnSarcophagus\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistProfileExistsShouldBe\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"}],\"name\":\"ArchaeologistPublishedIncorrectPrivateKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSetZeroProfileValue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusCompromised\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"TooEarlyForPublish\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"publishDeadline\",\"type\":\"uint256\"}],\"name\":\"TooLateForPublish\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"depositedBond\",\"type\":\"uint256\"}],\"name\":\"DepositFreeBond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"PublishPrivateKey\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minimumDiggingFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"RegisterArchaeologist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minimumDiggingFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"UpdateArchaeologist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawnBond\",\"type\":\"uint256\"}],\"name\":\"WithdrawFreeBond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawnReward\",\"type\":\"uint256\"}],\"name\":\"WithdrawReward\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositFreeBond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"}],\"name\":\"publishPrivateKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"registerArchaeologist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"updateArchaeologist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFreeBond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawReward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ArchaeologistAlreadyPublishedPrivateKey(address)\":[{\"params\":{\"archaeologistAddress\":\"address of publishing archaeologist\"}}],\"ArchaeologistHasBeenAccused(address,bytes32)\":[{\"params\":{\"archaeologistAddress\":\"Address of accused archaeologist who is attempting to publish their private key\",\"sarcoId\":\"ID of sarcophagus archaeologist has attempted to publish a key on\"}}],\"ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)\":[{\"params\":{\"archaeologistAddress\":\"address of publishing archaeologist\",\"privateKey\":\"privateKey the archaeologist has attempted to publish\",\"publicKey\":\"publicKey stored for archaeologist on the sarcophagus\"}}],\"TooEarlyForPublish(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed publish attempt\",\"resurrectionTime\":\"Time after which the sarcophagus can be resurrected\"}}],\"TooLateForPublish(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed publish attempt\",\"publishDeadline\":\"Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)\"}}]},\"events\":{\"PublishPrivateKey(bytes32,bytes32,address)\":{\"params\":{\"privateKey\":\"private key that has been published\",\"sarcoId\":\"ID of sarcophagus archaeologist has published the private key on\"}}},\"kind\":\"dev\",\"methods\":{\"depositFreeBond(uint256)\":{\"params\":{\"amount\":\"The amount to deposit\"}},\"publishPrivateKey(bytes32,bytes32)\":{\"params\":{\"privateKey\":\"The private key the archaeologist is publishing\",\"sarcoId\":\"The identifier of the sarcophagus for which the archaeologist is responsible\"}},\"registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"curseFee\":\"The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\",\"freeBond\":\"How much bond the archaeologist wants to deposit during the register call (if any)\",\"maximumResurrectionTime\":\"The time beyond which the archaeologist is not willing to accept new curses or rewraps\",\"maximumRewrapInterval\":\"The longest interval of time from a rewrap time the arch will accept for a resurrection\",\"minimumDiggingFeePerSecond\":\"The archaeologist's minimum amount to earn per second for being cursed\",\"peerId\":\"The libp2p identifier for the archaeologist\"}},\"updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"curseFee\":\"The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\",\"freeBond\":\"How much bond the archaeologist wants to deposit during the update call (if any)\",\"maximumRewrapInterval\":\"The longest interval of time from a rewrap time the arch will accept for a resurrection\",\"minimumDiggingFeePerSecond\":\"The archaeologist's minimum amount to earn per second for being cursed\",\"peerId\":\"The libp2p identifier for the archaeologist\"}},\"withdrawFreeBond(uint256)\":{\"params\":{\"amount\":\"The amount to withdraw\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ArchaeologistAlreadyPublishedPrivateKey(address)\":[{\"notice\":\"Archaeologist has attempted to publish a key for a sarcophagus twice\"}],\"ArchaeologistHasBeenAccused(address,bytes32)\":[{\"notice\":\"An archaeologist that has already been successfully accused has attempted to publish their private key\"}],\"ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)\":[{\"notice\":\"Archaeologist has attempted to publish the incorrect private key for a sarcophagus\"}],\"CannotSetZeroProfileValue()\":[{\"notice\":\"Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval\"}],\"TooEarlyForPublish(uint256,uint256)\":[{\"notice\":\"Archaeologist has attempted to publish a key before the resurrection time\"}],\"TooLateForPublish(uint256,uint256)\":[{\"notice\":\"Archaeologist has attempted to publish a key after the end of the resurrection window\"}]},\"events\":{\"PublishPrivateKey(bytes32,bytes32,address)\":{\"notice\":\"Emitted when an archaeologist successfully publishes their private key for a sarcophagus\"}},\"kind\":\"user\",\"methods\":{\"depositFreeBond(uint256)\":{\"notice\":\"Deposits an archaeologist's free bond to the contract.\"},\"publishPrivateKey(bytes32,bytes32)\":{\"notice\":\"Publishes the private key for which the archaeologist is responsible during the sarcophagus resurrection window. Pays digging fees to the archaeologist and releases their locked bond. Cannot be called on a compromised or buried sarcophagus.\"},\"registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Registers the archaeologist profile\"},\"updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Updates the archaeologist profile\"},\"withdrawFreeBond(uint256)\":{\"notice\":\"Withdraws an archaeologist's free bond from the contract.\"},\"withdrawReward()\":{\"notice\":\"Withdraws all rewards from an archaeologist's reward pool\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ArchaeologistFacet.sol\":\"ArchaeologistFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/ArchaeologistFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\nimport {LibPrivateKeys} from \\\"../libraries/LibPrivateKeys.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\n\\ncontract ArchaeologistFacet {\\n /// @notice Emitted when an archaeologist successfully publishes their private key for a sarcophagus\\n /// @param sarcoId ID of sarcophagus archaeologist has published the private key on\\n /// @param privateKey private key that has been published\\n event PublishPrivateKey(\\n bytes32 indexed sarcoId,\\n bytes32 privateKey,\\n address indexed archaeologist\\n );\\n\\n event DepositFreeBond(address indexed archaeologist, uint256 depositedBond);\\n\\n event RegisterArchaeologist(\\n address indexed archaeologist,\\n string peerId,\\n uint256 minimumDiggingFee,\\n uint256 maximumRewrapInterval,\\n uint256 freeBond,\\n uint256 maximumResurrectionTime,\\n uint256 curseFee\\n );\\n\\n event UpdateArchaeologist(\\n address indexed archaeologist,\\n string peerId,\\n uint256 minimumDiggingFee,\\n uint256 maximumRewrapInterval,\\n uint256 freeBond,\\n uint256 maximumResurrectionTime,\\n uint256 curseFee\\n );\\n\\n event WithdrawFreeBond(address indexed archaeologist, uint256 withdrawnBond);\\n\\n event WithdrawReward(address indexed archaeologist, uint256 withdrawnReward);\\n\\n /// @notice An archaeologist that has already been successfully accused has attempted to publish their private key\\n /// @param archaeologistAddress Address of accused archaeologist who is attempting to publish their private key\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a key on\\n error ArchaeologistHasBeenAccused(address archaeologistAddress, bytes32 sarcoId);\\n\\n /// @notice Archaeologist has attempted to publish a key before the resurrection time\\n /// @param currentTime Timestamp of the failed publish attempt\\n /// @param resurrectionTime Time after which the sarcophagus can be resurrected\\n error TooEarlyForPublish(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Archaeologist has attempted to publish a key after the end of the resurrection window\\n /// @param currentTime Timestamp of the failed publish attempt\\n /// @param publishDeadline Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)\\n error TooLateForPublish(uint256 currentTime, uint256 publishDeadline);\\n\\n /// @notice Archaeologist has attempted to publish a key for a sarcophagus twice\\n /// @param archaeologistAddress address of publishing archaeologist\\n error ArchaeologistAlreadyPublishedPrivateKey(address archaeologistAddress);\\n\\n /// @notice Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval\\n error CannotSetZeroProfileValue();\\n\\n /// @notice Archaeologist has attempted to publish the incorrect private key for a sarcophagus\\n /// @param archaeologistAddress address of publishing archaeologist\\n /// @param publicKey publicKey stored for archaeologist on the sarcophagus\\n /// @param privateKey privateKey the archaeologist has attempted to publish\\n error ArchaeologistPublishedIncorrectPrivateKey(\\n address archaeologistAddress,\\n bytes publicKey,\\n bytes32 privateKey\\n );\\n\\n /// @notice Registers the archaeologist profile\\n /// @param peerId The libp2p identifier for the archaeologist\\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\\n /// for a resurrection\\n /// @param freeBond How much bond the archaeologist wants to deposit during the register call (if any)\\n /// @param maximumResurrectionTime The time beyond which the archaeologist is not willing to accept new curses or rewraps\\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\\n function registerArchaeologist(\\n string memory peerId,\\n uint256 minimumDiggingFeePerSecond,\\n uint256 maximumRewrapInterval,\\n uint256 freeBond,\\n uint256 maximumResurrectionTime,\\n uint256 curseFee\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n // verify that the archaeologist does not already exist\\n LibUtils.revertIfArchProfileExists(msg.sender);\\n\\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\\n revert CannotSetZeroProfileValue();\\n }\\n\\n // create a new archaeologist\\n LibTypes.ArchaeologistProfile memory newArch = LibTypes.ArchaeologistProfile({\\n peerId: peerId,\\n minimumDiggingFeePerSecond: minimumDiggingFeePerSecond,\\n maximumResurrectionTime: maximumResurrectionTime,\\n maximumRewrapInterval: maximumRewrapInterval,\\n freeBond: freeBond,\\n cursedBond: 0,\\n curseFee: curseFee\\n });\\n\\n // transfer SARCO tokens from the archaeologist to this contract, to be\\n // used as their free bond. can be 0.\\n if (freeBond != 0) {\\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\\n }\\n\\n // save the new archaeologist into relevant data structures\\n s.archaeologistProfiles[msg.sender] = newArch;\\n s.archaeologistProfileAddresses.push(msg.sender);\\n\\n emit RegisterArchaeologist(\\n msg.sender,\\n newArch.peerId,\\n newArch.minimumDiggingFeePerSecond,\\n newArch.maximumRewrapInterval,\\n newArch.freeBond,\\n newArch.maximumResurrectionTime,\\n newArch.curseFee\\n );\\n }\\n\\n /// @notice Updates the archaeologist profile\\n /// @param peerId The libp2p identifier for the archaeologist\\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\\n /// @param freeBond How much bond the archaeologist wants to deposit during the update call (if any)\\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\\n /// for a resurrection\\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\\n function updateArchaeologist(\\n string memory peerId,\\n uint256 minimumDiggingFeePerSecond,\\n uint256 maximumRewrapInterval,\\n uint256 freeBond,\\n uint256 maximumResurrectionTime,\\n uint256 curseFee\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n // verify that the archaeologist exists\\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\\n\\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\\n revert CannotSetZeroProfileValue();\\n }\\n\\n LibTypes.ArchaeologistProfile storage existingArch = s.archaeologistProfiles[msg.sender];\\n existingArch.peerId = peerId;\\n existingArch.minimumDiggingFeePerSecond = minimumDiggingFeePerSecond;\\n existingArch.maximumRewrapInterval = maximumRewrapInterval;\\n existingArch.maximumResurrectionTime = maximumResurrectionTime;\\n existingArch.curseFee = curseFee;\\n\\n // transfer SARCO tokens from the archaeologist to this contract, to be\\n // used as their free bond. can be 0.\\n if (freeBond != 0) {\\n s.archaeologistProfiles[msg.sender].freeBond += freeBond;\\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\\n }\\n\\n emit UpdateArchaeologist(\\n msg.sender,\\n existingArch.peerId,\\n existingArch.minimumDiggingFeePerSecond,\\n existingArch.maximumRewrapInterval,\\n freeBond,\\n existingArch.maximumResurrectionTime,\\n existingArch.curseFee\\n );\\n }\\n\\n /// @notice Deposits an archaeologist's free bond to the contract.\\n /// @param amount The amount to deposit\\n function depositFreeBond(uint256 amount) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\\n\\n // Increase the archaeologist's free bond in app storage\\n s.archaeologistProfiles[msg.sender].freeBond += amount;\\n\\n // Transfer the amount of sarcoToken from the archaeologist to the contract\\n s.sarcoToken.transferFrom(msg.sender, address(this), amount);\\n // Emit an event\\n emit DepositFreeBond(msg.sender, amount);\\n }\\n\\n /// @notice Withdraws an archaeologist's free bond from the contract.\\n /// @param amount The amount to withdraw\\n function withdrawFreeBond(uint256 amount) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\\n // Decrease the archaeologist's free bond amount.\\n // Reverts if there is not enough free bond on the contract.\\n s.archaeologistProfiles[msg.sender].freeBond -= amount;\\n\\n // Transfer the amount of sarcoToken to the archaeologist\\n s.sarcoToken.transfer(msg.sender, amount);\\n\\n emit WithdrawFreeBond(msg.sender, amount);\\n }\\n\\n /// @notice Withdraws all rewards from an archaeologist's reward pool\\n function withdrawReward() external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n uint256 amountToWithdraw = s.archaeologistRewards[msg.sender];\\n s.archaeologistRewards[msg.sender] = 0;\\n\\n // Transfer the amount of sarcoToken to the archaeologist\\n s.sarcoToken.transfer(msg.sender, amountToWithdraw);\\n\\n emit WithdrawReward(msg.sender, amountToWithdraw);\\n }\\n\\n /// @notice Publishes the private key for which the archaeologist is responsible during the\\n /// sarcophagus resurrection window.\\n /// Pays digging fees to the archaeologist and releases their locked bond.\\n /// Cannot be called on a compromised or buried sarcophagus.\\n /// @param sarcoId The identifier of the sarcophagus for which the archaeologist is responsible\\n /// @param privateKey The private key the archaeologist is publishing\\n function publishPrivateKey(bytes32 sarcoId, bytes32 privateKey) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm current time is after resurrectionTime\\n if (block.timestamp < sarcophagus.resurrectionTime) {\\n revert TooEarlyForPublish(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm current time is within gracePeriod\\n if (block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod) {\\n revert TooLateForPublish(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\n }\\n\\n // Confirm tx sender is an archaeologist on the sarcophagus\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\n .sarcophagi[sarcoId]\\n .cursedArchaeologists[msg.sender];\\n if (cursedArchaeologist.publicKey.length == 0) {\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\n }\\n\\n // Confirm archaeologist has not already leaked their private key\\n if (cursedArchaeologist.isAccused) {\\n revert ArchaeologistHasBeenAccused(msg.sender, sarcoId);\\n }\\n\\n // Confirm archaeologist has not already published their private key\\n if (cursedArchaeologist.privateKey != 0) {\\n revert ArchaeologistAlreadyPublishedPrivateKey(msg.sender);\\n }\\n\\n // Confirm that the private key being submitted matches the public key stored on the\\n // sarcophagus for this archaeologist\\n if (!LibPrivateKeys.isPublicKeyOfPrivateKey(privateKey, cursedArchaeologist.publicKey)) {\\n revert ArchaeologistPublishedIncorrectPrivateKey(\\n msg.sender,\\n cursedArchaeologist.publicKey,\\n privateKey\\n );\\n }\\n\\n // Store the private key on cursed archaeologist\\n cursedArchaeologist.privateKey = privateKey;\\n\\n // Free archaeologist locked bond and transfer digging fees\\n LibBonds.freeArchaeologist(sarcoId, msg.sender);\\n\\n emit PublishPrivateKey(sarcoId, privateKey, msg.sender);\\n }\\n}\\n\",\"keccak256\":\"0x5c48c4e894171d7f817b88d9bcb319cefcbb8da86bf61d0f54c3f6b3fc0a79c7\",\"license\":\"Unlicense\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\n\\ncontract EmbalmerFacet {\\n /// @notice Emitted when a sarcophagus is created\\n /// @param sarcoId Id of the new sarcophagus\\n /// @param name Name of the new sarcophagus\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\n /// @param embalmer Address of embalmer\\n /// @param recipient Address of recipient\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\n event CreateSarcophagus(\\n bytes32 indexed sarcoId,\\n string name,\\n uint256 resurrectionTime,\\n uint256 creationTime,\\n address indexed embalmer,\\n address indexed recipient,\\n address[] cursedArchaeologists,\\n uint256 totalDiggingFees,\\n string arweaveTxId\\n );\\n\\n /// @notice Emitted when a sarcophagus is rewrapped\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\n event RewrapSarcophagus(\\n bytes32 indexed sarcoId,\\n uint256 resurrectionTime,\\n uint256 totalDiggingFees,\\n uint256 rewrapSarcophagusProtocolFees\\n );\\n\\n /// @notice Emitted when a sarcophagus is buried\\n /// @param sarcoId Id of sarcophagus that was buried\\n event BurySarcophagus(bytes32 indexed sarcoId);\\n\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\n struct SarcophagusParams {\\n string name;\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\n uint256 maximumRewrapInterval;\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\n uint256 maximumResurrectionTime;\\n address recipientAddress;\\n uint256 resurrectionTime;\\n uint8 threshold;\\n uint256 creationTime;\\n }\\n\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\n struct CurseParams {\\n bytes publicKey;\\n address archAddress;\\n uint256 diggingFeePerSecond;\\n uint256 curseFee;\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\n /// @param sarcoId Id that is already in use\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\n /// @param currentTime Timestamp of the failed create attempt\\n /// @param creationTime Time when the sarcophagus parameters were created\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\n error SarcophagusParametersExpired(\\n uint256 currentTime,\\n uint256 creationTime,\\n uint256 creationDeadline\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\n error NoArchaeologistsProvided();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\n error ThresholdCannotBeZero();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\n uint8 threshold,\\n uint256 totalNumberOfArchaeologists\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\n /// @param currentTime Timestamp of the failed rewrap attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\n /// @param publicKey the duplicated public key\\n error DuplicatePublicKey(bytes publicKey);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\n error ResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\n error ResurrectionTimePastMaxResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 maxResurrectionTime\\n );\\n\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\n\\n error NewResurrectionTimeIsZero();\\n\\n error NewResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 previousResurrectionTime\\n );\\n\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\n /// of the sarcophagus until its resurrection time.\\n ///\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\n /// - `creationTime` of sarcophagus\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\n ///\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param sarcophagusParams params to set on sarcophagus being created\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\n function createSarcophagus(\\n bytes32 sarcoId,\\n SarcophagusParams calldata sarcophagusParams,\\n CurseParams[] calldata selectedArchaeologists,\\n string calldata arweaveTxId\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n // Confirm that sarcophagus with supplied id doesn't already exist\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\n revert SarcophagusAlreadyExists(sarcoId);\\n }\\n\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\n // off by its cursed archaeologists.\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\n revert SarcophagusParametersExpired(\\n block.timestamp,\\n sarcophagusParams.creationTime,\\n sarcophagusParams.creationTime + s.expirationThreshold\\n );\\n }\\n\\n // Confirm that resurrection time is in the future\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\n }\\n\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\n if (\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\n sarcophagusParams.resurrectionTime\\n ) {\\n revert ResurrectionTimeTooFarInFuture(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumRewrapInterval,\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the resurrection time is less than the max resurrection time\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumResurrectionTime\\n );\\n }\\n\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // track total digging fees due upon creation of sarcophagus\\n uint256 totalDiggingFees;\\n\\n {\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\n // Validate archaeologist and threshold lengths\\n if (nSelectedArchs == 0) {\\n revert NoArchaeologistsProvided();\\n }\\n\\n if (sarcophagusParams.threshold == 0) {\\n revert ThresholdCannotBeZero();\\n }\\n\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\n // used to distribute keyshares among archaeologists\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\n sarcophagusParams.threshold,\\n nSelectedArchs\\n );\\n }\\n\\n // create the sarcophagus\\n sarcophagus.name = sarcophagusParams.name;\\n sarcophagus.threshold = sarcophagusParams.threshold;\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\n sarcophagus.arweaveTxId = arweaveTxId;\\n sarcophagus.embalmerAddress = msg.sender;\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\n\\n for (uint256 i; i < nSelectedArchs; ) {\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\n\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\n if (\\n sarcophagus\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\n .publicKey\\n .length != 0\\n ) {\\n revert ArchaeologistListContainsDuplicate(\\n selectedArchaeologists[i].archAddress\\n );\\n }\\n\\n // Confirm archaeologist is not re-using a key pair\\n if (\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\n address(0)\\n ) {\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\n }\\n\\n LibUtils.verifyArchaeologistSignature(\\n sarcophagusParams.maximumRewrapInterval,\\n sarcophagusParams.maximumResurrectionTime,\\n sarcophagusParams.creationTime,\\n selectedArchaeologists[i]\\n );\\n\\n // Curse the archaeologist on this sarcophagus\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\n sarcoId,\\n selectedArchaeologists[i],\\n i\\n );\\n\\n totalDiggingFees += diggingFeesDue;\\n\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\n s.publicKeyToArchaeologistAddress[\\n selectedArchaeologists[i].publicKey\\n ] = selectedArchaeologists[i].archAddress;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n s.totalProtocolFees += protocolFees;\\n s.sarcoToken.transferFrom(\\n msg.sender,\\n address(this),\\n totalDiggingFees + protocolFees\\n );\\n }\\n emit CreateSarcophagus(\\n sarcoId,\\n sarcophagusParams.name,\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.creationTime,\\n msg.sender,\\n sarcophagusParams.recipientAddress,\\n sarcophagus.cursedArchaeologistAddresses,\\n totalDiggingFees,\\n arweaveTxId\\n );\\n }\\n\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param resurrectionTime the new resurrection time\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n\\n // Confirm resurrection time has not yet passed\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time is in future\\n if (block.timestamp >= resurrectionTime) {\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\n revert NewResurrectionTimeTooFarInFuture(\\n resurrectionTime,\\n sarcophagus.maximumRewrapInterval,\\n block.timestamp + sarcophagus.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n resurrectionTime,\\n sarcophagus.maximumResurrectionTime\\n );\\n }\\n\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\n uint256 totalDiggingFees;\\n\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\n\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n if (!cursedArchaeologist.isAccused) {\\n // Previous digging fees calculation ignores curseFee\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (resurrectionTime - block.timestamp);\\n\\n // If the new digging fees are greater than the previous digging fees, we need to\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\n if (newDiggingFees > prevDiggingFees) {\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\n if (cursedBondIncrease > prevDiggingFees) {\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n resurrectionTime,\\n sarcophagus.resurrectionTime\\n );\\n }\\n\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond += cursedBondIncrease;\\n\\n // Rewards are now previous digging fees - difference\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\n } else if (newDiggingFees < prevDiggingFees) {\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // Decrease archaeologist's cursed bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond -= cursedBondDecrease;\\n\\n // Increase archaeologist's free bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .freeBond += cursedBondDecrease;\\n\\n // Rewards are equal to the previous digging fees\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n } else {\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n }\\n\\n // Add digging fees due for the new interval\\n totalDiggingFees += newDiggingFees;\\n\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n // Pay archaeologists the curse fee to their rewards\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n\\n // Add the protocol fee to the total protocol fees in storage\\n s.totalProtocolFees += protocolFees;\\n\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\n sarcophagus.resurrectionTime = resurrectionTime;\\n sarcophagus.previousRewrapTime = block.timestamp;\\n\\n if (!sarcophagus.isRewrapped) {\\n sarcophagus.isRewrapped = true;\\n }\\n\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\n\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\n }\\n\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n function burySarcophagus(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n // Confirm that the current resurrection time is in the future\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\n if (!cursedArchaeologist.isAccused) {\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Set resurrection time to infinity\\n sarcophagus.resurrectionTime = type(uint256).max;\\n\\n emit BurySarcophagus(sarcoId);\\n }\\n}\\n\",\"keccak256\":\"0x6f608191836cb34a89292cbad9d19962144f57439e8acade82a5a6ffaf8f248a\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\ncontract ThirdPartyFacet {\\n event AccuseArchaeologist(\\n bytes32 indexed sarcoId,\\n address indexed accuser,\\n uint256 totalSlashedBondDistributed,\\n uint256 totalDiggingFeesDistributed,\\n address[] accusedArchAddresses\\n );\\n\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\n\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\n\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\n\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\n /// @param senderAddress Address of sender\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\n\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\n /// @param currentTime Timestamp of the failed accuse attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\n /// @param signatures the number of signatures passed into the accuse call\\n /// @param publicKeys the number of public keys passed into the accuse call\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\n\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\n /// @param sarcoId that should have been signed\\n /// @param paymentAddress payment address that should have been signed\\n /// @param publicKey publicKey that should be derived from signing key\\n /// @param signature invalid signature\\n error InvalidAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes publicKey,\\n LibTypes.Signature signature\\n );\\n\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\n /// be able to claim remaining locked bond and diggingFees\\n /// @param sarcoId The identifier of the sarcophagus to clean\\n function clean(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer or admin\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not already been cleaned\\n if (sarcophagus.isCleaned) {\\n revert SarcophagusAlreadyCleaned(sarcoId);\\n }\\n\\n // Confirm that the resurrectionTime + gracePeriod have passed\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\n }\\n\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\n if (\\n msg.sender == sarcophagus.embalmerAddress &&\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert EmbalmerClaimWindowPassed(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // if sender is admin, confirm embalmerClaimWindow has passed\\n if (\\n msg.sender == LibDiamond.contractOwner() &&\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert TooEarlyForAdminClean(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\n uint256 totalDiggingFeesAndLockedBonds;\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\n\\n // Punish archaeologists that failed to publish their private key in time\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n if (!sarcophagus.isRewrapped) {\\n diggingFeesDue += cursedArchaeologist.curseFee;\\n }\\n\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\n\\n // slash the archaeologist's locked bond for the sarcophagus\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\n // this to the contract's protocol fees\\n if (msg.sender == sarcophagus.embalmerAddress) {\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\n } else {\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\n }\\n\\n sarcophagus.isCleaned = true;\\n emit Clean(sarcoId, msg.sender);\\n }\\n\\n /**\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\n * and payment address generated with the leaked private keys\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\n *\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\n * returned\\n *\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\n * @param paymentAddress the address to which rewards should be sent if successful\\n */\\n function accuse(\\n bytes32 sarcoId,\\n bytes[] calldata publicKeys,\\n LibTypes.Signature[] calldata signatures,\\n address paymentAddress\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // verify that current time is not past resurrection time\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n uint256 nSigs = signatures.length;\\n\\n if (nSigs != publicKeys.length) {\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\n }\\n\\n address[] memory accusedArchAddresses = new address[](nSigs);\\n\\n // track the combined locked bond across all archaeologists being accused in this call\\n uint256 totalCursedBond;\\n uint256 accusalCount;\\n for (uint256 i; i < nSigs; ) {\\n if (\\n !LibUtils.verifyAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n )\\n ) {\\n revert InvalidAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n );\\n }\\n\\n // look up the archaeologist responsible for the publicKey\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\n .cursedArchaeologists[accusedArchaeologistAddress];\\n\\n // verify the accused archaeologist is cursed on the sarcophagus\\n if (accusedArchaeologist.publicKey.length == 0) {\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\n }\\n\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\n if (accusedArchaeologist.isAccused) {\\n unchecked {\\n ++i;\\n }\\n continue;\\n }\\n\\n // mark the archaeologist on the sarcophagus as having been accused\\n accusedArchaeologist.isAccused = true;\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\n\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\n sarcophagus.cursedBondPercentage) / 10000;\\n\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\n if (!sarcophagus.isRewrapped) {\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\n }\\n\\n totalCursedBond += cursedBondDue;\\n\\n // Slash the offending archaeologists bond\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\n if (accusalCount == 0) {\\n return;\\n }\\n\\n {\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\n if (accusalCount >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n } else {\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\n uint256 totalAccusals;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n if (\\n sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n ++totalAccusals;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\n if (totalAccusals >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n }\\n }\\n\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\n // be returned to the remaining well behaved archaeologists\\n if (sarcophagus.isCompromised) {\\n // iterate through all archaeologist addresses on the sarcophagus\\n for (uint256 i; i < nCursedArchs; ) {\\n // if the archaeologist has never been accused, release their locked bond back to them\\n if (\\n !sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n LibBonds.freeArchaeologist(\\n sarcoId,\\n sarcophagus.cursedArchaeologistAddresses[i]\\n );\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\n s.sarcoToken.transfer(\\n sarcophagus.embalmerAddress,\\n totalDiggingFees + halfTotalCursedBond\\n );\\n\\n // transfer the other half of the cursed bond to the transaction caller\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\n\\n emit AccuseArchaeologist(\\n sarcoId,\\n msg.sender,\\n totalCursedBond,\\n totalDiggingFees,\\n accusedArchAddresses\\n );\\n }\\n}\\n\",\"keccak256\":\"0x6d493c3c0d5bd584f4432f4c559fd431cbff1f47f5587d7453ef918fe91190c2\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\n\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\nlibrary LibBonds {\\n /// @notice Bonds the archaeologist to a sarcophagus.\\n /// This does the following:\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\n ///\\n /// @return the amount of digging fees due the embalmer for this curse\\n function curseArchaeologist(\\n bytes32 sarcoId,\\n EmbalmerFacet.CurseParams calldata archaeologist,\\n uint256 index\\n ) internal returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\n publicKey: archaeologist.publicKey,\\n privateKey: 0,\\n isAccused: false,\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\n curseFee: archaeologist.curseFee\\n });\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\n\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\n + archaeologist.curseFee;\\n\\n // Use cursed bond percentage to determine how much bond to lock up\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\n\\n // Transfer bond to curse from free bond to cursed bond\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\n\\n return diggingFeesDue;\\n }\\n\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\n /// @param archaeologistAddress the address of the archaeologist to free\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\n .sarcophagi[sarcoId]\\n .cursedArchaeologists[archaeologistAddress];\\n\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n // Include curse fee in bond amount being released\\n uint256 cursedBondAmount = ((diggingFeeAmount + cursedArchaeologist.curseFee) * sarcophagus.cursedBondPercentage) / 10000;\\n\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\n\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\n }\\n\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\n }\\n}\\n\",\"keccak256\":\"0x1ce4949867d00310a878d0671312e3c9b51c3301586df45dfc63bc43f16bd1d9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title A collection of Errors\\n * @notice This library defines all of the Errors that the Sarcophagus system\\n * uses.\\n */\\nlibrary LibErrors {\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\n\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\n\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\n\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\n\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\n\\n error SarcophagusInactive(bytes32 sarcoId);\\n\\n error SarcophagusCompromised(bytes32 sarcoId);\\n\\n error SenderNotEmbalmer(address sender, address embalmer);\\n\\n error InvalidSignature(\\n // address recovered from signature via ecrecover\\n address recoveredAddress,\\n // address we expected to have signed the data\\n address expectedAddress\\n );\\n}\\n\",\"keccak256\":\"0xed77e67ab300a74738cd8ec5fe8e3bd5c166b87410051ceaabe0a7ec2e45b967\",\"license\":\"Unlicense\"},\"contracts/libraries/LibPrivateKeys.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Private key verification\\n * @notice Implements a private key -> public key checking function\\n * @dev modified from https://github.com/1Address/ecsol, removes extra code\\n * which isn't necessary for our Sarcophagus implementation\\n */\\nlibrary LibPrivateKeys {\\n /**\\n * @notice Given a private key and a public key, determines if that public\\n * key was derived from the private key\\n * @dev based on https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9\\n * @param privKey an secp256k1 private key\\n * @param pubKey an uncompressed 65 byte secp256k1 public key\\n * @return bool indicating whether the public key is derived from the\\n * private key\\n */\\n function isPublicKeyOfPrivateKey(\\n bytes32 privKey,\\n bytes storage pubKey\\n ) internal view returns (bool) {\\n // removes the 0x04 prefix from an uncompressed public key\\n uint256 pubKeyLength = pubKey.length;\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\n for (uint256 i = 1; i < pubKeyLength; ) {\\n truncatedPublicKey[i - 1] = pubKey[i];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // generator point coordinates and order of secp256k1\\n uint256 gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;\\n uint256 gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;\\n uint256 m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;\\n\\n address signer = ecrecover(\\n 0,\\n gy % 2 != 0 ? 28 : 27,\\n bytes32(gx),\\n bytes32(mulmod(uint256(privKey), gx, m))\\n );\\n\\n address xyAddress = address(\\n uint160(\\n uint256(keccak256(truncatedPublicKey)) &\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n )\\n );\\n return xyAddress == signer;\\n }\\n}\\n\",\"keccak256\":\"0x130ec3b71ef6f6bd40ed4d57009d03e9db3c87d40fb33bd6ffe27e3256ffcca3\",\"license\":\"MIT\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Types shared across facets for the Sarcophagus diamond\\n */\\nlibrary LibTypes {\\n struct Sarcophagus {\\n // Also used for existence checks -- does not exist if 0\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\n bool isCompromised;\\n bool isCleaned;\\n bool isRewrapped;\\n uint8 threshold;\\n string name;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] cursedArchaeologistAddresses;\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\n uint256 cursedBondPercentage;\\n }\\n\\n struct CursedArchaeologist {\\n uint256 diggingFeePerSecond;\\n // Also used for publish checks -- has not published if 0\\n bytes32 privateKey;\\n // Also used for curse checks -- is not bonded if length is 0\\n bytes publicKey;\\n bool isAccused;\\n uint256 curseFee;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n struct ArchaeologistProfile {\\n // Also used for existence checks -- does not exist if 0\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string peerId;\\n uint256 minimumDiggingFeePerSecond;\\n uint256 freeBond;\\n uint256 cursedBond;\\n uint256 curseFee;\\n }\\n}\\n\",\"keccak256\":\"0x1b2f2f8c309ec6d6f4895143d290b5d99daacfee6bfd2443dfe74dc0f29e8678\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\nimport \\\"./LibTypes.sol\\\";\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\n/**\\n * @title Utility functions used within the Sarcophagus system\\n * @notice This library implements various functions that are used throughout\\n * Sarcophagus, mainly to DRY up the codebase\\n * @dev these functions are all stateless, public, pure/view\\n */\\nlibrary LibUtils {\\n /**\\n * @notice The archaeologist needs to sign off on two pieces of data\\n * to guarantee their unrwap will be successful\\n *\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\n * @param curseParams parameters of curse signed by archaeologist\\n */\\n function verifyArchaeologistSignature(\\n uint256 agreedMaximumRewrapInterval,\\n uint256 maximumResurrectionTime,\\n uint256 timestamp,\\n EmbalmerFacet.CurseParams calldata curseParams\\n ) internal pure {\\n // Hash the hash of the data payload\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(\\n abi.encode(\\n curseParams.publicKey,\\n agreedMaximumRewrapInterval,\\n maximumResurrectionTime,\\n curseParams.diggingFeePerSecond,\\n timestamp,\\n curseParams.curseFee\\n )\\n )\\n )\\n );\\n\\n // Generate the address from the signature.\\n // ecrecover should always return a valid address.\\n address recoveredAddress = ecrecover(\\n messageHash,\\n curseParams.v,\\n curseParams.r,\\n curseParams.s\\n );\\n\\n if (recoveredAddress != curseParams.archAddress) {\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\n }\\n }\\n\\n /// @notice Verifies that a signature and public key were created from the same private key\\n /// @param sarcoId the sarcoId that was signed\\n /// @param paymentAddress the payment address that was signed\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\n /// @param signature signature on the sarco id and payment address\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\n function verifyAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes calldata publicKey,\\n LibTypes.Signature calldata signature\\n ) internal pure returns (bool) {\\n // removes the 0x04 prefix from an uncompressed public key\\n uint256 pubKeyLength = publicKey.length;\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\n for (uint256 i = 1; i < pubKeyLength; ) {\\n truncatedPublicKey[i - 1] = publicKey[i];\\n unchecked {\\n ++i;\\n }\\n }\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(abi.encode(sarcoId, paymentAddress))\\n )\\n );\\n // Use ecrecover to get the address that signed the message\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\n\\n address publicKeyAddress = address(\\n uint160(\\n uint256(keccak256(truncatedPublicKey)) &\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n )\\n );\\n\\n return signingAddress == publicKeyAddress;\\n }\\n\\n /// @notice Checks if an archaeologist profile exists and\\n /// reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check existence of\\n function revertIfArchProfileExists(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\n }\\n }\\n\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check lack of existence of\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\n }\\n }\\n\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\n /// @return The protocol fees amount\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\n }\\n}\\n\",\"keccak256\":\"0x1b411278faa2f19d4fb8f558fb1ce33f35cc367cca58b7229d5c2f8848201b48\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\n/**\\n * Global diamond storage struct to be shared across facets\\n */\\nstruct AppStorage {\\n // SARCO token contract\\n IERC20 sarcoToken;\\n // The Admin address allowed to call Admin Facet functions\\n address admin;\\n // total protocol fees available to be withdrawn by the admin\\n uint256 totalProtocolFees;\\n /**\\n * Protocol level admin configurations\\n */\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\n uint256 protocolFeeBasePercentage;\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\n uint256 cursedBondPercentage;\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\n uint256 gracePeriod;\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\n uint256 expirationThreshold;\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\n uint256 embalmerClaimWindow;\\n // registered archaeologist addresses\\n address[] archaeologistProfileAddresses;\\n // public key => archaeologist address\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\n // sarcophagus id => sarcophagus object\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\n // archaeologist address => profile\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\n // current balance of rewards available for the archaeologist to withdraw\\n mapping(address => uint256) archaeologistRewards;\\n}\\n\\nlibrary LibAppStorage {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\n\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n s.slot := position\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07df02177bdd1ecc43723d2c46b8d81ecc84b49c40b7c85478ef4c4650b02335\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50612151806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063364e0801146100675780636a5ac74c1461008357806395b22c721461009f578063a4110dbe146100bb578063a4d9eb43146100d7578063c885bc58146100f3575b600080fd5b610081600480360381019061007c91906114af565b6100fd565b005b61009d600480360381019061009891906114af565b610262565b005b6100b960048036038101906100b49190611622565b6103c9565b005b6100d560048036038101906100d09190611701565b61061d565b005b6100f160048036038101906100ec9190611622565b610a10565b005b6100fb610cc7565b005b6000610107610e55565b905061011233610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546101669190611770565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b81526004016101cc9291906117f4565b6020604051808303816000875af11580156101eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020f9190611855565b503373ffffffffffffffffffffffffffffffffffffffff167fd91b1e491a880123721b161dbbf8249668b0c546077d7ba4d0016441ca9d8f45836040516102569190611882565b60405180910390a25050565b600061026c610e55565b905061027733610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546102cb919061189d565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401610333939291906118d1565b6020604051808303816000875af1158015610352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103769190611855565b503373ffffffffffffffffffffffffffffffffffffffff167ff882a0847c57aefe6f6c7df2098dd0afd122eb0e886199e223651b8e45fda823836040516103bd9190611882565b60405180910390a25050565b60006103d3610e55565b90506103de33610e82565b60008514806103ed5750600086145b15610424576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508781600201908161047a9190611b1f565b50868160030181905550858160000181905550838160010181905550828160060181905550600085146105a8578482600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546104fb919061189d565b925050819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610563939291906118d1565b6020604051808303816000875af1158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190611855565b505b3373ffffffffffffffffffffffffffffffffffffffff167f8497b060a6072f95dc9b98911879fc0378644d084b03c80f8acdb6385609deb88260020183600301548460000154898660010154876006015460405161060b96959493929190611c86565b60405180910390a25050505050505050565b6000610627610e55565b9050600081600a0160008581526020019081526020016000209050600081600001540361068b57836040517f018da6880000000000000000000000000000000000000000000000000000000081526004016106829190611cfd565b60405180910390fd5b8060020160009054906101000a900460ff16156106df57836040517f9af72b860000000000000000000000000000000000000000000000000000000081526004016106d69190611cfd565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361074757836040517f7c6a6d7000000000000000000000000000000000000000000000000000000000815260040161073e9190611cfd565b60405180910390fd5b8060000154421015610796574281600001546040517f4827680900000000000000000000000000000000000000000000000000000000815260040161078d929190611d18565b60405180910390fd5b816005015481600001546107aa919061189d565b4211156108035742826005015482600001546107c6919061189d565b6040517f4ccffab10000000000000000000000000000000000000000000000000000000081526004016107fa929190611d18565b60405180910390fd5b600082600a016000868152602001908152602001600020600a0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201805461086d90611942565b9050036108b157336040517f82881f030000000000000000000000000000000000000000000000000000000081526004016108a89190611d41565b60405180910390fd5b8060030160009054906101000a900460ff16156109075733856040517fa40b44230000000000000000000000000000000000000000000000000000000081526004016108fe929190611d5c565b60405180910390fd5b6000801b81600101541461095257336040517f7b06b1770000000000000000000000000000000000000000000000000000000081526004016109499190611d41565b60405180910390fd5b61095f8482600201610f1e565b6109a7573381600201856040517f5a95e91c00000000000000000000000000000000000000000000000000000000815260040161099e93929190611e2f565b60405180910390fd5b8381600101819055506109ba85336111b4565b3373ffffffffffffffffffffffffffffffffffffffff16857f110eca32dd0b1dbdeaa29671186ba025abb2a6d9c193469a7214ee3244ef740486604051610a019190611cfd565b60405180910390a35050505050565b6000610a1a610e55565b9050610a25336113c9565b6000851480610a345750600086145b15610a6b576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060e001604052808781526020018581526020018981526020018881526020018681526020016000815260200184815250905060008514610b51578160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610b0c939291906118d1565b6020604051808303816000875af1158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190611855565b505b8082600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081610bbc9190611b1f565b50606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505081600801339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f6b3162bc849214e57423b31909892ac678c2245d7ee3c2642c173f7036452394826040015183606001518460000151856080015186602001518760c00151604051610cb596959493929190611ed0565b60405180910390a25050505050505050565b6000610cd1610e55565b9050600081600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600082600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401610dbf9291906117f4565b6020604051808303816000875af1158015610dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e029190611855565b503373ffffffffffffffffffffffffffffffffffffffff167fbc84835063c693975166f00cffb19f01a94c2db55b1bf259238c5da3594e506682604051610e499190611882565b60405180910390a25050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000610e8c610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403610f1a576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401610f11929190611f47565b60405180910390fd5b5050565b600080828054610f2d90611942565b905090506000600182610f409190611770565b67ffffffffffffffff811115610f5957610f586114f7565b5b6040519080825280601f01601f191660200182016040528015610f8b5781602001600182028036833780820191505090505b5090506000600190505b828110156110575784818154610faa90611942565b8110610fb957610fb8611f70565b5b815460011615610fd85790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000028260018361100c9190611770565b8151811061101d5761101c611f70565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806001019050610f95565b5060007f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798905060007f483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419050600060016000806002866110db9190611fce565b036110e757601b6110ea565b601c5b8660001b85806110fd576110fc611f9f565b5b888e60001c0960001b604051600081526020016040526040516111239493929190612063565b6020604051602081039080840390855afa158015611145573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff868051906020012060001c1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161497505050505050505092915050565b60006111be610e55565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546112489190611770565b826000015461125791906120a8565b9050600061271084600b0154846004015484611273919061189d565b61127d91906120a8565b61128791906120ea565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546112dd9190611770565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611338919061189d565b925050819055508360020160029054906101000a900460ff1661136857826004015482611365919061189d565b91505b8185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113b9919061189d565b9250508190555050505050505050565b60006113d3610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414611461576000826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611458929190611f47565b60405180910390fd5b5050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61148c81611479565b811461149757600080fd5b50565b6000813590506114a981611483565b92915050565b6000602082840312156114c5576114c461146f565b5b60006114d38482850161149a565b91505092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61152f826114e6565b810181811067ffffffffffffffff8211171561154e5761154d6114f7565b5b80604052505050565b6000611561611465565b905061156d8282611526565b919050565b600067ffffffffffffffff82111561158d5761158c6114f7565b5b611596826114e6565b9050602081019050919050565b82818337600083830152505050565b60006115c56115c084611572565b611557565b9050828152602081018484840111156115e1576115e06114e1565b5b6115ec8482856115a3565b509392505050565b600082601f830112611609576116086114dc565b5b81356116198482602086016115b2565b91505092915050565b60008060008060008060c0878903121561163f5761163e61146f565b5b600087013567ffffffffffffffff81111561165d5761165c611474565b5b61166989828a016115f4565b965050602061167a89828a0161149a565b955050604061168b89828a0161149a565b945050606061169c89828a0161149a565b93505060806116ad89828a0161149a565b92505060a06116be89828a0161149a565b9150509295509295509295565b6000819050919050565b6116de816116cb565b81146116e957600080fd5b50565b6000813590506116fb816116d5565b92915050565b600080604083850312156117185761171761146f565b5b6000611726858286016116ec565b9250506020611737858286016116ec565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061177b82611479565b915061178683611479565b925082820390508181111561179e5761179d611741565b5b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006117cf826117a4565b9050919050565b6117df816117c4565b82525050565b6117ee81611479565b82525050565b600060408201905061180960008301856117d6565b61181660208301846117e5565b9392505050565b60008115159050919050565b6118328161181d565b811461183d57600080fd5b50565b60008151905061184f81611829565b92915050565b60006020828403121561186b5761186a61146f565b5b600061187984828501611840565b91505092915050565b600060208201905061189760008301846117e5565b92915050565b60006118a882611479565b91506118b383611479565b92508282019050808211156118cb576118ca611741565b5b92915050565b60006060820190506118e660008301866117d6565b6118f360208301856117d6565b61190060408301846117e5565b949350505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061195a57607f821691505b60208210810361196d5761196c611913565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026119d57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611998565b6119df8683611998565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611a1c611a17611a1284611479565b6119f7565b611479565b9050919050565b6000819050919050565b611a3683611a01565b611a4a611a4282611a23565b8484546119a5565b825550505050565b600090565b611a5f611a52565b611a6a818484611a2d565b505050565b5b81811015611a8e57611a83600082611a57565b600181019050611a70565b5050565b601f821115611ad357611aa481611973565b611aad84611988565b81016020851015611abc578190505b611ad0611ac885611988565b830182611a6f565b50505b505050565b600082821c905092915050565b6000611af660001984600802611ad8565b1980831691505092915050565b6000611b0f8383611ae5565b9150826002028217905092915050565b611b2882611908565b67ffffffffffffffff811115611b4157611b406114f7565b5b611b4b8254611942565b611b56828285611a92565b600060209050601f831160018114611b895760008415611b77578287015190505b611b818582611b03565b865550611be9565b601f198416611b9786611973565b60005b82811015611bbf57848901518255600182019150602085019450602081019050611b9a565b86831015611bdc5784890151611bd8601f891682611ae5565b8355505b6001600288020188555050505b505050505050565b600082825260208201905092915050565b60008154611c0f81611942565b611c198186611bf1565b94506001821660008114611c345760018114611c4a57611c7d565b60ff198316865281151560200286019350611c7d565b611c5385611973565b60005b83811015611c7557815481890152600182019150602081019050611c56565b808801955050505b50505092915050565b600060c0820190508181036000830152611ca08189611c02565b9050611caf60208301886117e5565b611cbc60408301876117e5565b611cc960608301866117e5565b611cd660808301856117e5565b611ce360a08301846117e5565b979650505050505050565b611cf7816116cb565b82525050565b6000602082019050611d126000830184611cee565b92915050565b6000604082019050611d2d60008301856117e5565b611d3a60208301846117e5565b9392505050565b6000602082019050611d5660008301846117d6565b92915050565b6000604082019050611d7160008301856117d6565b611d7e6020830184611cee565b9392505050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b60008154611db881611942565b611dc28186611d85565b94506001821660008114611ddd5760018114611df357611e26565b60ff198316865281151560200286019350611e26565b611dfc85611d96565b60005b83811015611e1e57815481890152600182019150602081019050611dff565b808801955050505b50505092915050565b6000606082019050611e4460008301866117d6565b8181036020830152611e568185611dab565b9050611e656040830184611cee565b949350505050565b60005b83811015611e8b578082015181840152602081019050611e70565b60008484015250505050565b6000611ea282611908565b611eac8185611bf1565b9350611ebc818560208601611e6d565b611ec5816114e6565b840191505092915050565b600060c0820190508181036000830152611eea8189611e97565b9050611ef960208301886117e5565b611f0660408301876117e5565b611f1360608301866117e5565b611f2060808301856117e5565b611f2d60a08301846117e5565b979650505050505050565b611f418161181d565b82525050565b6000604082019050611f5c6000830185611f38565b611f6960208301846117d6565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611fd982611479565b9150611fe483611479565b925082611ff457611ff3611f9f565b5b828206905092915050565b6000819050919050565b60008160001b9050919050565b600061203161202c61202784611fff565b612009565b6116cb565b9050919050565b61204181612016565b82525050565b600060ff82169050919050565b61205d81612047565b82525050565b60006080820190506120786000830187612038565b6120856020830186612054565b6120926040830185611cee565b61209f6060830184611cee565b95945050505050565b60006120b382611479565b91506120be83611479565b92508282026120cc81611479565b915082820484148315176120e3576120e2611741565b5b5092915050565b60006120f582611479565b915061210083611479565b9250826121105761210f611f9f565b5b82820490509291505056fea2646970667358221220a866403ce48c1acead1f794ccb93ced9b9dae86cbe242907370c90b181a9a99f64736f6c63430008120033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063364e0801146100675780636a5ac74c1461008357806395b22c721461009f578063a4110dbe146100bb578063a4d9eb43146100d7578063c885bc58146100f3575b600080fd5b610081600480360381019061007c91906114af565b6100fd565b005b61009d600480360381019061009891906114af565b610262565b005b6100b960048036038101906100b49190611622565b6103c9565b005b6100d560048036038101906100d09190611701565b61061d565b005b6100f160048036038101906100ec9190611622565b610a10565b005b6100fb610cc7565b005b6000610107610e55565b905061011233610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546101669190611770565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b81526004016101cc9291906117f4565b6020604051808303816000875af11580156101eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020f9190611855565b503373ffffffffffffffffffffffffffffffffffffffff167fd91b1e491a880123721b161dbbf8249668b0c546077d7ba4d0016441ca9d8f45836040516102569190611882565b60405180910390a25050565b600061026c610e55565b905061027733610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546102cb919061189d565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401610333939291906118d1565b6020604051808303816000875af1158015610352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103769190611855565b503373ffffffffffffffffffffffffffffffffffffffff167ff882a0847c57aefe6f6c7df2098dd0afd122eb0e886199e223651b8e45fda823836040516103bd9190611882565b60405180910390a25050565b60006103d3610e55565b90506103de33610e82565b60008514806103ed5750600086145b15610424576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508781600201908161047a9190611b1f565b50868160030181905550858160000181905550838160010181905550828160060181905550600085146105a8578482600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546104fb919061189d565b925050819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610563939291906118d1565b6020604051808303816000875af1158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190611855565b505b3373ffffffffffffffffffffffffffffffffffffffff167f8497b060a6072f95dc9b98911879fc0378644d084b03c80f8acdb6385609deb88260020183600301548460000154898660010154876006015460405161060b96959493929190611c86565b60405180910390a25050505050505050565b6000610627610e55565b9050600081600a0160008581526020019081526020016000209050600081600001540361068b57836040517f018da6880000000000000000000000000000000000000000000000000000000081526004016106829190611cfd565b60405180910390fd5b8060020160009054906101000a900460ff16156106df57836040517f9af72b860000000000000000000000000000000000000000000000000000000081526004016106d69190611cfd565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361074757836040517f7c6a6d7000000000000000000000000000000000000000000000000000000000815260040161073e9190611cfd565b60405180910390fd5b8060000154421015610796574281600001546040517f4827680900000000000000000000000000000000000000000000000000000000815260040161078d929190611d18565b60405180910390fd5b816005015481600001546107aa919061189d565b4211156108035742826005015482600001546107c6919061189d565b6040517f4ccffab10000000000000000000000000000000000000000000000000000000081526004016107fa929190611d18565b60405180910390fd5b600082600a016000868152602001908152602001600020600a0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201805461086d90611942565b9050036108b157336040517f82881f030000000000000000000000000000000000000000000000000000000081526004016108a89190611d41565b60405180910390fd5b8060030160009054906101000a900460ff16156109075733856040517fa40b44230000000000000000000000000000000000000000000000000000000081526004016108fe929190611d5c565b60405180910390fd5b6000801b81600101541461095257336040517f7b06b1770000000000000000000000000000000000000000000000000000000081526004016109499190611d41565b60405180910390fd5b61095f8482600201610f1e565b6109a7573381600201856040517f5a95e91c00000000000000000000000000000000000000000000000000000000815260040161099e93929190611e2f565b60405180910390fd5b8381600101819055506109ba85336111b4565b3373ffffffffffffffffffffffffffffffffffffffff16857f110eca32dd0b1dbdeaa29671186ba025abb2a6d9c193469a7214ee3244ef740486604051610a019190611cfd565b60405180910390a35050505050565b6000610a1a610e55565b9050610a25336113c9565b6000851480610a345750600086145b15610a6b576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060e001604052808781526020018581526020018981526020018881526020018681526020016000815260200184815250905060008514610b51578160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610b0c939291906118d1565b6020604051808303816000875af1158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190611855565b505b8082600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081610bbc9190611b1f565b50606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505081600801339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f6b3162bc849214e57423b31909892ac678c2245d7ee3c2642c173f7036452394826040015183606001518460000151856080015186602001518760c00151604051610cb596959493929190611ed0565b60405180910390a25050505050505050565b6000610cd1610e55565b9050600081600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600082600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401610dbf9291906117f4565b6020604051808303816000875af1158015610dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e029190611855565b503373ffffffffffffffffffffffffffffffffffffffff167fbc84835063c693975166f00cffb19f01a94c2db55b1bf259238c5da3594e506682604051610e499190611882565b60405180910390a25050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000610e8c610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403610f1a576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401610f11929190611f47565b60405180910390fd5b5050565b600080828054610f2d90611942565b905090506000600182610f409190611770565b67ffffffffffffffff811115610f5957610f586114f7565b5b6040519080825280601f01601f191660200182016040528015610f8b5781602001600182028036833780820191505090505b5090506000600190505b828110156110575784818154610faa90611942565b8110610fb957610fb8611f70565b5b815460011615610fd85790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000028260018361100c9190611770565b8151811061101d5761101c611f70565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806001019050610f95565b5060007f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798905060007f483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419050600060016000806002866110db9190611fce565b036110e757601b6110ea565b601c5b8660001b85806110fd576110fc611f9f565b5b888e60001c0960001b604051600081526020016040526040516111239493929190612063565b6020604051602081039080840390855afa158015611145573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff868051906020012060001c1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161497505050505050505092915050565b60006111be610e55565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546112489190611770565b826000015461125791906120a8565b9050600061271084600b0154846004015484611273919061189d565b61127d91906120a8565b61128791906120ea565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546112dd9190611770565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611338919061189d565b925050819055508360020160029054906101000a900460ff1661136857826004015482611365919061189d565b91505b8185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113b9919061189d565b9250508190555050505050505050565b60006113d3610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414611461576000826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611458929190611f47565b60405180910390fd5b5050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61148c81611479565b811461149757600080fd5b50565b6000813590506114a981611483565b92915050565b6000602082840312156114c5576114c461146f565b5b60006114d38482850161149a565b91505092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b61152f826114e6565b810181811067ffffffffffffffff8211171561154e5761154d6114f7565b5b80604052505050565b6000611561611465565b905061156d8282611526565b919050565b600067ffffffffffffffff82111561158d5761158c6114f7565b5b611596826114e6565b9050602081019050919050565b82818337600083830152505050565b60006115c56115c084611572565b611557565b9050828152602081018484840111156115e1576115e06114e1565b5b6115ec8482856115a3565b509392505050565b600082601f830112611609576116086114dc565b5b81356116198482602086016115b2565b91505092915050565b60008060008060008060c0878903121561163f5761163e61146f565b5b600087013567ffffffffffffffff81111561165d5761165c611474565b5b61166989828a016115f4565b965050602061167a89828a0161149a565b955050604061168b89828a0161149a565b945050606061169c89828a0161149a565b93505060806116ad89828a0161149a565b92505060a06116be89828a0161149a565b9150509295509295509295565b6000819050919050565b6116de816116cb565b81146116e957600080fd5b50565b6000813590506116fb816116d5565b92915050565b600080604083850312156117185761171761146f565b5b6000611726858286016116ec565b9250506020611737858286016116ec565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061177b82611479565b915061178683611479565b925082820390508181111561179e5761179d611741565b5b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006117cf826117a4565b9050919050565b6117df816117c4565b82525050565b6117ee81611479565b82525050565b600060408201905061180960008301856117d6565b61181660208301846117e5565b9392505050565b60008115159050919050565b6118328161181d565b811461183d57600080fd5b50565b60008151905061184f81611829565b92915050565b60006020828403121561186b5761186a61146f565b5b600061187984828501611840565b91505092915050565b600060208201905061189760008301846117e5565b92915050565b60006118a882611479565b91506118b383611479565b92508282019050808211156118cb576118ca611741565b5b92915050565b60006060820190506118e660008301866117d6565b6118f360208301856117d6565b61190060408301846117e5565b949350505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061195a57607f821691505b60208210810361196d5761196c611913565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026119d57fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611998565b6119df8683611998565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611a1c611a17611a1284611479565b6119f7565b611479565b9050919050565b6000819050919050565b611a3683611a01565b611a4a611a4282611a23565b8484546119a5565b825550505050565b600090565b611a5f611a52565b611a6a818484611a2d565b505050565b5b81811015611a8e57611a83600082611a57565b600181019050611a70565b5050565b601f821115611ad357611aa481611973565b611aad84611988565b81016020851015611abc578190505b611ad0611ac885611988565b830182611a6f565b50505b505050565b600082821c905092915050565b6000611af660001984600802611ad8565b1980831691505092915050565b6000611b0f8383611ae5565b9150826002028217905092915050565b611b2882611908565b67ffffffffffffffff811115611b4157611b406114f7565b5b611b4b8254611942565b611b56828285611a92565b600060209050601f831160018114611b895760008415611b77578287015190505b611b818582611b03565b865550611be9565b601f198416611b9786611973565b60005b82811015611bbf57848901518255600182019150602085019450602081019050611b9a565b86831015611bdc5784890151611bd8601f891682611ae5565b8355505b6001600288020188555050505b505050505050565b600082825260208201905092915050565b60008154611c0f81611942565b611c198186611bf1565b94506001821660008114611c345760018114611c4a57611c7d565b60ff198316865281151560200286019350611c7d565b611c5385611973565b60005b83811015611c7557815481890152600182019150602081019050611c56565b808801955050505b50505092915050565b600060c0820190508181036000830152611ca08189611c02565b9050611caf60208301886117e5565b611cbc60408301876117e5565b611cc960608301866117e5565b611cd660808301856117e5565b611ce360a08301846117e5565b979650505050505050565b611cf7816116cb565b82525050565b6000602082019050611d126000830184611cee565b92915050565b6000604082019050611d2d60008301856117e5565b611d3a60208301846117e5565b9392505050565b6000602082019050611d5660008301846117d6565b92915050565b6000604082019050611d7160008301856117d6565b611d7e6020830184611cee565b9392505050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b60008154611db881611942565b611dc28186611d85565b94506001821660008114611ddd5760018114611df357611e26565b60ff198316865281151560200286019350611e26565b611dfc85611d96565b60005b83811015611e1e57815481890152600182019150602081019050611dff565b808801955050505b50505092915050565b6000606082019050611e4460008301866117d6565b8181036020830152611e568185611dab565b9050611e656040830184611cee565b949350505050565b60005b83811015611e8b578082015181840152602081019050611e70565b60008484015250505050565b6000611ea282611908565b611eac8185611bf1565b9350611ebc818560208601611e6d565b611ec5816114e6565b840191505092915050565b600060c0820190508181036000830152611eea8189611e97565b9050611ef960208301886117e5565b611f0660408301876117e5565b611f1360608301866117e5565b611f2060808301856117e5565b611f2d60a08301846117e5565b979650505050505050565b611f418161181d565b82525050565b6000604082019050611f5c6000830185611f38565b611f6960208301846117d6565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611fd982611479565b9150611fe483611479565b925082611ff457611ff3611f9f565b5b828206905092915050565b6000819050919050565b60008160001b9050919050565b600061203161202c61202784611fff565b612009565b6116cb565b9050919050565b61204181612016565b82525050565b600060ff82169050919050565b61205d81612047565b82525050565b60006080820190506120786000830187612038565b6120856020830186612054565b6120926040830185611cee565b61209f6060830184611cee565b95945050505050565b60006120b382611479565b91506120be83611479565b92508282026120cc81611479565b915082820484148315176120e3576120e2611741565b5b5092915050565b60006120f582611479565b915061210083611479565b9250826121105761210f611f9f565b5b82820490509291505056fea2646970667358221220a866403ce48c1acead1f794ccb93ced9b9dae86cbe242907370c90b181a9a99f64736f6c63430008120033", + "devdoc": { + "errors": { + "ArchaeologistAlreadyPublishedPrivateKey(address)": [ + { + "params": { + "archaeologistAddress": "address of publishing archaeologist" + } + } + ], + "ArchaeologistHasBeenAccused(address,bytes32)": [ + { + "params": { + "archaeologistAddress": "Address of accused archaeologist who is attempting to publish their private key", + "sarcoId": "ID of sarcophagus archaeologist has attempted to publish a key on" + } + } + ], + "ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)": [ + { + "params": { + "archaeologistAddress": "address of publishing archaeologist", + "privateKey": "privateKey the archaeologist has attempted to publish", + "publicKey": "publicKey stored for archaeologist on the sarcophagus" + } + } + ], + "TooEarlyForPublish(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed publish attempt", + "resurrectionTime": "Time after which the sarcophagus can be resurrected" + } + } + ], + "TooLateForPublish(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed publish attempt", + "publishDeadline": "Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)" + } + } + ] + }, + "events": { + "PublishPrivateKey(bytes32,bytes32,address)": { + "params": { + "privateKey": "private key that has been published", + "sarcoId": "ID of sarcophagus archaeologist has published the private key on" + } + } + }, + "kind": "dev", + "methods": { + "depositFreeBond(uint256)": { + "params": { + "amount": "The amount to deposit" + } + }, + "publishPrivateKey(bytes32,bytes32)": { + "params": { + "privateKey": "The private key the archaeologist is publishing", + "sarcoId": "The identifier of the sarcophagus for which the archaeologist is responsible" + } + }, + "registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { + "params": { + "curseFee": "The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction", + "freeBond": "How much bond the archaeologist wants to deposit during the register call (if any)", + "maximumResurrectionTime": "The time beyond which the archaeologist is not willing to accept new curses or rewraps", + "maximumRewrapInterval": "The longest interval of time from a rewrap time the arch will accept for a resurrection", + "minimumDiggingFeePerSecond": "The archaeologist's minimum amount to earn per second for being cursed", + "peerId": "The libp2p identifier for the archaeologist" + } + }, + "updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { + "params": { + "curseFee": "The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction", + "freeBond": "How much bond the archaeologist wants to deposit during the update call (if any)", + "maximumRewrapInterval": "The longest interval of time from a rewrap time the arch will accept for a resurrection", + "minimumDiggingFeePerSecond": "The archaeologist's minimum amount to earn per second for being cursed", + "peerId": "The libp2p identifier for the archaeologist" + } + }, + "withdrawFreeBond(uint256)": { + "params": { + "amount": "The amount to withdraw" + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "ArchaeologistAlreadyPublishedPrivateKey(address)": [ + { + "notice": "Archaeologist has attempted to publish a key for a sarcophagus twice" + } + ], + "ArchaeologistHasBeenAccused(address,bytes32)": [ + { + "notice": "An archaeologist that has already been successfully accused has attempted to publish their private key" + } + ], + "ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)": [ + { + "notice": "Archaeologist has attempted to publish the incorrect private key for a sarcophagus" + } + ], + "CannotSetZeroProfileValue()": [ + { + "notice": "Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval" + } + ], + "TooEarlyForPublish(uint256,uint256)": [ + { + "notice": "Archaeologist has attempted to publish a key before the resurrection time" + } + ], + "TooLateForPublish(uint256,uint256)": [ + { + "notice": "Archaeologist has attempted to publish a key after the end of the resurrection window" + } + ] + }, + "events": { + "PublishPrivateKey(bytes32,bytes32,address)": { + "notice": "Emitted when an archaeologist successfully publishes their private key for a sarcophagus" + } + }, + "kind": "user", + "methods": { + "depositFreeBond(uint256)": { + "notice": "Deposits an archaeologist's free bond to the contract." + }, + "publishPrivateKey(bytes32,bytes32)": { + "notice": "Publishes the private key for which the archaeologist is responsible during the sarcophagus resurrection window. Pays digging fees to the archaeologist and releases their locked bond. Cannot be called on a compromised or buried sarcophagus." + }, + "registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { + "notice": "Registers the archaeologist profile" + }, + "updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { + "notice": "Updates the archaeologist profile" + }, + "withdrawFreeBond(uint256)": { + "notice": "Withdraws an archaeologist's free bond from the contract." + }, + "withdrawReward()": { + "notice": "Withdraws all rewards from an archaeologist's reward pool" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/arbitrum/EmbalmerFacet.json b/deployments/arbitrum/EmbalmerFacet.json new file mode 100644 index 0000000..b5635cb --- /dev/null +++ b/deployments/arbitrum/EmbalmerFacet.json @@ -0,0 +1,722 @@ +{ + "address": "0xA08B01a4A170d6167433ce322C67a9f9C5b28557", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "archaeologistAddress", + "type": "address" + } + ], + "name": "ArchaeologistListContainsDuplicate", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bool", + "name": "exists", + "type": "bool" + }, + { + "internalType": "address", + "name": "archaeologist", + "type": "address" + } + ], + "name": "ArchaeologistProfileExistsShouldBe", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + } + ], + "name": "DuplicatePublicKey", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recoveredAddress", + "type": "address" + }, + { + "internalType": "address", + "name": "expectedAddress", + "type": "address" + } + ], + "name": "InvalidSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "newResurrectionTime", + "type": "uint256" + } + ], + "name": "NewResurrectionTimeInPast", + "type": "error" + }, + { + "inputs": [], + "name": "NewResurrectionTimeIsZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sarcophagusMaximumRewrapInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumPermissibleResurrectionTime", + "type": "uint256" + } + ], + "name": "NewResurrectionTimeTooFarInFuture", + "type": "error" + }, + { + "inputs": [], + "name": "NoArchaeologistsProvided", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + } + ], + "name": "ResurrectionTimeInPast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maxResurrectionTime", + "type": "uint256" + } + ], + "name": "ResurrectionTimePastMaxResurrectionTime", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "sarcophagusMaximumRewrapInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumPermissibleResurrectionTime", + "type": "uint256" + } + ], + "name": "ResurrectionTimeTooFarInFuture", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "previousResurrectionTime", + "type": "uint256" + } + ], + "name": "ResurrectionTimeTooFarPastPreviousResurrectionTime", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusAlreadyExists", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusCompromised", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "creationDeadline", + "type": "uint256" + } + ], + "name": "SarcophagusParametersExpired", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "sender", + "type": "address" + }, + { + "internalType": "address", + "name": "embalmer", + "type": "address" + } + ], + "name": "SenderNotEmbalmer", + "type": "error" + }, + { + "inputs": [], + "name": "ThresholdCannotBeZero", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "threshold", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "totalNumberOfArchaeologists", + "type": "uint256" + } + ], + "name": "ThresholdGreaterThanTotalNumberOfArchaeologists", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "BurySarcophagus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "creationTime", + "type": "uint256" + }, + { + "indexed": true, + "internalType": "address", + "name": "embalmer", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "recipient", + "type": "address" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "cursedArchaeologists", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDiggingFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "string", + "name": "arweaveTxId", + "type": "string" + } + ], + "name": "CreateSarcophagus", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDiggingFees", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "rewrapSarcophagusProtocolFees", + "type": "uint256" + } + ], + "name": "RewrapSarcophagus", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "burySarcophagus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "components": [ + { + "internalType": "string", + "name": "name", + "type": "string" + }, + { + "internalType": "uint256", + "name": "maximumRewrapInterval", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "maximumResurrectionTime", + "type": "uint256" + }, + { + "internalType": "address", + "name": "recipientAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "threshold", + "type": "uint8" + }, + { + "internalType": "uint256", + "name": "creationTime", + "type": "uint256" + } + ], + "internalType": "struct EmbalmerFacet.SarcophagusParams", + "name": "sarcophagusParams", + "type": "tuple" + }, + { + "components": [ + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "internalType": "address", + "name": "archAddress", + "type": "address" + }, + { + "internalType": "uint256", + "name": "diggingFeePerSecond", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "curseFee", + "type": "uint256" + }, + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "internalType": "struct EmbalmerFacet.CurseParams[]", + "name": "selectedArchaeologists", + "type": "tuple[]" + }, + { + "internalType": "string", + "name": "arweaveTxId", + "type": "string" + } + ], + "name": "createSarcophagus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + } + ], + "name": "rewrapSarcophagus", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x5d72ef6576862bc2431f52a81defb0bcc2c03973b8207fc655012ad57df69aa4", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", + "contractAddress": null, + "transactionIndex": 3, + "gasUsed": "29240869", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x68bdcd0852b4cc3e81ef557e32486179279da16f32d1aedb7f7650fe4bdca46c", + "transactionHash": "0x5d72ef6576862bc2431f52a81defb0bcc2c03973b8207fc655012ad57df69aa4", + "logs": [], + "blockNumber": 152626932, + "cumulativeGasUsed": "33621311", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "69b6ccc89b7eaa4e346529a9a529edba", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"}],\"name\":\"ArchaeologistListContainsDuplicate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistProfileExistsShouldBe\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"DuplicatePublicKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recoveredAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"expectedAddress\",\"type\":\"address\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"NewResurrectionTimeInPast\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewResurrectionTimeIsZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sarcophagusMaximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumPermissibleResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"NewResurrectionTimeTooFarInFuture\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoArchaeologistsProvided\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeInPast\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimePastMaxResurrectionTime\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sarcophagusMaximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumPermissibleResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeTooFarInFuture\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"previousResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeTooFarPastPreviousResurrectionTime\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusCompromised\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationDeadline\",\"type\":\"uint256\"}],\"name\":\"SarcophagusParametersExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"embalmer\",\"type\":\"address\"}],\"name\":\"SenderNotEmbalmer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"threshold\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"totalNumberOfArchaeologists\",\"type\":\"uint256\"}],\"name\":\"ThresholdGreaterThanTotalNumberOfArchaeologists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"BurySarcophagus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"creationTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"embalmer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"cursedArchaeologists\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDiggingFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"arweaveTxId\",\"type\":\"string\"}],\"name\":\"CreateSarcophagus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDiggingFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewrapSarcophagusProtocolFees\",\"type\":\"uint256\"}],\"name\":\"RewrapSarcophagus\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"burySarcophagus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipientAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"threshold\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"creationTime\",\"type\":\"uint256\"}],\"internalType\":\"struct EmbalmerFacet.SarcophagusParams\",\"name\":\"sarcophagusParams\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"archAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"diggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct EmbalmerFacet.CurseParams[]\",\"name\":\"selectedArchaeologists\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"arweaveTxId\",\"type\":\"string\"}],\"name\":\"createSarcophagus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"rewrapSarcophagus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DuplicatePublicKey(bytes)\":[{\"params\":{\"publicKey\":\"the duplicated public key\"}}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed rewrap attempt\",\"resurrectionTime\":\"Resurrection timestamp which has already passed\"}}],\"ResurrectionTimePastMaxResurrectionTime(uint256,uint256)\":[{\"params\":{\"maxResurrectionTime\":\"The maximum allowed resurrection time\",\"resurrectionTime\":\"The resurrection time defined during the sarcophagus creation or rewrap\"}}],\"ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)\":[{\"params\":{\"maximumPermissibleResurrectionTime\":\"Resurrection timestamp which is too far in the future\",\"resurrectionTime\":\"Resurrection timestamp which is too far in the future\",\"sarcophagusMaximumRewrapInterval\":\"Maximum rewrap interval set for the sarcophagus\"}}],\"SarcophagusAlreadyExists(bytes32)\":[{\"params\":{\"sarcoId\":\"Id that is already in use\"}}],\"SarcophagusParametersExpired(uint256,uint256,uint256)\":[{\"params\":{\"creationDeadline\":\"Deadline for creation of a sarcophagus with the supplied parameters\",\"creationTime\":\"Time when the sarcophagus parameters were created\",\"currentTime\":\"Timestamp of the failed create attempt\"}}]},\"events\":{\"BurySarcophagus(bytes32)\":{\"params\":{\"sarcoId\":\"Id of sarcophagus that was buried\"}},\"CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)\":{\"params\":{\"arweaveTxId\":\"arweave tx id for the sarcophagus\",\"creationTime\":\"Creation time as set during negotiation, not the same as blocktime at which event is emitted\",\"cursedArchaeologists\":\"Array of addresses of cursed archaeologists\",\"embalmer\":\"Address of embalmer\",\"name\":\"Name of the new sarcophagus\",\"recipient\":\"Address of recipient\",\"resurrectionTime\":\"Resurrection time of the new sarcophagus\",\"sarcoId\":\"Id of the new sarcophagus\",\"totalDiggingFees\":\"Total digging fees charged to embalmer to create the sarcophagus\"}},\"RewrapSarcophagus(bytes32,uint256,uint256,uint256)\":{\"params\":{\"resurrectionTime\":\"New resurrection time for the sarcophagus\",\"rewrapSarcophagusProtocolFees\":\"Total protocol fees charged to the embalmer for the rewrap\",\"sarcoId\":\"Id of sarcophagus that was rewrapped\",\"totalDiggingFees\":\"Total digging fees charged to the embalmer for the rewrap\"}}},\"kind\":\"dev\",\"methods\":{\"burySarcophagus(bytes32)\":{\"params\":{\"sarcoId\":\"the identifier of the sarcophagus\"}},\"createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)\":{\"params\":{\"arweaveTxId\":\"id of tx storing the sarcophagus payload on arweave\",\"sarcoId\":\"the identifier of the sarcophagus\",\"sarcophagusParams\":\"params to set on sarcophagus being created\",\"selectedArchaeologists\":\"the archaeologists the embalmer has selected to curse\"}},\"rewrapSarcophagus(bytes32,uint256)\":{\"params\":{\"resurrectionTime\":\"the new resurrection time\",\"sarcoId\":\"the identifier of the sarcophagus\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ArchaeologistListContainsDuplicate(address)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\"}],\"DuplicatePublicKey(bytes)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\"}],\"NoArchaeologistsProvided()\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\"}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\"}],\"ResurrectionTimePastMaxResurrectionTime(uint256,uint256)\":[{\"notice\":\"Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\"}],\"ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\"}],\"SarcophagusAlreadyExists(bytes32)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\"}],\"SarcophagusParametersExpired(uint256,uint256,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with expired parameters\"}],\"ThresholdCannotBeZero()\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\"}],\"ThresholdGreaterThanTotalNumberOfArchaeologists(uint8,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\"}]},\"events\":{\"BurySarcophagus(bytes32)\":{\"notice\":\"Emitted when a sarcophagus is buried\"},\"CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)\":{\"notice\":\"Emitted when a sarcophagus is created\"},\"RewrapSarcophagus(bytes32,uint256,uint256,uint256)\":{\"notice\":\"Emitted when a sarcophagus is rewrapped\"}},\"kind\":\"user\",\"methods\":{\"burySarcophagus(bytes32)\":{\"notice\":\"Terminates a sarcophagus by setting its resurrection time to infinity and returning locked bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\"},\"createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)\":{\"notice\":\"Creates a sarcophagus with the supplied parameters and locks a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration of the sarcophagus until its resurrection time. Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters: - `publicKey` that matches the private key the archaeologist is responsible for - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap. - `creationTime` of sarcophagus - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant. - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\"},\"rewrapSarcophagus(bytes32,uint256)\":{\"notice\":\"Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/EmbalmerFacet.sol\":\"EmbalmerFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\n\\ncontract EmbalmerFacet {\\n /// @notice Emitted when a sarcophagus is created\\n /// @param sarcoId Id of the new sarcophagus\\n /// @param name Name of the new sarcophagus\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\n /// @param embalmer Address of embalmer\\n /// @param recipient Address of recipient\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\n event CreateSarcophagus(\\n bytes32 indexed sarcoId,\\n string name,\\n uint256 resurrectionTime,\\n uint256 creationTime,\\n address indexed embalmer,\\n address indexed recipient,\\n address[] cursedArchaeologists,\\n uint256 totalDiggingFees,\\n string arweaveTxId\\n );\\n\\n /// @notice Emitted when a sarcophagus is rewrapped\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\n event RewrapSarcophagus(\\n bytes32 indexed sarcoId,\\n uint256 resurrectionTime,\\n uint256 totalDiggingFees,\\n uint256 rewrapSarcophagusProtocolFees\\n );\\n\\n /// @notice Emitted when a sarcophagus is buried\\n /// @param sarcoId Id of sarcophagus that was buried\\n event BurySarcophagus(bytes32 indexed sarcoId);\\n\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\n struct SarcophagusParams {\\n string name;\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\n uint256 maximumRewrapInterval;\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\n uint256 maximumResurrectionTime;\\n address recipientAddress;\\n uint256 resurrectionTime;\\n uint8 threshold;\\n uint256 creationTime;\\n }\\n\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\n struct CurseParams {\\n bytes publicKey;\\n address archAddress;\\n uint256 diggingFeePerSecond;\\n uint256 curseFee;\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\n /// @param sarcoId Id that is already in use\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\n /// @param currentTime Timestamp of the failed create attempt\\n /// @param creationTime Time when the sarcophagus parameters were created\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\n error SarcophagusParametersExpired(\\n uint256 currentTime,\\n uint256 creationTime,\\n uint256 creationDeadline\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\n error NoArchaeologistsProvided();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\n error ThresholdCannotBeZero();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\n uint8 threshold,\\n uint256 totalNumberOfArchaeologists\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\n /// @param currentTime Timestamp of the failed rewrap attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\n /// @param publicKey the duplicated public key\\n error DuplicatePublicKey(bytes publicKey);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\n error ResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\n error ResurrectionTimePastMaxResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 maxResurrectionTime\\n );\\n\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\n\\n error NewResurrectionTimeIsZero();\\n\\n error NewResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 previousResurrectionTime\\n );\\n\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\n /// of the sarcophagus until its resurrection time.\\n ///\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\n /// - `creationTime` of sarcophagus\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\n ///\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param sarcophagusParams params to set on sarcophagus being created\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\n function createSarcophagus(\\n bytes32 sarcoId,\\n SarcophagusParams calldata sarcophagusParams,\\n CurseParams[] calldata selectedArchaeologists,\\n string calldata arweaveTxId\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n // Confirm that sarcophagus with supplied id doesn't already exist\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\n revert SarcophagusAlreadyExists(sarcoId);\\n }\\n\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\n // off by its cursed archaeologists.\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\n revert SarcophagusParametersExpired(\\n block.timestamp,\\n sarcophagusParams.creationTime,\\n sarcophagusParams.creationTime + s.expirationThreshold\\n );\\n }\\n\\n // Confirm that resurrection time is in the future\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\n }\\n\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\n if (\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\n sarcophagusParams.resurrectionTime\\n ) {\\n revert ResurrectionTimeTooFarInFuture(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumRewrapInterval,\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the resurrection time is less than the max resurrection time\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumResurrectionTime\\n );\\n }\\n\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // track total digging fees due upon creation of sarcophagus\\n uint256 totalDiggingFees;\\n\\n {\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\n // Validate archaeologist and threshold lengths\\n if (nSelectedArchs == 0) {\\n revert NoArchaeologistsProvided();\\n }\\n\\n if (sarcophagusParams.threshold == 0) {\\n revert ThresholdCannotBeZero();\\n }\\n\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\n // used to distribute keyshares among archaeologists\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\n sarcophagusParams.threshold,\\n nSelectedArchs\\n );\\n }\\n\\n // create the sarcophagus\\n sarcophagus.name = sarcophagusParams.name;\\n sarcophagus.threshold = sarcophagusParams.threshold;\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\n sarcophagus.arweaveTxId = arweaveTxId;\\n sarcophagus.embalmerAddress = msg.sender;\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\n\\n for (uint256 i; i < nSelectedArchs; ) {\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\n\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\n if (\\n sarcophagus\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\n .publicKey\\n .length != 0\\n ) {\\n revert ArchaeologistListContainsDuplicate(\\n selectedArchaeologists[i].archAddress\\n );\\n }\\n\\n // Confirm archaeologist is not re-using a key pair\\n if (\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\n address(0)\\n ) {\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\n }\\n\\n LibUtils.verifyArchaeologistSignature(\\n sarcophagusParams.maximumRewrapInterval,\\n sarcophagusParams.maximumResurrectionTime,\\n sarcophagusParams.creationTime,\\n selectedArchaeologists[i]\\n );\\n\\n // Curse the archaeologist on this sarcophagus\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\n sarcoId,\\n selectedArchaeologists[i],\\n i\\n );\\n\\n totalDiggingFees += diggingFeesDue;\\n\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\n s.publicKeyToArchaeologistAddress[\\n selectedArchaeologists[i].publicKey\\n ] = selectedArchaeologists[i].archAddress;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n s.totalProtocolFees += protocolFees;\\n s.sarcoToken.transferFrom(\\n msg.sender,\\n address(this),\\n totalDiggingFees + protocolFees\\n );\\n }\\n emit CreateSarcophagus(\\n sarcoId,\\n sarcophagusParams.name,\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.creationTime,\\n msg.sender,\\n sarcophagusParams.recipientAddress,\\n sarcophagus.cursedArchaeologistAddresses,\\n totalDiggingFees,\\n arweaveTxId\\n );\\n }\\n\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param resurrectionTime the new resurrection time\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n\\n // Confirm resurrection time has not yet passed\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time is in future\\n if (block.timestamp >= resurrectionTime) {\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\n revert NewResurrectionTimeTooFarInFuture(\\n resurrectionTime,\\n sarcophagus.maximumRewrapInterval,\\n block.timestamp + sarcophagus.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n resurrectionTime,\\n sarcophagus.maximumResurrectionTime\\n );\\n }\\n\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\n uint256 totalDiggingFees;\\n\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\n\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n if (!cursedArchaeologist.isAccused) {\\n // Previous digging fees calculation ignores curseFee\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (resurrectionTime - block.timestamp);\\n\\n // If the new digging fees are greater than the previous digging fees, we need to\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\n if (newDiggingFees > prevDiggingFees) {\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\n if (cursedBondIncrease > prevDiggingFees) {\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n resurrectionTime,\\n sarcophagus.resurrectionTime\\n );\\n }\\n\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond += cursedBondIncrease;\\n\\n // Rewards are now previous digging fees - difference\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\n } else if (newDiggingFees < prevDiggingFees) {\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // Decrease archaeologist's cursed bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond -= cursedBondDecrease;\\n\\n // Increase archaeologist's free bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .freeBond += cursedBondDecrease;\\n\\n // Rewards are equal to the previous digging fees\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n } else {\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n }\\n\\n // Add digging fees due for the new interval\\n totalDiggingFees += newDiggingFees;\\n\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n // Pay archaeologists the curse fee to their rewards\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n\\n // Add the protocol fee to the total protocol fees in storage\\n s.totalProtocolFees += protocolFees;\\n\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\n sarcophagus.resurrectionTime = resurrectionTime;\\n sarcophagus.previousRewrapTime = block.timestamp;\\n\\n if (!sarcophagus.isRewrapped) {\\n sarcophagus.isRewrapped = true;\\n }\\n\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\n\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\n }\\n\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n function burySarcophagus(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n // Confirm that the current resurrection time is in the future\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\n if (!cursedArchaeologist.isAccused) {\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Set resurrection time to infinity\\n sarcophagus.resurrectionTime = type(uint256).max;\\n\\n emit BurySarcophagus(sarcoId);\\n }\\n}\\n\",\"keccak256\":\"0x6f608191836cb34a89292cbad9d19962144f57439e8acade82a5a6ffaf8f248a\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\ncontract ThirdPartyFacet {\\n event AccuseArchaeologist(\\n bytes32 indexed sarcoId,\\n address indexed accuser,\\n uint256 totalSlashedBondDistributed,\\n uint256 totalDiggingFeesDistributed,\\n address[] accusedArchAddresses\\n );\\n\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\n\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\n\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\n\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\n /// @param senderAddress Address of sender\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\n\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\n /// @param currentTime Timestamp of the failed accuse attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\n /// @param signatures the number of signatures passed into the accuse call\\n /// @param publicKeys the number of public keys passed into the accuse call\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\n\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\n /// @param sarcoId that should have been signed\\n /// @param paymentAddress payment address that should have been signed\\n /// @param publicKey publicKey that should be derived from signing key\\n /// @param signature invalid signature\\n error InvalidAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes publicKey,\\n LibTypes.Signature signature\\n );\\n\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\n /// be able to claim remaining locked bond and diggingFees\\n /// @param sarcoId The identifier of the sarcophagus to clean\\n function clean(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer or admin\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not already been cleaned\\n if (sarcophagus.isCleaned) {\\n revert SarcophagusAlreadyCleaned(sarcoId);\\n }\\n\\n // Confirm that the resurrectionTime + gracePeriod have passed\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\n }\\n\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\n if (\\n msg.sender == sarcophagus.embalmerAddress &&\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert EmbalmerClaimWindowPassed(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // if sender is admin, confirm embalmerClaimWindow has passed\\n if (\\n msg.sender == LibDiamond.contractOwner() &&\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert TooEarlyForAdminClean(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\n uint256 totalDiggingFeesAndLockedBonds;\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\n\\n // Punish archaeologists that failed to publish their private key in time\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n if (!sarcophagus.isRewrapped) {\\n diggingFeesDue += cursedArchaeologist.curseFee;\\n }\\n\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\n\\n // slash the archaeologist's locked bond for the sarcophagus\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\n // this to the contract's protocol fees\\n if (msg.sender == sarcophagus.embalmerAddress) {\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\n } else {\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\n }\\n\\n sarcophagus.isCleaned = true;\\n emit Clean(sarcoId, msg.sender);\\n }\\n\\n /**\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\n * and payment address generated with the leaked private keys\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\n *\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\n * returned\\n *\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\n * @param paymentAddress the address to which rewards should be sent if successful\\n */\\n function accuse(\\n bytes32 sarcoId,\\n bytes[] calldata publicKeys,\\n LibTypes.Signature[] calldata signatures,\\n address paymentAddress\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // verify that current time is not past resurrection time\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n uint256 nSigs = signatures.length;\\n\\n if (nSigs != publicKeys.length) {\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\n }\\n\\n address[] memory accusedArchAddresses = new address[](nSigs);\\n\\n // track the combined locked bond across all archaeologists being accused in this call\\n uint256 totalCursedBond;\\n uint256 accusalCount;\\n for (uint256 i; i < nSigs; ) {\\n if (\\n !LibUtils.verifyAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n )\\n ) {\\n revert InvalidAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n );\\n }\\n\\n // look up the archaeologist responsible for the publicKey\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\n .cursedArchaeologists[accusedArchaeologistAddress];\\n\\n // verify the accused archaeologist is cursed on the sarcophagus\\n if (accusedArchaeologist.publicKey.length == 0) {\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\n }\\n\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\n if (accusedArchaeologist.isAccused) {\\n unchecked {\\n ++i;\\n }\\n continue;\\n }\\n\\n // mark the archaeologist on the sarcophagus as having been accused\\n accusedArchaeologist.isAccused = true;\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\n\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\n sarcophagus.cursedBondPercentage) / 10000;\\n\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\n if (!sarcophagus.isRewrapped) {\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\n }\\n\\n totalCursedBond += cursedBondDue;\\n\\n // Slash the offending archaeologists bond\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\n if (accusalCount == 0) {\\n return;\\n }\\n\\n {\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\n if (accusalCount >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n } else {\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\n uint256 totalAccusals;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n if (\\n sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n ++totalAccusals;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\n if (totalAccusals >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n }\\n }\\n\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\n // be returned to the remaining well behaved archaeologists\\n if (sarcophagus.isCompromised) {\\n // iterate through all archaeologist addresses on the sarcophagus\\n for (uint256 i; i < nCursedArchs; ) {\\n // if the archaeologist has never been accused, release their locked bond back to them\\n if (\\n !sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n LibBonds.freeArchaeologist(\\n sarcoId,\\n sarcophagus.cursedArchaeologistAddresses[i]\\n );\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\n s.sarcoToken.transfer(\\n sarcophagus.embalmerAddress,\\n totalDiggingFees + halfTotalCursedBond\\n );\\n\\n // transfer the other half of the cursed bond to the transaction caller\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\n\\n emit AccuseArchaeologist(\\n sarcoId,\\n msg.sender,\\n totalCursedBond,\\n totalDiggingFees,\\n accusedArchAddresses\\n );\\n }\\n}\\n\",\"keccak256\":\"0x6d493c3c0d5bd584f4432f4c559fd431cbff1f47f5587d7453ef918fe91190c2\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\n\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\nlibrary LibBonds {\\n /// @notice Bonds the archaeologist to a sarcophagus.\\n /// This does the following:\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\n ///\\n /// @return the amount of digging fees due the embalmer for this curse\\n function curseArchaeologist(\\n bytes32 sarcoId,\\n EmbalmerFacet.CurseParams calldata archaeologist,\\n uint256 index\\n ) internal returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\n publicKey: archaeologist.publicKey,\\n privateKey: 0,\\n isAccused: false,\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\n curseFee: archaeologist.curseFee\\n });\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\n\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\n + archaeologist.curseFee;\\n\\n // Use cursed bond percentage to determine how much bond to lock up\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\n\\n // Transfer bond to curse from free bond to cursed bond\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\n\\n return diggingFeesDue;\\n }\\n\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\n /// @param archaeologistAddress the address of the archaeologist to free\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\n .sarcophagi[sarcoId]\\n .cursedArchaeologists[archaeologistAddress];\\n\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n // Include curse fee in bond amount being released\\n uint256 cursedBondAmount = ((diggingFeeAmount + cursedArchaeologist.curseFee) * sarcophagus.cursedBondPercentage) / 10000;\\n\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\n\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\n }\\n\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\n }\\n}\\n\",\"keccak256\":\"0x1ce4949867d00310a878d0671312e3c9b51c3301586df45dfc63bc43f16bd1d9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title A collection of Errors\\n * @notice This library defines all of the Errors that the Sarcophagus system\\n * uses.\\n */\\nlibrary LibErrors {\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\n\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\n\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\n\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\n\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\n\\n error SarcophagusInactive(bytes32 sarcoId);\\n\\n error SarcophagusCompromised(bytes32 sarcoId);\\n\\n error SenderNotEmbalmer(address sender, address embalmer);\\n\\n error InvalidSignature(\\n // address recovered from signature via ecrecover\\n address recoveredAddress,\\n // address we expected to have signed the data\\n address expectedAddress\\n );\\n}\\n\",\"keccak256\":\"0xed77e67ab300a74738cd8ec5fe8e3bd5c166b87410051ceaabe0a7ec2e45b967\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Types shared across facets for the Sarcophagus diamond\\n */\\nlibrary LibTypes {\\n struct Sarcophagus {\\n // Also used for existence checks -- does not exist if 0\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\n bool isCompromised;\\n bool isCleaned;\\n bool isRewrapped;\\n uint8 threshold;\\n string name;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] cursedArchaeologistAddresses;\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\n uint256 cursedBondPercentage;\\n }\\n\\n struct CursedArchaeologist {\\n uint256 diggingFeePerSecond;\\n // Also used for publish checks -- has not published if 0\\n bytes32 privateKey;\\n // Also used for curse checks -- is not bonded if length is 0\\n bytes publicKey;\\n bool isAccused;\\n uint256 curseFee;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n struct ArchaeologistProfile {\\n // Also used for existence checks -- does not exist if 0\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string peerId;\\n uint256 minimumDiggingFeePerSecond;\\n uint256 freeBond;\\n uint256 cursedBond;\\n uint256 curseFee;\\n }\\n}\\n\",\"keccak256\":\"0x1b2f2f8c309ec6d6f4895143d290b5d99daacfee6bfd2443dfe74dc0f29e8678\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\nimport \\\"./LibTypes.sol\\\";\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\n/**\\n * @title Utility functions used within the Sarcophagus system\\n * @notice This library implements various functions that are used throughout\\n * Sarcophagus, mainly to DRY up the codebase\\n * @dev these functions are all stateless, public, pure/view\\n */\\nlibrary LibUtils {\\n /**\\n * @notice The archaeologist needs to sign off on two pieces of data\\n * to guarantee their unrwap will be successful\\n *\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\n * @param curseParams parameters of curse signed by archaeologist\\n */\\n function verifyArchaeologistSignature(\\n uint256 agreedMaximumRewrapInterval,\\n uint256 maximumResurrectionTime,\\n uint256 timestamp,\\n EmbalmerFacet.CurseParams calldata curseParams\\n ) internal pure {\\n // Hash the hash of the data payload\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(\\n abi.encode(\\n curseParams.publicKey,\\n agreedMaximumRewrapInterval,\\n maximumResurrectionTime,\\n curseParams.diggingFeePerSecond,\\n timestamp,\\n curseParams.curseFee\\n )\\n )\\n )\\n );\\n\\n // Generate the address from the signature.\\n // ecrecover should always return a valid address.\\n address recoveredAddress = ecrecover(\\n messageHash,\\n curseParams.v,\\n curseParams.r,\\n curseParams.s\\n );\\n\\n if (recoveredAddress != curseParams.archAddress) {\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\n }\\n }\\n\\n /// @notice Verifies that a signature and public key were created from the same private key\\n /// @param sarcoId the sarcoId that was signed\\n /// @param paymentAddress the payment address that was signed\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\n /// @param signature signature on the sarco id and payment address\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\n function verifyAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes calldata publicKey,\\n LibTypes.Signature calldata signature\\n ) internal pure returns (bool) {\\n // removes the 0x04 prefix from an uncompressed public key\\n uint256 pubKeyLength = publicKey.length;\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\n for (uint256 i = 1; i < pubKeyLength; ) {\\n truncatedPublicKey[i - 1] = publicKey[i];\\n unchecked {\\n ++i;\\n }\\n }\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(abi.encode(sarcoId, paymentAddress))\\n )\\n );\\n // Use ecrecover to get the address that signed the message\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\n\\n address publicKeyAddress = address(\\n uint160(\\n uint256(keccak256(truncatedPublicKey)) &\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n )\\n );\\n\\n return signingAddress == publicKeyAddress;\\n }\\n\\n /// @notice Checks if an archaeologist profile exists and\\n /// reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check existence of\\n function revertIfArchProfileExists(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\n }\\n }\\n\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check lack of existence of\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\n }\\n }\\n\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\n /// @return The protocol fees amount\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\n }\\n}\\n\",\"keccak256\":\"0x1b411278faa2f19d4fb8f558fb1ce33f35cc367cca58b7229d5c2f8848201b48\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\n/**\\n * Global diamond storage struct to be shared across facets\\n */\\nstruct AppStorage {\\n // SARCO token contract\\n IERC20 sarcoToken;\\n // The Admin address allowed to call Admin Facet functions\\n address admin;\\n // total protocol fees available to be withdrawn by the admin\\n uint256 totalProtocolFees;\\n /**\\n * Protocol level admin configurations\\n */\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\n uint256 protocolFeeBasePercentage;\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\n uint256 cursedBondPercentage;\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\n uint256 gracePeriod;\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\n uint256 expirationThreshold;\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\n uint256 embalmerClaimWindow;\\n // registered archaeologist addresses\\n address[] archaeologistProfileAddresses;\\n // public key => archaeologist address\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\n // sarcophagus id => sarcophagus object\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\n // archaeologist address => profile\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\n // current balance of rewards available for the archaeologist to withdraw\\n mapping(address => uint256) archaeologistRewards;\\n}\\n\\nlibrary LibAppStorage {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\n\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n s.slot := position\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07df02177bdd1ecc43723d2c46b8d81ecc84b49c40b7c85478ef4c4650b02335\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50613154806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630511f2ec1461004657806355b21ba214610062578063ab7d79691461007e575b600080fd5b610060600480360381019061005b9190612149565b61009a565b005b61007c60048036038101906100779190612255565b610432565b005b6100986004803603810190610093919061234e565b610e19565b005b60006100a46118cd565b9050600081600a0160008481526020019081526020016000209050600081600001540361010857826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100ff919061239d565b60405180910390fd5b8060020160009054906101000a900460ff161561015c57826040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610153919061239d565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036101c457826040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016101bb919061239d565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461027e57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c0000000000000000000000000000000000000000000000000000000081526004016102759291906123f9565b60405180910390fd5b806000015442106102cc574281600001546040517f2458293a0000000000000000000000000000000000000000000000000000000081526004016102c3929190612431565b60405180910390fd5b600081600901905060008180549050905060005b818110156103d457600084600a0160008584815481106103035761030261245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff166103c8576103c7878584815481106103975761039661245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166118fa565b5b816001019150506102e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360000181905550847f3a0205aa93b1a96da7d6405b2967f91b441383623de2d1ee3b27bfd1642b167a60405160405180910390a25050505050565b600061043c6118cd565b9050600081600a016000898152602001908152602001600020600001541461049b57866040517fb9d0d584000000000000000000000000000000000000000000000000000000008152600401610492919061239d565b60405180910390fd5b80600601548660c001356104af91906124b8565b42111561050e57428660c0013582600601548860c001356104d091906124b8565b6040517ffafba495000000000000000000000000000000000000000000000000000000008152600401610505939291906124ec565b60405180910390fd5b8560800135421061055c574286608001356040517f2458293a000000000000000000000000000000000000000000000000000000008152600401610553929190612431565b60405180910390fd5b856080013586602001354261057191906124b8565b10156105cf578560800135866020013587602001354261059191906124b8565b6040517f3d7ad6900000000000000000000000000000000000000000000000000000000081526004016105c6939291906124ec565b60405180910390fd5b85604001358660800135111561062657856080013586604001356040517f7532a1b000000000000000000000000000000000000000000000000000000000815260040161061d929190612431565b60405180910390fd5b600081600a016000898152602001908152602001600020905060008087879050905060008103610682576040517fb274cdd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008960a0016020810190610697919061255c565b60ff16036106d1576040517ff412416600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808960a00160208101906106e5919061255c565b60ff16111561073f578860a0016020810190610701919061255c565b816040517fa44e438a000000000000000000000000000000000000000000000000000000008152600401610736929190612598565b60405180910390fd5b88806000019061074f91906125d0565b846003019182610760929190612879565b508860a0016020810190610774919061255c565b8360020160036101000a81548160ff021916908360ff160217905550886080013583600001819055508860c001358360010181905550886020013583600401819055508860400135836005018190555085858460060191826107d7929190612879565b50338360070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088606001602081019061082e9190612975565b8360080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508067ffffffffffffffff81111561088a5761088961263e565b5b6040519080825280602002602001820160405280156108b85781602001602082028036833780820191505090505b508360090190805190602001906108d0929190612062565b50836004015483600b018190555060005b81811015610c94576109288989838181106108ff576108fe61245a565b5b905060200281019061091191906129a2565b60200160208101906109239190612975565b611b0f565b600084600a0160008b8b858181106109435761094261245a565b5b905060200281019061095591906129a2565b60200160208101906109679190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180546109af9061269c565b905014610a29578888828181106109c9576109c861245a565b5b90506020028101906109db91906129a2565b60200160208101906109ed9190612975565b6040517f11298b2f000000000000000000000000000000000000000000000000000000008152600401610a2091906129ca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16856009018a8a84818110610a5857610a5761245a565b5b9050602002810190610a6a91906129a2565b8060000190610a7991906129e5565b604051610a87929190612a87565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610b4257888882818110610ae457610ae361245a565b5b9050602002810190610af691906129a2565b8060000190610b0591906129e5565b6040517f65453fd5000000000000000000000000000000000000000000000000000000008152600401610b39929190612aef565b60405180910390fd5b610b7e8a602001358b604001358c60c001358c8c86818110610b6757610b6661245a565b5b9050602002810190610b7991906129a2565b611bab565b6000610baf8c8b8b85818110610b9757610b9661245a565b5b9050602002810190610ba991906129a2565b84611d29565b90508084610bbd91906124b8565b9350898983818110610bd257610bd161245a565b5b9050602002810190610be491906129a2565b6020016020810190610bf69190612975565b866009018b8b85818110610c0d57610c0c61245a565b5b9050602002810190610c1f91906129a2565b8060000190610c2e91906129e5565b604051610c3c929190612a87565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816001019150506108e1565b506000610ca083612030565b905080856002016000828254610cb691906124b8565b925050819055508460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308487610d0b91906124b8565b6040518463ffffffff1660e01b8152600401610d2993929190612b13565b6020604051808303816000875af1158015610d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6c9190612b82565b505050876060016020810190610d829190612975565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168a7fe4607f24c5b0a05d9a47b2d4cd8bdb75b50ec717c6bcf5bbc92d48b175d5ce068b8060000190610de191906125d0565b8d608001358e60c0013589600901898e8e604051610e06989796959493929190612d11565b60405180910390a4505050505050505050565b6000610e236118cd565b9050600081600a01600085815260200190815260200160002090506000816000015403610e8757836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610e7e919061239d565b60405180910390fd5b8060020160009054906101000a900460ff1615610edb57836040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610ed2919061239d565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff816000015403610f4357836040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610f3a919061239d565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ffd57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c000000000000000000000000000000000000000000000000000000008152600401610ff49291906123f9565b60405180910390fd5b8060000154421061104b574281600001546040517f2458293a000000000000000000000000000000000000000000000000000000008152600401611042929190612431565b60405180910390fd5b8242106110915742836040517f3c6870c0000000000000000000000000000000000000000000000000000000008152600401611088929190612431565b60405180910390fd5b828160040154426110a291906124b8565b10156110fc578281600401548260040154426110be91906124b8565b6040517fca9b0f900000000000000000000000000000000000000000000000000000000081526004016110f3939291906124ec565b60405180910390fd5b828160050154101561114b578281600501546040517f7532a1b0000000000000000000000000000000000000000000000000000000008152600401611142929190612431565b60405180910390fd5b600080826009019050600083600b0154905060008280549050905060005b8181101561176757600086600a01600086848154811061118c5761118b61245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff1661175b5760008760010154886000015461121f9190612d8b565b826000015461122e9190612dbf565b90506000428b61123e9190612d8b565b836000015461124d9190612dbf565b9050818111156114085760006127108784846112699190612d8b565b6112739190612dbf565b61127d9190612e30565b9050828111156112ca578b8a600001546040517f48d069230000000000000000000000000000000000000000000000000000000081526004016112c1929190612431565b60405180910390fd5b808b600b0160008a88815481106112e4576112e361245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501600082825461135b91906124b8565b92505081905550808361136e9190612d8b565b8b600c0160008a88815481106113875761138661245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113fb91906124b8565b925050819055505061169a565b818110156116035760006127108783856114229190612d8b565b61142c9190612dbf565b6114369190612e30565b9050808b600b0160008a88815481106114525761145161245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546114c99190612d8b565b92505081905550808b600b0160008a88815481106114ea576114e961245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401600082825461156191906124b8565b92505081905550828b600c0160008a88815481106115825761158161245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546115f691906124b8565b9250508190555050611699565b818a600c01600089878154811061161d5761161c61245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461169191906124b8565b925050819055505b5b80886116a691906124b8565b97508860020160029054906101000a900460ff166117585782600401548a600c0160008987815481106116dc576116db61245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461175091906124b8565b925050819055505b50505b81600101915050611169565b50600061177385612030565b90508087600201600082825461178991906124b8565b925050819055508786600001819055504286600101819055508560020160029054906101000a900460ff166117d65760018660020160026101000a81548160ff0219169083151502179055505b8660000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330848961182491906124b8565b6040518463ffffffff1660e01b815260040161184293929190612b13565b6020604051808303816000875af1158015611861573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118859190612b82565b50887ff2ded5f77c6de574fac210979efbdd01ff3071d109e50651be4e05211f6e49438987846040516118ba939291906124ec565b60405180910390a2505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b60006119046118cd565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260010154836000015461198e9190612d8b565b826000015461199d9190612dbf565b9050600061271084600b01548460040154846119b991906124b8565b6119c39190612dbf565b6119cd9190612e30565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254611a239190612d8b565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611a7e91906124b8565b925050819055508360020160029054906101000a900460ff16611aae57826004015482611aab91906124b8565b91505b8185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611aff91906124b8565b9250508190555050505050505050565b6000611b196118cd565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403611ba7576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611b9e929190612e70565b60405180910390fd5b5050565b6000818060000190611bbd91906129e5565b86868560400135878760600135604051602001611be09796959493929190612e99565b60405160208183030381529060405280519060200120604051602001611c069190612f7b565b6040516020818303038152906040528051906020012090506000600182846080016020810190611c36919061255c565b8560a001358660c0013560405160008152602001604052604051611c5d9493929190612fa1565b6020604051602081039080840390855afa158015611c7f573d6000803e3d6000fd5b505050602060405103519050826020016020810190611c9e9190612975565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611d215780836020016020810190611ce49190612975565b6040517f42d750dc000000000000000000000000000000000000000000000000000000008152600401611d189291906123f9565b60405180910390fd5b505050505050565b600080611d346118cd565b9050600081600a01600087815260200190815260200160002090506040518060a00160405280866040013581526020016000801b8152602001868060000190611d7d91906129e5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600015158152602001866060013581525081600a016000876020016020810190611def9190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081611e52919061304c565b5060608201518160030160006101000a81548160ff02191690831515021790555060808201518160040155905050846020016020810190611e939190612975565b816009018581548110611ea957611ea861245a565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000856060013582600101548360000154611f0c9190612d8b565b8760400135611f1b9190612dbf565b611f2591906124b8565b90506000612710846004015483611f3c9190612dbf565b611f469190612e30565b90508084600b016000896020016020810190611f629190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611fae9190612d8b565b925050819055508084600b016000896020016020810190611fcf9190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501600082825461201b91906124b8565b92505081905550819450505050509392505050565b60008061203b6118cd565b90506127108160030154846120509190612dbf565b61205a9190612e30565b915050919050565b8280548282559060005260206000209081019282156120db579160200282015b828111156120da5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190612082565b5b5090506120e891906120ec565b5090565b5b808211156121055760008160009055506001016120ed565b5090565b600080fd5b600080fd5b6000819050919050565b61212681612113565b811461213157600080fd5b50565b6000813590506121438161211d565b92915050565b60006020828403121561215f5761215e612109565b5b600061216d84828501612134565b91505092915050565b600080fd5b600060e0828403121561219157612190612176565b5b81905092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126121bf576121be61219a565b5b8235905067ffffffffffffffff8111156121dc576121db61219f565b5b6020830191508360208202830111156121f8576121f76121a4565b5b9250929050565b60008083601f8401126122155761221461219a565b5b8235905067ffffffffffffffff8111156122325761223161219f565b5b60208301915083600182028301111561224e5761224d6121a4565b5b9250929050565b6000806000806000806080878903121561227257612271612109565b5b600061228089828a01612134565b965050602087013567ffffffffffffffff8111156122a1576122a061210e565b5b6122ad89828a0161217b565b955050604087013567ffffffffffffffff8111156122ce576122cd61210e565b5b6122da89828a016121a9565b9450945050606087013567ffffffffffffffff8111156122fd576122fc61210e565b5b61230989828a016121ff565b92509250509295509295509295565b6000819050919050565b61232b81612318565b811461233657600080fd5b50565b60008135905061234881612322565b92915050565b6000806040838503121561236557612364612109565b5b600061237385828601612134565b925050602061238485828601612339565b9150509250929050565b61239781612113565b82525050565b60006020820190506123b2600083018461238e565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123e3826123b8565b9050919050565b6123f3816123d8565b82525050565b600060408201905061240e60008301856123ea565b61241b60208301846123ea565b9392505050565b61242b81612318565b82525050565b60006040820190506124466000830185612422565b6124536020830184612422565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006124c382612318565b91506124ce83612318565b92508282019050808211156124e6576124e5612489565b5b92915050565b60006060820190506125016000830186612422565b61250e6020830185612422565b61251b6040830184612422565b949350505050565b600060ff82169050919050565b61253981612523565b811461254457600080fd5b50565b60008135905061255681612530565b92915050565b60006020828403121561257257612571612109565b5b600061258084828501612547565b91505092915050565b61259281612523565b82525050565b60006040820190506125ad6000830185612589565b6125ba6020830184612422565b9392505050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126125ed576125ec6125c1565b5b80840192508235915067ffffffffffffffff82111561260f5761260e6125c6565b5b60208301925060018202360383131561262b5761262a6125cb565b5b509250929050565b600082905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806126b457607f821691505b6020821081036126c7576126c661266d565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261272f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826126f2565b61273986836126f2565b95508019841693508086168417925050509392505050565b6000819050919050565b600061277661277161276c84612318565b612751565b612318565b9050919050565b6000819050919050565b6127908361275b565b6127a461279c8261277d565b8484546126ff565b825550505050565b600090565b6127b96127ac565b6127c4818484612787565b505050565b5b818110156127e8576127dd6000826127b1565b6001810190506127ca565b5050565b601f82111561282d576127fe816126cd565b612807846126e2565b81016020851015612816578190505b61282a612822856126e2565b8301826127c9565b50505b505050565b600082821c905092915050565b600061285060001984600802612832565b1980831691505092915050565b6000612869838361283f565b9150826002028217905092915050565b6128838383612633565b67ffffffffffffffff81111561289c5761289b61263e565b5b6128a6825461269c565b6128b18282856127ec565b6000601f8311600181146128e057600084156128ce578287013590505b6128d8858261285d565b865550612940565b601f1984166128ee866126cd565b60005b82811015612916578489013582556001820191506020850194506020810190506128f1565b86831015612933578489013561292f601f89168261283f565b8355505b6001600288020188555050505b50505050505050565b612952816123d8565b811461295d57600080fd5b50565b60008135905061296f81612949565b92915050565b60006020828403121561298b5761298a612109565b5b600061299984828501612960565b91505092915050565b60008235600160e0038336030381126129be576129bd6125c1565b5b80830191505092915050565b60006020820190506129df60008301846123ea565b92915050565b60008083356001602003843603038112612a0257612a016125c1565b5b80840192508235915067ffffffffffffffff821115612a2457612a236125c6565b5b602083019250600182023603831315612a4057612a3f6125cb565b5b509250929050565b600081905092915050565b82818337600083830152505050565b6000612a6e8385612a48565b9350612a7b838584612a53565b82840190509392505050565b6000612a94828486612a62565b91508190509392505050565b600082825260208201905092915050565b6000601f19601f8301169050919050565b6000612ace8385612aa0565b9350612adb838584612a53565b612ae483612ab1565b840190509392505050565b60006020820190508181036000830152612b0a818486612ac2565b90509392505050565b6000606082019050612b2860008301866123ea565b612b3560208301856123ea565b612b426040830184612422565b949350505050565b60008115159050919050565b612b5f81612b4a565b8114612b6a57600080fd5b50565b600081519050612b7c81612b56565b92915050565b600060208284031215612b9857612b97612109565b5b6000612ba684828501612b6d565b91505092915050565b600082825260208201905092915050565b6000612bcc8385612baf565b9350612bd9838584612a53565b612be283612ab1565b840190509392505050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b612c27816123d8565b82525050565b6000612c398383612c1e565b60208301905092915050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612c85612c8083612c45565b612c52565b9050919050565b6000612c988254612c72565b9050919050565b6000600182019050919050565b6000612cb782612bed565b612cc18185612bf8565b9350612ccc83612c09565b8060005b83811015612d0457612ce182612c8c565b612ceb8882612c2d565b9750612cf683612c9f565b925050600181019050612cd0565b5085935050505092915050565b600060c0820190508181036000830152612d2c818a8c612bc0565b9050612d3b6020830189612422565b612d486040830188612422565b8181036060830152612d5a8187612cac565b9050612d696080830186612422565b81810360a0830152612d7c818486612bc0565b90509998505050505050505050565b6000612d9682612318565b9150612da183612318565b9250828203905081811115612db957612db8612489565b5b92915050565b6000612dca82612318565b9150612dd583612318565b9250828202612de381612318565b91508282048414831517612dfa57612df9612489565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612e3b82612318565b9150612e4683612318565b925082612e5657612e55612e01565b5b828204905092915050565b612e6a81612b4a565b82525050565b6000604082019050612e856000830185612e61565b612e9260208301846123ea565b9392505050565b600060c0820190508181036000830152612eb481898b612ac2565b9050612ec36020830188612422565b612ed06040830187612422565b612edd6060830186612422565b612eea6080830185612422565b612ef760a0830184612422565b98975050505050505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000612f44601c83612f03565b9150612f4f82612f0e565b601c82019050919050565b6000819050919050565b612f75612f7082612113565b612f5a565b82525050565b6000612f8682612f37565b9150612f928284612f64565b60208201915081905092915050565b6000608082019050612fb6600083018761238e565b612fc36020830186612589565b612fd0604083018561238e565b612fdd606083018461238e565b95945050505050565b600081519050919050565b60008190508160005260206000209050919050565b601f8211156130475761301881612ff1565b613021846126e2565b81016020851015613030578190505b61304461303c856126e2565b8301826127c9565b50505b505050565b61305582612fe6565b67ffffffffffffffff81111561306e5761306d61263e565b5b613078825461269c565b613083828285613006565b600060209050601f8311600181146130b657600084156130a4578287015190505b6130ae858261285d565b865550613116565b601f1984166130c486612ff1565b60005b828110156130ec578489015182556001820191506020850194506020810190506130c7565b868310156131095784890151613105601f89168261283f565b8355505b6001600288020188555050505b50505050505056fea2646970667358221220422a428fb4ff1f89ac3334bffb8bfebc962d855eb2f0b389c74021152d7e1c0364736f6c63430008120033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80630511f2ec1461004657806355b21ba214610062578063ab7d79691461007e575b600080fd5b610060600480360381019061005b9190612149565b61009a565b005b61007c60048036038101906100779190612255565b610432565b005b6100986004803603810190610093919061234e565b610e19565b005b60006100a46118cd565b9050600081600a0160008481526020019081526020016000209050600081600001540361010857826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100ff919061239d565b60405180910390fd5b8060020160009054906101000a900460ff161561015c57826040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610153919061239d565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036101c457826040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016101bb919061239d565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461027e57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c0000000000000000000000000000000000000000000000000000000081526004016102759291906123f9565b60405180910390fd5b806000015442106102cc574281600001546040517f2458293a0000000000000000000000000000000000000000000000000000000081526004016102c3929190612431565b60405180910390fd5b600081600901905060008180549050905060005b818110156103d457600084600a0160008584815481106103035761030261245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff166103c8576103c7878584815481106103975761039661245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166118fa565b5b816001019150506102e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360000181905550847f3a0205aa93b1a96da7d6405b2967f91b441383623de2d1ee3b27bfd1642b167a60405160405180910390a25050505050565b600061043c6118cd565b9050600081600a016000898152602001908152602001600020600001541461049b57866040517fb9d0d584000000000000000000000000000000000000000000000000000000008152600401610492919061239d565b60405180910390fd5b80600601548660c001356104af91906124b8565b42111561050e57428660c0013582600601548860c001356104d091906124b8565b6040517ffafba495000000000000000000000000000000000000000000000000000000008152600401610505939291906124ec565b60405180910390fd5b8560800135421061055c574286608001356040517f2458293a000000000000000000000000000000000000000000000000000000008152600401610553929190612431565b60405180910390fd5b856080013586602001354261057191906124b8565b10156105cf578560800135866020013587602001354261059191906124b8565b6040517f3d7ad6900000000000000000000000000000000000000000000000000000000081526004016105c6939291906124ec565b60405180910390fd5b85604001358660800135111561062657856080013586604001356040517f7532a1b000000000000000000000000000000000000000000000000000000000815260040161061d929190612431565b60405180910390fd5b600081600a016000898152602001908152602001600020905060008087879050905060008103610682576040517fb274cdd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008960a0016020810190610697919061255c565b60ff16036106d1576040517ff412416600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808960a00160208101906106e5919061255c565b60ff16111561073f578860a0016020810190610701919061255c565b816040517fa44e438a000000000000000000000000000000000000000000000000000000008152600401610736929190612598565b60405180910390fd5b88806000019061074f91906125d0565b846003019182610760929190612879565b508860a0016020810190610774919061255c565b8360020160036101000a81548160ff021916908360ff160217905550886080013583600001819055508860c001358360010181905550886020013583600401819055508860400135836005018190555085858460060191826107d7929190612879565b50338360070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088606001602081019061082e9190612975565b8360080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508067ffffffffffffffff81111561088a5761088961263e565b5b6040519080825280602002602001820160405280156108b85781602001602082028036833780820191505090505b508360090190805190602001906108d0929190612062565b50836004015483600b018190555060005b81811015610c94576109288989838181106108ff576108fe61245a565b5b905060200281019061091191906129a2565b60200160208101906109239190612975565b611b0f565b600084600a0160008b8b858181106109435761094261245a565b5b905060200281019061095591906129a2565b60200160208101906109679190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180546109af9061269c565b905014610a29578888828181106109c9576109c861245a565b5b90506020028101906109db91906129a2565b60200160208101906109ed9190612975565b6040517f11298b2f000000000000000000000000000000000000000000000000000000008152600401610a2091906129ca565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16856009018a8a84818110610a5857610a5761245a565b5b9050602002810190610a6a91906129a2565b8060000190610a7991906129e5565b604051610a87929190612a87565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610b4257888882818110610ae457610ae361245a565b5b9050602002810190610af691906129a2565b8060000190610b0591906129e5565b6040517f65453fd5000000000000000000000000000000000000000000000000000000008152600401610b39929190612aef565b60405180910390fd5b610b7e8a602001358b604001358c60c001358c8c86818110610b6757610b6661245a565b5b9050602002810190610b7991906129a2565b611bab565b6000610baf8c8b8b85818110610b9757610b9661245a565b5b9050602002810190610ba991906129a2565b84611d29565b90508084610bbd91906124b8565b9350898983818110610bd257610bd161245a565b5b9050602002810190610be491906129a2565b6020016020810190610bf69190612975565b866009018b8b85818110610c0d57610c0c61245a565b5b9050602002810190610c1f91906129a2565b8060000190610c2e91906129e5565b604051610c3c929190612a87565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816001019150506108e1565b506000610ca083612030565b905080856002016000828254610cb691906124b8565b925050819055508460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308487610d0b91906124b8565b6040518463ffffffff1660e01b8152600401610d2993929190612b13565b6020604051808303816000875af1158015610d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6c9190612b82565b505050876060016020810190610d829190612975565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168a7fe4607f24c5b0a05d9a47b2d4cd8bdb75b50ec717c6bcf5bbc92d48b175d5ce068b8060000190610de191906125d0565b8d608001358e60c0013589600901898e8e604051610e06989796959493929190612d11565b60405180910390a4505050505050505050565b6000610e236118cd565b9050600081600a01600085815260200190815260200160002090506000816000015403610e8757836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610e7e919061239d565b60405180910390fd5b8060020160009054906101000a900460ff1615610edb57836040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610ed2919061239d565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff816000015403610f4357836040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610f3a919061239d565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ffd57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c000000000000000000000000000000000000000000000000000000008152600401610ff49291906123f9565b60405180910390fd5b8060000154421061104b574281600001546040517f2458293a000000000000000000000000000000000000000000000000000000008152600401611042929190612431565b60405180910390fd5b8242106110915742836040517f3c6870c0000000000000000000000000000000000000000000000000000000008152600401611088929190612431565b60405180910390fd5b828160040154426110a291906124b8565b10156110fc578281600401548260040154426110be91906124b8565b6040517fca9b0f900000000000000000000000000000000000000000000000000000000081526004016110f3939291906124ec565b60405180910390fd5b828160050154101561114b578281600501546040517f7532a1b0000000000000000000000000000000000000000000000000000000008152600401611142929190612431565b60405180910390fd5b600080826009019050600083600b0154905060008280549050905060005b8181101561176757600086600a01600086848154811061118c5761118b61245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff1661175b5760008760010154886000015461121f9190612d8b565b826000015461122e9190612dbf565b90506000428b61123e9190612d8b565b836000015461124d9190612dbf565b9050818111156114085760006127108784846112699190612d8b565b6112739190612dbf565b61127d9190612e30565b9050828111156112ca578b8a600001546040517f48d069230000000000000000000000000000000000000000000000000000000081526004016112c1929190612431565b60405180910390fd5b808b600b0160008a88815481106112e4576112e361245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501600082825461135b91906124b8565b92505081905550808361136e9190612d8b565b8b600c0160008a88815481106113875761138661245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113fb91906124b8565b925050819055505061169a565b818110156116035760006127108783856114229190612d8b565b61142c9190612dbf565b6114369190612e30565b9050808b600b0160008a88815481106114525761145161245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546114c99190612d8b565b92505081905550808b600b0160008a88815481106114ea576114e961245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401600082825461156191906124b8565b92505081905550828b600c0160008a88815481106115825761158161245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546115f691906124b8565b9250508190555050611699565b818a600c01600089878154811061161d5761161c61245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461169191906124b8565b925050819055505b5b80886116a691906124b8565b97508860020160029054906101000a900460ff166117585782600401548a600c0160008987815481106116dc576116db61245a565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600082825461175091906124b8565b925050819055505b50505b81600101915050611169565b50600061177385612030565b90508087600201600082825461178991906124b8565b925050819055508786600001819055504286600101819055508560020160029054906101000a900460ff166117d65760018660020160026101000a81548160ff0219169083151502179055505b8660000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330848961182491906124b8565b6040518463ffffffff1660e01b815260040161184293929190612b13565b6020604051808303816000875af1158015611861573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118859190612b82565b50887ff2ded5f77c6de574fac210979efbdd01ff3071d109e50651be4e05211f6e49438987846040516118ba939291906124ec565b60405180910390a2505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b60006119046118cd565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020905060008260010154836000015461198e9190612d8b565b826000015461199d9190612dbf565b9050600061271084600b01548460040154846119b991906124b8565b6119c39190612dbf565b6119cd9190612e30565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254611a239190612d8b565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611a7e91906124b8565b925050819055508360020160029054906101000a900460ff16611aae57826004015482611aab91906124b8565b91505b8185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611aff91906124b8565b9250508190555050505050505050565b6000611b196118cd565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403611ba7576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611b9e929190612e70565b60405180910390fd5b5050565b6000818060000190611bbd91906129e5565b86868560400135878760600135604051602001611be09796959493929190612e99565b60405160208183030381529060405280519060200120604051602001611c069190612f7b565b6040516020818303038152906040528051906020012090506000600182846080016020810190611c36919061255c565b8560a001358660c0013560405160008152602001604052604051611c5d9493929190612fa1565b6020604051602081039080840390855afa158015611c7f573d6000803e3d6000fd5b505050602060405103519050826020016020810190611c9e9190612975565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611d215780836020016020810190611ce49190612975565b6040517f42d750dc000000000000000000000000000000000000000000000000000000008152600401611d189291906123f9565b60405180910390fd5b505050505050565b600080611d346118cd565b9050600081600a01600087815260200190815260200160002090506040518060a00160405280866040013581526020016000801b8152602001868060000190611d7d91906129e5565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600015158152602001866060013581525081600a016000876020016020810190611def9190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081611e52919061304c565b5060608201518160030160006101000a81548160ff02191690831515021790555060808201518160040155905050846020016020810190611e939190612975565b816009018581548110611ea957611ea861245a565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055506000856060013582600101548360000154611f0c9190612d8b565b8760400135611f1b9190612dbf565b611f2591906124b8565b90506000612710846004015483611f3c9190612dbf565b611f469190612e30565b90508084600b016000896020016020810190611f629190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611fae9190612d8b565b925050819055508084600b016000896020016020810190611fcf9190612975565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501600082825461201b91906124b8565b92505081905550819450505050509392505050565b60008061203b6118cd565b90506127108160030154846120509190612dbf565b61205a9190612e30565b915050919050565b8280548282559060005260206000209081019282156120db579160200282015b828111156120da5782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555091602001919060010190612082565b5b5090506120e891906120ec565b5090565b5b808211156121055760008160009055506001016120ed565b5090565b600080fd5b600080fd5b6000819050919050565b61212681612113565b811461213157600080fd5b50565b6000813590506121438161211d565b92915050565b60006020828403121561215f5761215e612109565b5b600061216d84828501612134565b91505092915050565b600080fd5b600060e0828403121561219157612190612176565b5b81905092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126121bf576121be61219a565b5b8235905067ffffffffffffffff8111156121dc576121db61219f565b5b6020830191508360208202830111156121f8576121f76121a4565b5b9250929050565b60008083601f8401126122155761221461219a565b5b8235905067ffffffffffffffff8111156122325761223161219f565b5b60208301915083600182028301111561224e5761224d6121a4565b5b9250929050565b6000806000806000806080878903121561227257612271612109565b5b600061228089828a01612134565b965050602087013567ffffffffffffffff8111156122a1576122a061210e565b5b6122ad89828a0161217b565b955050604087013567ffffffffffffffff8111156122ce576122cd61210e565b5b6122da89828a016121a9565b9450945050606087013567ffffffffffffffff8111156122fd576122fc61210e565b5b61230989828a016121ff565b92509250509295509295509295565b6000819050919050565b61232b81612318565b811461233657600080fd5b50565b60008135905061234881612322565b92915050565b6000806040838503121561236557612364612109565b5b600061237385828601612134565b925050602061238485828601612339565b9150509250929050565b61239781612113565b82525050565b60006020820190506123b2600083018461238e565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006123e3826123b8565b9050919050565b6123f3816123d8565b82525050565b600060408201905061240e60008301856123ea565b61241b60208301846123ea565b9392505050565b61242b81612318565b82525050565b60006040820190506124466000830185612422565b6124536020830184612422565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006124c382612318565b91506124ce83612318565b92508282019050808211156124e6576124e5612489565b5b92915050565b60006060820190506125016000830186612422565b61250e6020830185612422565b61251b6040830184612422565b949350505050565b600060ff82169050919050565b61253981612523565b811461254457600080fd5b50565b60008135905061255681612530565b92915050565b60006020828403121561257257612571612109565b5b600061258084828501612547565b91505092915050565b61259281612523565b82525050565b60006040820190506125ad6000830185612589565b6125ba6020830184612422565b9392505050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126125ed576125ec6125c1565b5b80840192508235915067ffffffffffffffff82111561260f5761260e6125c6565b5b60208301925060018202360383131561262b5761262a6125cb565b5b509250929050565b600082905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b600060028204905060018216806126b457607f821691505b6020821081036126c7576126c661266d565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b60006008830261272f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826126f2565b61273986836126f2565b95508019841693508086168417925050509392505050565b6000819050919050565b600061277661277161276c84612318565b612751565b612318565b9050919050565b6000819050919050565b6127908361275b565b6127a461279c8261277d565b8484546126ff565b825550505050565b600090565b6127b96127ac565b6127c4818484612787565b505050565b5b818110156127e8576127dd6000826127b1565b6001810190506127ca565b5050565b601f82111561282d576127fe816126cd565b612807846126e2565b81016020851015612816578190505b61282a612822856126e2565b8301826127c9565b50505b505050565b600082821c905092915050565b600061285060001984600802612832565b1980831691505092915050565b6000612869838361283f565b9150826002028217905092915050565b6128838383612633565b67ffffffffffffffff81111561289c5761289b61263e565b5b6128a6825461269c565b6128b18282856127ec565b6000601f8311600181146128e057600084156128ce578287013590505b6128d8858261285d565b865550612940565b601f1984166128ee866126cd565b60005b82811015612916578489013582556001820191506020850194506020810190506128f1565b86831015612933578489013561292f601f89168261283f565b8355505b6001600288020188555050505b50505050505050565b612952816123d8565b811461295d57600080fd5b50565b60008135905061296f81612949565b92915050565b60006020828403121561298b5761298a612109565b5b600061299984828501612960565b91505092915050565b60008235600160e0038336030381126129be576129bd6125c1565b5b80830191505092915050565b60006020820190506129df60008301846123ea565b92915050565b60008083356001602003843603038112612a0257612a016125c1565b5b80840192508235915067ffffffffffffffff821115612a2457612a236125c6565b5b602083019250600182023603831315612a4057612a3f6125cb565b5b509250929050565b600081905092915050565b82818337600083830152505050565b6000612a6e8385612a48565b9350612a7b838584612a53565b82840190509392505050565b6000612a94828486612a62565b91508190509392505050565b600082825260208201905092915050565b6000601f19601f8301169050919050565b6000612ace8385612aa0565b9350612adb838584612a53565b612ae483612ab1565b840190509392505050565b60006020820190508181036000830152612b0a818486612ac2565b90509392505050565b6000606082019050612b2860008301866123ea565b612b3560208301856123ea565b612b426040830184612422565b949350505050565b60008115159050919050565b612b5f81612b4a565b8114612b6a57600080fd5b50565b600081519050612b7c81612b56565b92915050565b600060208284031215612b9857612b97612109565b5b6000612ba684828501612b6d565b91505092915050565b600082825260208201905092915050565b6000612bcc8385612baf565b9350612bd9838584612a53565b612be283612ab1565b840190509392505050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b612c27816123d8565b82525050565b6000612c398383612c1e565b60208301905092915050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612c85612c8083612c45565b612c52565b9050919050565b6000612c988254612c72565b9050919050565b6000600182019050919050565b6000612cb782612bed565b612cc18185612bf8565b9350612ccc83612c09565b8060005b83811015612d0457612ce182612c8c565b612ceb8882612c2d565b9750612cf683612c9f565b925050600181019050612cd0565b5085935050505092915050565b600060c0820190508181036000830152612d2c818a8c612bc0565b9050612d3b6020830189612422565b612d486040830188612422565b8181036060830152612d5a8187612cac565b9050612d696080830186612422565b81810360a0830152612d7c818486612bc0565b90509998505050505050505050565b6000612d9682612318565b9150612da183612318565b9250828203905081811115612db957612db8612489565b5b92915050565b6000612dca82612318565b9150612dd583612318565b9250828202612de381612318565b91508282048414831517612dfa57612df9612489565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612e3b82612318565b9150612e4683612318565b925082612e5657612e55612e01565b5b828204905092915050565b612e6a81612b4a565b82525050565b6000604082019050612e856000830185612e61565b612e9260208301846123ea565b9392505050565b600060c0820190508181036000830152612eb481898b612ac2565b9050612ec36020830188612422565b612ed06040830187612422565b612edd6060830186612422565b612eea6080830185612422565b612ef760a0830184612422565b98975050505050505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b6000612f44601c83612f03565b9150612f4f82612f0e565b601c82019050919050565b6000819050919050565b612f75612f7082612113565b612f5a565b82525050565b6000612f8682612f37565b9150612f928284612f64565b60208201915081905092915050565b6000608082019050612fb6600083018761238e565b612fc36020830186612589565b612fd0604083018561238e565b612fdd606083018461238e565b95945050505050565b600081519050919050565b60008190508160005260206000209050919050565b601f8211156130475761301881612ff1565b613021846126e2565b81016020851015613030578190505b61304461303c856126e2565b8301826127c9565b50505b505050565b61305582612fe6565b67ffffffffffffffff81111561306e5761306d61263e565b5b613078825461269c565b613083828285613006565b600060209050601f8311600181146130b657600084156130a4578287015190505b6130ae858261285d565b865550613116565b601f1984166130c486612ff1565b60005b828110156130ec578489015182556001820191506020850194506020810190506130c7565b868310156131095784890151613105601f89168261283f565b8355505b6001600288020188555050505b50505050505056fea2646970667358221220422a428fb4ff1f89ac3334bffb8bfebc962d855eb2f0b389c74021152d7e1c0364736f6c63430008120033", + "devdoc": { + "errors": { + "DuplicatePublicKey(bytes)": [ + { + "params": { + "publicKey": "the duplicated public key" + } + } + ], + "ResurrectionTimeInPast(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed rewrap attempt", + "resurrectionTime": "Resurrection timestamp which has already passed" + } + } + ], + "ResurrectionTimePastMaxResurrectionTime(uint256,uint256)": [ + { + "params": { + "maxResurrectionTime": "The maximum allowed resurrection time", + "resurrectionTime": "The resurrection time defined during the sarcophagus creation or rewrap" + } + } + ], + "ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)": [ + { + "params": { + "maximumPermissibleResurrectionTime": "Resurrection timestamp which is too far in the future", + "resurrectionTime": "Resurrection timestamp which is too far in the future", + "sarcophagusMaximumRewrapInterval": "Maximum rewrap interval set for the sarcophagus" + } + } + ], + "SarcophagusAlreadyExists(bytes32)": [ + { + "params": { + "sarcoId": "Id that is already in use" + } + } + ], + "SarcophagusParametersExpired(uint256,uint256,uint256)": [ + { + "params": { + "creationDeadline": "Deadline for creation of a sarcophagus with the supplied parameters", + "creationTime": "Time when the sarcophagus parameters were created", + "currentTime": "Timestamp of the failed create attempt" + } + } + ] + }, + "events": { + "BurySarcophagus(bytes32)": { + "params": { + "sarcoId": "Id of sarcophagus that was buried" + } + }, + "CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)": { + "params": { + "arweaveTxId": "arweave tx id for the sarcophagus", + "creationTime": "Creation time as set during negotiation, not the same as blocktime at which event is emitted", + "cursedArchaeologists": "Array of addresses of cursed archaeologists", + "embalmer": "Address of embalmer", + "name": "Name of the new sarcophagus", + "recipient": "Address of recipient", + "resurrectionTime": "Resurrection time of the new sarcophagus", + "sarcoId": "Id of the new sarcophagus", + "totalDiggingFees": "Total digging fees charged to embalmer to create the sarcophagus" + } + }, + "RewrapSarcophagus(bytes32,uint256,uint256,uint256)": { + "params": { + "resurrectionTime": "New resurrection time for the sarcophagus", + "rewrapSarcophagusProtocolFees": "Total protocol fees charged to the embalmer for the rewrap", + "sarcoId": "Id of sarcophagus that was rewrapped", + "totalDiggingFees": "Total digging fees charged to the embalmer for the rewrap" + } + } + }, + "kind": "dev", + "methods": { + "burySarcophagus(bytes32)": { + "params": { + "sarcoId": "the identifier of the sarcophagus" + } + }, + "createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)": { + "params": { + "arweaveTxId": "id of tx storing the sarcophagus payload on arweave", + "sarcoId": "the identifier of the sarcophagus", + "sarcophagusParams": "params to set on sarcophagus being created", + "selectedArchaeologists": "the archaeologists the embalmer has selected to curse" + } + }, + "rewrapSarcophagus(bytes32,uint256)": { + "params": { + "resurrectionTime": "the new resurrection time", + "sarcoId": "the identifier of the sarcophagus" + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "ArchaeologistListContainsDuplicate(address)": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once" + } + ], + "DuplicatePublicKey(bytes)": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus" + } + ], + "NoArchaeologistsProvided()": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with no archaeologists" + } + ], + "ResurrectionTimeInPast(uint256,uint256)": [ + { + "notice": "Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed" + } + ], + "ResurrectionTimePastMaxResurrectionTime(uint256,uint256)": [ + { + "notice": "Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time" + } + ], + "ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)": [ + { + "notice": "Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval" + } + ], + "SarcophagusAlreadyExists(bytes32)": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use" + } + ], + "SarcophagusParametersExpired(uint256,uint256,uint256)": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with expired parameters" + } + ], + "ThresholdCannotBeZero()": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0" + } + ], + "ThresholdGreaterThanTotalNumberOfArchaeologists(uint8,uint256)": [ + { + "notice": "Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists" + } + ] + }, + "events": { + "BurySarcophagus(bytes32)": { + "notice": "Emitted when a sarcophagus is buried" + }, + "CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)": { + "notice": "Emitted when a sarcophagus is created" + }, + "RewrapSarcophagus(bytes32,uint256,uint256,uint256)": { + "notice": "Emitted when a sarcophagus is rewrapped" + } + }, + "kind": "user", + "methods": { + "burySarcophagus(bytes32)": { + "notice": "Terminates a sarcophagus by setting its resurrection time to infinity and returning locked bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried." + }, + "createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)": { + "notice": "Creates a sarcophagus with the supplied parameters and locks a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration of the sarcophagus until its resurrection time. Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters: - `publicKey` that matches the private key the archaeologist is responsible for - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap. - `creationTime` of sarcophagus - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant. - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant." + }, + "rewrapSarcophagus(bytes32,uint256)": { + "notice": "Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried." + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/baseGoerli/Sarcophagus_V2.json b/deployments/arbitrum/Sarcophagus_V2.json similarity index 96% rename from deployments/baseGoerli/Sarcophagus_V2.json rename to deployments/arbitrum/Sarcophagus_V2.json index 22bc4f9..16a09ef 100644 --- a/deployments/baseGoerli/Sarcophagus_V2.json +++ b/deployments/arbitrum/Sarcophagus_V2.json @@ -1,5 +1,5 @@ { - "address": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", + "address": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", "abi": [ { "inputs": [ @@ -1656,7 +1656,7 @@ }, { "inputs": [], - "name": "CallerIsNotAdmin", + "name": "CallerIsNotAdminOrOwner", "type": "error" }, { @@ -1772,6 +1772,19 @@ "name": "WithdrawProtocolFees", "type": "event" }, + { + "inputs": [], + "name": "getDiamondOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1850,6 +1863,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferDiamondOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2086,54 +2112,54 @@ "type": "function" } ], - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", "receipt": { "to": null, - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", - "transactionIndex": 2, - "gasUsed": "3634494", - "logsBloom": "0x00000000000008000000000000000000000000000000000000800400000000000000000000000000000000040000000000000000000010000000000000000000000000000000000000000000000000000001000001000000000800000000000000000000020000000000000000000800000000000000040000000000000000400020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020008000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2a8a7c6082186fea6f7726e3935d85c9ef8d63015eb2f7da60013705fbc90959", - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", + "contractAddress": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", + "transactionIndex": 7, + "gasUsed": "31879810", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401000001000000000800000000000000000000021000000000000000000800000000000000000000000000000000400020000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000010020000000000000000000000000000000000000000000000000000000080000000000", + "blockHash": "0x7df0c6ddae4e885b619eb6cf2f4603f54f5a284cdf4c92c23c13510677033f3b", + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", "logs": [ { - "transactionIndex": 2, - "blockNumber": 9669994, - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", - "address": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", + "transactionIndex": 7, + "blockNumber": 152627007, + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", + "address": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000b38c80e2263a060bd077ece9b2c81a7a18ec74b5" + "0x000000000000000000000000ae9b102741a1b60c221e39cd9526ab38c9865ab3" ], "data": "0x", - "logIndex": 0, - "blockHash": "0x2a8a7c6082186fea6f7726e3935d85c9ef8d63015eb2f7da60013705fbc90959" + "logIndex": 30, + "blockHash": "0x7df0c6ddae4e885b619eb6cf2f4603f54f5a284cdf4c92c23c13510677033f3b" }, { - "transactionIndex": 2, - "blockNumber": 9669994, - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", - "address": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", + "transactionIndex": 7, + "blockNumber": 152627007, + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", + "address": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", "topics": [ "0x8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000009200000000000000000000000005ca66f7e40f28e0905dd641e7bf4ec69306566360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000030511f2ec0000000000000000000000000000000000000000000000000000000055b21ba200000000000000000000000000000000000000000000000000000000ab7d796900000000000000000000000000000000000000000000000000000000000000000000000000000000a5d2340a71b0b10b82cb879b9f9a31d4c45951020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000066a5ac74c00000000000000000000000000000000000000000000000000000000a4110dbe00000000000000000000000000000000000000000000000000000000a4d9eb430000000000000000000000000000000000000000000000000000000095b22c7200000000000000000000000000000000000000000000000000000000364e080100000000000000000000000000000000000000000000000000000000c885bc58000000000000000000000000000000000000000000000000000000000000000000000000000000007c488a0a555211a6300b8be9a1937f31d41efa2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002ebad22f80000000000000000000000000000000000000000000000000000000097b03b530000000000000000000000000000000000000000000000000000000000000000000000000000000089f887186e23b04a98e2f1d6ad5e8ee300d113590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000106e9960c30000000000000000000000000000000000000000000000000000000042e10bc80000000000000000000000000000000000000000000000000000000057babbaf000000000000000000000000000000000000000000000000000000003fbb893000000000000000000000000000000000000000000000000000000000a9328dcc0000000000000000000000000000000000000000000000000000000087927ce600000000000000000000000000000000000000000000000000000000dcfcb9010000000000000000000000000000000000000000000000000000000031baea67000000000000000000000000000000000000000000000000000000007aa9fd2f000000000000000000000000000000000000000000000000000000008fbd55d200000000000000000000000000000000000000000000000000000000dbd18388000000000000000000000000000000000000000000000000000000009fdaded10000000000000000000000000000000000000000000000000000000079ee54f700000000000000000000000000000000000000000000000000000000de116f0600000000000000000000000000000000000000000000000000000000dc231f43000000000000000000000000000000000000000000000000000000009c54563900000000000000000000000000000000000000000000000000000000000000000000000000000000dd76d7b1720b8ee74218a28eb6d54a52502d637b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000076430ae6a00000000000000000000000000000000000000000000000000000000274f255e00000000000000000000000000000000000000000000000000000000a828c47900000000000000000000000000000000000000000000000000000000f2f65960000000000000000000000000000000000000000000000000000000008a5b56900000000000000000000000000000000000000000000000000000000075829def000000000000000000000000000000000000000000000000000000002d80caa500000000000000000000000000000000000000000000000000000000000000000000000000000000429dbde7913c0ed51e4b21163760b92ee66ff5f50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000ad6e96ff641af53cce4205dafecb8e3acd0490e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b000000000000000000000000000000000000000000000000000000000000000000000000000000003bcf4185443a339517ad4e580067f178d1b68e1d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logIndex": 1, - "blockHash": "0x2a8a7c6082186fea6f7726e3935d85c9ef8d63015eb2f7da60013705fbc90959" + "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000960000000000000000000000000a08b01a4a170d6167433ce322c67a9f9c5b285570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000030511f2ec0000000000000000000000000000000000000000000000000000000055b21ba200000000000000000000000000000000000000000000000000000000ab7d796900000000000000000000000000000000000000000000000000000000000000000000000000000000f375135d20d8098287a3d6961bddf780624865510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000066a5ac74c00000000000000000000000000000000000000000000000000000000a4110dbe00000000000000000000000000000000000000000000000000000000a4d9eb430000000000000000000000000000000000000000000000000000000095b22c7200000000000000000000000000000000000000000000000000000000364e080100000000000000000000000000000000000000000000000000000000c885bc580000000000000000000000000000000000000000000000000000000000000000000000000000000074ecb927aa45de25fb4777e398a2e5514c2a681b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002ebad22f80000000000000000000000000000000000000000000000000000000097b03b530000000000000000000000000000000000000000000000000000000000000000000000000000000067e8a916284558989f2d85c4674f640ec2f1e2830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000106e9960c30000000000000000000000000000000000000000000000000000000042e10bc80000000000000000000000000000000000000000000000000000000057babbaf000000000000000000000000000000000000000000000000000000003fbb893000000000000000000000000000000000000000000000000000000000a9328dcc0000000000000000000000000000000000000000000000000000000087927ce600000000000000000000000000000000000000000000000000000000dcfcb9010000000000000000000000000000000000000000000000000000000031baea67000000000000000000000000000000000000000000000000000000007aa9fd2f000000000000000000000000000000000000000000000000000000008fbd55d200000000000000000000000000000000000000000000000000000000dbd18388000000000000000000000000000000000000000000000000000000009fdaded10000000000000000000000000000000000000000000000000000000079ee54f700000000000000000000000000000000000000000000000000000000de116f0600000000000000000000000000000000000000000000000000000000dc231f43000000000000000000000000000000000000000000000000000000009c54563900000000000000000000000000000000000000000000000000000000000000000000000000000000941b0319c0b1090810fba842b372e9f0795b2a96000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000009682e4e5f000000000000000000000000000000000000000000000000000000006430ae6a00000000000000000000000000000000000000000000000000000000274f255e00000000000000000000000000000000000000000000000000000000a828c47900000000000000000000000000000000000000000000000000000000f2f65960000000000000000000000000000000000000000000000000000000008a5b56900000000000000000000000000000000000000000000000000000000075829def000000000000000000000000000000000000000000000000000000003a805a3c000000000000000000000000000000000000000000000000000000002d80caa500000000000000000000000000000000000000000000000000000000000000000000000000000000429dbde7913c0ed51e4b21163760b92ee66ff5f50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000ad6e96ff641af53cce4205dafecb8e3acd0490e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b000000000000000000000000000000000000000000000000000000000000000000000000000000003bcf4185443a339517ad4e580067f178d1b68e1d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 31, + "blockHash": "0x7df0c6ddae4e885b619eb6cf2f4603f54f5a284cdf4c92c23c13510677033f3b" } ], - "blockNumber": 9669994, - "cumulativeGasUsed": "3732792", + "blockNumber": 152627007, + "cumulativeGasUsed": "40235954", "status": 1, "byzantium": true }, "args": [ - "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", + "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", [ { - "facetAddress": "0x5CA66f7E40F28e0905DD641E7bF4Ec6930656636", + "facetAddress": "0xA08B01a4A170d6167433ce322C67a9f9C5b28557", "functionSelectors": [ "0x0511f2ec", "0x55b21ba2", @@ -2142,7 +2168,7 @@ "action": 0 }, { - "facetAddress": "0xa5D2340a71B0b10b82CB879B9F9a31d4C4595102", + "facetAddress": "0xf375135d20D8098287a3D6961BDDF78062486551", "functionSelectors": [ "0x6a5ac74c", "0xa4110dbe", @@ -2154,7 +2180,7 @@ "action": 0 }, { - "facetAddress": "0x7C488A0a555211A6300B8BE9A1937F31d41eFA2e", + "facetAddress": "0x74eCB927aA45de25fB4777E398A2e5514C2a681B", "functionSelectors": [ "0xebad22f8", "0x97b03b53" @@ -2162,7 +2188,7 @@ "action": 0 }, { - "facetAddress": "0x89f887186e23B04A98e2f1D6aD5E8Ee300d11359", + "facetAddress": "0x67E8A916284558989F2d85C4674F640eC2F1e283", "functionSelectors": [ "0x6e9960c3", "0x42e10bc8", @@ -2184,14 +2210,16 @@ "action": 0 }, { - "facetAddress": "0xdd76D7b1720b8Ee74218a28Eb6D54A52502d637b", + "facetAddress": "0x941B0319c0B1090810fbA842b372E9F0795B2A96", "functionSelectors": [ + "0x682e4e5f", "0x6430ae6a", "0x274f255e", "0xa828c479", "0xf2f65960", "0x8a5b5690", "0x75829def", + "0x3a805a3c", "0x2d80caa5" ], "action": 0 @@ -2229,8 +2257,8 @@ "initData": "0x2a84809100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000148e2b093000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, { - "initContract": "0xe14E811e93B36a5Cb0D74102919D19748cfB14CA", - "initData": "0xb36a27e70000000000000000000000002bc9019e6d9e6a26d7d8d8cdda4e5de9b787d7bb000000000000000000000000b38c80e2263a060bd077ece9b2c81a7a18ec74b50000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000e10" + "initContract": "0x8B54aF0d46B57D219e5f41F78ad7569E28eaE793", + "initData": "0xb36a27e700000000000000000000000082155ab6b6c1113cfb352c7573b010a88f5974bd000000000000000000000000ae9b102741a1b60c221e39cd9526ab38c9865ab30000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000e10" } ] ], @@ -2241,7 +2269,7 @@ "deployedBytecode": "0x60806040523661000b57005b600080357fffffffff000000000000000000000000000000000000000000000000000000001681527fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c6020819052604090912054819073ffffffffffffffffffffffffffffffffffffffff16806100e3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820181905260248201527f4469616d6f6e643a2046756e6374696f6e20646f6573206e6f7420657869737460448201526064015b60405180910390fd5b3660008037600080366000845af43d6000803e808015610102573d6000f35b3d6000fd5b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c132080547fffffffffffffffffffffffff0000000000000000000000000000000000000000811673ffffffffffffffffffffffffffffffffffffffff8481169182179093556040517fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c939092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b60005b83518110156103ba5760008482815181106101e1576101e1611657565b60200260200101516020015190506000600281111561020257610202611686565b81600281111561021457610214611686565b14156102635761025e85838151811061022f5761022f611657565b60200260200101516000015186848151811061024d5761024d611657565b6020026020010151604001516106be565b6103a7565b600181600281111561027757610277611686565b14156102c15761025e85838151811061029257610292611657565b6020026020010151600001518684815181106102b0576102b0611657565b602002602001015160400151610a71565b60028160028111156102d5576102d5611686565b141561031f5761025e8583815181106102f0576102f0611657565b60200260200101516000015186848151811061030e5761030e611657565b602002602001015160400151610e2e565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602760248201527f4c69624469616d6f6e644375743a20496e636f7272656374204661636574437560448201527f74416374696f6e0000000000000000000000000000000000000000000000000060648201526084016100da565b50806103b2816116e4565b9150506101c4565b507f8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb6738383836040516103ee93929190611793565b60405180910390a16104008282610405565b505050565b73ffffffffffffffffffffffffffffffffffffffff82166104b3578051156104af576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603c60248201527f4c69624469616d6f6e644375743a205f696e697420697320616464726573732860448201527f3029206275745f63616c6c64617461206973206e6f7420656d7074790000000060648201526084016100da565b5050565b6000815111610544576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603d60248201527f4c69624469616d6f6e644375743a205f63616c6c6461746120697320656d707460448201527f7920627574205f696e6974206973206e6f74206164647265737328302900000060648201526084016100da565b73ffffffffffffffffffffffffffffffffffffffff8216301461058357610583826040518060600160405280602881526020016119a46028913961101b565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516105ab91906118fb565b600060405180830381855af49150503d80600081146105e6576040519150601f19603f3d011682016040523d82523d6000602084013e6105eb565b606091505b5091509150816106b85780511561063057806040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100da9190611917565b6040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f4c69624469616d6f6e644375743a205f696e69742066756e6374696f6e20726560448201527f766572746564000000000000000000000000000000000000000000000000000060648201526084016100da565b50505050565b600081511161074f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f2063757400000000000000000000000000000000000000000060648201526084016100da565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c73ffffffffffffffffffffffffffffffffffffffff8316610813576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201527f652061646472657373283029000000000000000000000000000000000000000060648201526084016100da565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001820160205260409020546bffffffffffffffffffffffff8116610858576108588285611056565b60005b8351811015610a6a57600084828151811061087857610878611657565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529186905260409091205490915073ffffffffffffffffffffffffffffffffffffffff16801561095d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603560248201527f4c69624469616d6f6e644375743a2043616e2774206164642066756e6374696f60448201527f6e207468617420616c726561647920657869737473000000000000000000000060648201526084016100da565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260208781526040808320805473ffffffffffffffffffffffffffffffffffffffff908116740100000000000000000000000000000000000000006bffffffffffffffffffffffff8c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281547fffffffffffffffffffffffff00000000000000000000000000000000000000001617905583610a5281611931565b94505050508080610a62906116e4565b91505061085b565b5050505050565b6000815111610b02576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f2063757400000000000000000000000000000000000000000060648201526084016100da565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c73ffffffffffffffffffffffffffffffffffffffff8316610bc6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602c60248201527f4c69624469616d6f6e644375743a204164642066616365742063616e2774206260448201527f652061646472657373283029000000000000000000000000000000000000000060648201526084016100da565b73ffffffffffffffffffffffffffffffffffffffff831660009081526001820160205260409020546bffffffffffffffffffffffff8116610c0b57610c0b8285611056565b60005b8351811015610a6a576000848281518110610c2b57610c2b611657565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529186905260409091205490915073ffffffffffffffffffffffffffffffffffffffff908116908716811415610d16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603860248201527f4c69624469616d6f6e644375743a2043616e2774207265706c6163652066756e60448201527f6374696f6e20776974682073616d652066756e6374696f6e000000000000000060648201526084016100da565b610d218582846110e5565b7fffffffff000000000000000000000000000000000000000000000000000000008216600081815260208781526040808320805473ffffffffffffffffffffffffffffffffffffffff908116740100000000000000000000000000000000000000006bffffffffffffffffffffffff8c16021782558c168085526001808c0185529285208054938401815585528385206008840401805463ffffffff60079095166004026101000a948502191660e08a901c94909402939093179092559390925287905281547fffffffffffffffffffffffff00000000000000000000000000000000000000001617905583610e1681611931565b94505050508080610e26906116e4565b915050610c0e565b6000815111610ebf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602b60248201527f4c69624469616d6f6e644375743a204e6f2073656c6563746f727320696e206660448201527f6163657420746f2063757400000000000000000000000000000000000000000060648201526084016100da565b7fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c73ffffffffffffffffffffffffffffffffffffffff831615610f84576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603660248201527f4c69624469616d6f6e644375743a2052656d6f7665206661636574206164647260448201527f657373206d75737420626520616464726573732830290000000000000000000060648201526084016100da565b60005b82518110156106b8576000838281518110610fa457610fa4611657565b6020908102919091018101517fffffffff00000000000000000000000000000000000000000000000000000000811660009081529185905260409091205490915073ffffffffffffffffffffffffffffffffffffffff166110068482846110e5565b50508080611013906116e4565b915050610f87565b813b81816106b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016100da9190611917565b611078816040518060600160405280602481526020016119cc6024913961101b565b60028201805473ffffffffffffffffffffffffffffffffffffffff90921660008181526001948501602090815260408220860185905594840183559182529290200180547fffffffffffffffffffffffff0000000000000000000000000000000000000000169091179055565b73ffffffffffffffffffffffffffffffffffffffff8216611188576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152603760248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f76652066756e6360448201527f74696f6e207468617420646f65736e277420657869737400000000000000000060648201526084016100da565b73ffffffffffffffffffffffffffffffffffffffff821630141561122e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602e60248201527f4c69624469616d6f6e644375743a2043616e27742072656d6f766520696d6d7560448201527f7461626c652066756e6374696f6e00000000000000000000000000000000000060648201526084016100da565b7fffffffff0000000000000000000000000000000000000000000000000000000081166000908152602084815260408083205473ffffffffffffffffffffffffffffffffffffffff86168452600180880190935290832054740100000000000000000000000000000000000000009091046bffffffffffffffffffffffff1692916112b89161195d565b90508082146113ff5773ffffffffffffffffffffffffffffffffffffffff8416600090815260018601602052604081208054839081106112fa576112fa611657565b6000918252602080832060088304015473ffffffffffffffffffffffffffffffffffffffff8916845260018a019091526040909220805460079092166004026101000a90920460e01b92508291908590811061135857611358611657565b600091825260208083206008830401805463ffffffff60079094166004026101000a938402191660e09590951c929092029390931790557fffffffff0000000000000000000000000000000000000000000000000000000092909216825286905260409020805473ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000006bffffffffffffffffffffffff8516021790555b73ffffffffffffffffffffffffffffffffffffffff84166000908152600186016020526040902080548061143557611435611974565b6000828152602080822060087fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90940193840401805463ffffffff600460078716026101000a0219169055919092557fffffffff0000000000000000000000000000000000000000000000000000000085168252869052604081205580610a6a5760028501546000906114ca9060019061195d565b73ffffffffffffffffffffffffffffffffffffffff861660009081526001808901602052604090912001549091508082146115b857600087600201838154811061151657611516611657565b60009182526020909120015460028901805473ffffffffffffffffffffffffffffffffffffffff909216925082918490811061155457611554611657565b600091825260208083209190910180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff948516179055929091168152600189810190925260409020018190555b866002018054806115cb576115cb611974565b6000828152602080822083017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff90810180547fffffffffffffffffffffffff000000000000000000000000000000000000000016905590920190925573ffffffffffffffffffffffffffffffffffffffff88168252600189810190915260408220015550505050505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff821415611716576117166116b5565b5060010190565b60005b83811015611738578181015183820152602001611720565b838111156106b85750506000910152565b6000815180845261176181602086016020860161171d565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b60006060808301818452808751808352608092508286019150828160051b8701016020808b0160005b848110156118be577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff808a8503018652815188850173ffffffffffffffffffffffffffffffffffffffff82511686528482015160038110611845577f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b868601526040918201519186018a905281519081905290840190600090898701905b808310156118a95783517fffffffff00000000000000000000000000000000000000000000000000000000168252928601926001929092019190860190611867565b509785019795505050908201906001016117bc565b505073ffffffffffffffffffffffffffffffffffffffff8a169088015286810360408801526118ed8189611749565b9a9950505050505050505050565b6000825161190d81846020870161171d565b9190910192915050565b60208152600061192a6020830184611749565b9392505050565b60006bffffffffffffffffffffffff80831681811415611953576119536116b5565b6001019392505050565b60008282101561196f5761196f6116b5565b500390565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fdfe4c69624469616d6f6e644375743a205f696e6974206164647265737320686173206e6f20636f64654c69624469616d6f6e644375743a204e657720666163657420686173206e6f20636f6465a26469706673582212202b18a533b03703e1326000cf2f36b1c6ec631cff163a752d939e5ee79ad2cde364736f6c634300080a0033", "facets": [ { - "facetAddress": "0x5CA66f7E40F28e0905DD641E7bF4Ec6930656636", + "facetAddress": "0xA08B01a4A170d6167433ce322C67a9f9C5b28557", "functionSelectors": [ "0x0511f2ec", "0x55b21ba2", @@ -2249,7 +2277,7 @@ ] }, { - "facetAddress": "0xa5D2340a71B0b10b82CB879B9F9a31d4C4595102", + "facetAddress": "0xf375135d20D8098287a3D6961BDDF78062486551", "functionSelectors": [ "0x6a5ac74c", "0xa4110dbe", @@ -2260,14 +2288,14 @@ ] }, { - "facetAddress": "0x7C488A0a555211A6300B8BE9A1937F31d41eFA2e", + "facetAddress": "0x74eCB927aA45de25fB4777E398A2e5514C2a681B", "functionSelectors": [ "0xebad22f8", "0x97b03b53" ] }, { - "facetAddress": "0x89f887186e23B04A98e2f1D6aD5E8Ee300d11359", + "facetAddress": "0x67E8A916284558989F2d85C4674F640eC2F1e283", "functionSelectors": [ "0x6e9960c3", "0x42e10bc8", @@ -2288,14 +2316,16 @@ ] }, { - "facetAddress": "0xdd76D7b1720b8Ee74218a28Eb6D54A52502d637b", + "facetAddress": "0x941B0319c0B1090810fbA842b372E9F0795B2A96", "functionSelectors": [ + "0x682e4e5f", "0x6430ae6a", "0x274f255e", "0xa828c479", "0xf2f65960", "0x8a5b5690", "0x75829def", + "0x3a805a3c", "0x2d80caa5" ] }, @@ -2327,8 +2357,8 @@ "contract": "AppStorageInit", "methodName": "init", "args": [ - "0x2BC9019e6d9e6a26D7D8d8CDDa4e5dE9B787D7bb", - "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", + "0x82155Ab6b6c1113CFb352c7573B010a88f5974bD", + "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", "100", "10000", 86400, diff --git a/deployments/baseGoerli/Sarcophagus_V2_DiamondProxy.json b/deployments/arbitrum/Sarcophagus_V2_DiamondProxy.json similarity index 96% rename from deployments/baseGoerli/Sarcophagus_V2_DiamondProxy.json rename to deployments/arbitrum/Sarcophagus_V2_DiamondProxy.json index 735e602..59397ec 100644 --- a/deployments/baseGoerli/Sarcophagus_V2_DiamondProxy.json +++ b/deployments/arbitrum/Sarcophagus_V2_DiamondProxy.json @@ -1,5 +1,5 @@ { - "address": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", + "address": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", "abi": [ { "inputs": [ @@ -1656,7 +1656,7 @@ }, { "inputs": [], - "name": "CallerIsNotAdmin", + "name": "CallerIsNotAdminOrOwner", "type": "error" }, { @@ -1772,6 +1772,19 @@ "name": "WithdrawProtocolFees", "type": "event" }, + { + "inputs": [], + "name": "getDiamondOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, { "inputs": [ { @@ -1850,6 +1863,19 @@ "stateMutability": "nonpayable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferDiamondOwner", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, { "inputs": [ { @@ -2086,54 +2112,54 @@ "type": "function" } ], - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", "receipt": { "to": null, - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", - "transactionIndex": 2, - "gasUsed": "3634494", - "logsBloom": "0x00000000000008000000000000000000000000000000000000800400000000000000000000000000000000040000000000000000000010000000000000000000000000000000000000000000000000000001000001000000000800000000000000000000020000000000000000000800000000000000040000000000000000400020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020008000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2a8a7c6082186fea6f7726e3935d85c9ef8d63015eb2f7da60013705fbc90959", - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", + "contractAddress": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", + "transactionIndex": 7, + "gasUsed": "31879810", + "logsBloom": "0x00000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000401000001000000000800000000000000000000021000000000000000000800000000000000000000000000000000400020000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000000010020000000000000000000000000000000000000000000000000000000080000000000", + "blockHash": "0x7df0c6ddae4e885b619eb6cf2f4603f54f5a284cdf4c92c23c13510677033f3b", + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", "logs": [ { - "transactionIndex": 2, - "blockNumber": 9669994, - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", - "address": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", + "transactionIndex": 7, + "blockNumber": 152627007, + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", + "address": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", "topics": [ "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", "0x0000000000000000000000000000000000000000000000000000000000000000", - "0x000000000000000000000000b38c80e2263a060bd077ece9b2c81a7a18ec74b5" + "0x000000000000000000000000ae9b102741a1b60c221e39cd9526ab38c9865ab3" ], "data": "0x", - "logIndex": 0, - "blockHash": "0x2a8a7c6082186fea6f7726e3935d85c9ef8d63015eb2f7da60013705fbc90959" + "logIndex": 30, + "blockHash": "0x7df0c6ddae4e885b619eb6cf2f4603f54f5a284cdf4c92c23c13510677033f3b" }, { - "transactionIndex": 2, - "blockNumber": 9669994, - "transactionHash": "0xd13ce7f0b580dad5b781bdf1be1486eae10b159d85229ff6335ecc1d35e0ef38", - "address": "0xB933926f50b33797d0fa1DaEe65D5830224E53E1", + "transactionIndex": 7, + "blockNumber": 152627007, + "transactionHash": "0x7b4c75817dbdb89fbf6ba4048c5f750c670e701159033665d506db2423c67486", + "address": "0xc1984df3e3ddc1DC24d54179CCD5537e290C7E9c", "topics": [ "0x8faa70878671ccd212d20771b795c50af8fd3ff6cf27f4bde57e5d4de0aeb673" ], - "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ac00000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e0000000000000000000000000000000000000000000000000000000000000066000000000000000000000000000000000000000000000000000000000000007c0000000000000000000000000000000000000000000000000000000000000086000000000000000000000000000000000000000000000000000000000000009200000000000000000000000005ca66f7e40f28e0905dd641e7bf4ec69306566360000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000030511f2ec0000000000000000000000000000000000000000000000000000000055b21ba200000000000000000000000000000000000000000000000000000000ab7d796900000000000000000000000000000000000000000000000000000000000000000000000000000000a5d2340a71b0b10b82cb879b9f9a31d4c45951020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000066a5ac74c00000000000000000000000000000000000000000000000000000000a4110dbe00000000000000000000000000000000000000000000000000000000a4d9eb430000000000000000000000000000000000000000000000000000000095b22c7200000000000000000000000000000000000000000000000000000000364e080100000000000000000000000000000000000000000000000000000000c885bc58000000000000000000000000000000000000000000000000000000000000000000000000000000007c488a0a555211a6300b8be9a1937f31d41efa2e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002ebad22f80000000000000000000000000000000000000000000000000000000097b03b530000000000000000000000000000000000000000000000000000000000000000000000000000000089f887186e23b04a98e2f1d6ad5e8ee300d113590000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000106e9960c30000000000000000000000000000000000000000000000000000000042e10bc80000000000000000000000000000000000000000000000000000000057babbaf000000000000000000000000000000000000000000000000000000003fbb893000000000000000000000000000000000000000000000000000000000a9328dcc0000000000000000000000000000000000000000000000000000000087927ce600000000000000000000000000000000000000000000000000000000dcfcb9010000000000000000000000000000000000000000000000000000000031baea67000000000000000000000000000000000000000000000000000000007aa9fd2f000000000000000000000000000000000000000000000000000000008fbd55d200000000000000000000000000000000000000000000000000000000dbd18388000000000000000000000000000000000000000000000000000000009fdaded10000000000000000000000000000000000000000000000000000000079ee54f700000000000000000000000000000000000000000000000000000000de116f0600000000000000000000000000000000000000000000000000000000dc231f43000000000000000000000000000000000000000000000000000000009c54563900000000000000000000000000000000000000000000000000000000000000000000000000000000dd76d7b1720b8ee74218a28eb6d54a52502d637b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000076430ae6a00000000000000000000000000000000000000000000000000000000274f255e00000000000000000000000000000000000000000000000000000000a828c47900000000000000000000000000000000000000000000000000000000f2f65960000000000000000000000000000000000000000000000000000000008a5b56900000000000000000000000000000000000000000000000000000000075829def000000000000000000000000000000000000000000000000000000002d80caa500000000000000000000000000000000000000000000000000000000000000000000000000000000429dbde7913c0ed51e4b21163760b92ee66ff5f50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000ad6e96ff641af53cce4205dafecb8e3acd0490e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b000000000000000000000000000000000000000000000000000000000000000000000000000000003bcf4185443a339517ad4e580067f178d1b68e1d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "logIndex": 1, - "blockHash": "0x2a8a7c6082186fea6f7726e3935d85c9ef8d63015eb2f7da60013705fbc90959" + "data": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000b000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000001e0000000000000000000000000000000000000000000000000000000000000032000000000000000000000000000000000000000000000000000000000000003e00000000000000000000000000000000000000000000000000000000000000660000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000960000000000000000000000000a08b01a4a170d6167433ce322c67a9f9c5b285570000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000030511f2ec0000000000000000000000000000000000000000000000000000000055b21ba200000000000000000000000000000000000000000000000000000000ab7d796900000000000000000000000000000000000000000000000000000000000000000000000000000000f375135d20d8098287a3d6961bddf780624865510000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000066a5ac74c00000000000000000000000000000000000000000000000000000000a4110dbe00000000000000000000000000000000000000000000000000000000a4d9eb430000000000000000000000000000000000000000000000000000000095b22c7200000000000000000000000000000000000000000000000000000000364e080100000000000000000000000000000000000000000000000000000000c885bc580000000000000000000000000000000000000000000000000000000000000000000000000000000074ecb927aa45de25fb4777e398a2e5514c2a681b000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000002ebad22f80000000000000000000000000000000000000000000000000000000097b03b530000000000000000000000000000000000000000000000000000000000000000000000000000000067e8a916284558989f2d85c4674f640ec2f1e2830000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000106e9960c30000000000000000000000000000000000000000000000000000000042e10bc80000000000000000000000000000000000000000000000000000000057babbaf000000000000000000000000000000000000000000000000000000003fbb893000000000000000000000000000000000000000000000000000000000a9328dcc0000000000000000000000000000000000000000000000000000000087927ce600000000000000000000000000000000000000000000000000000000dcfcb9010000000000000000000000000000000000000000000000000000000031baea67000000000000000000000000000000000000000000000000000000007aa9fd2f000000000000000000000000000000000000000000000000000000008fbd55d200000000000000000000000000000000000000000000000000000000dbd18388000000000000000000000000000000000000000000000000000000009fdaded10000000000000000000000000000000000000000000000000000000079ee54f700000000000000000000000000000000000000000000000000000000de116f0600000000000000000000000000000000000000000000000000000000dc231f43000000000000000000000000000000000000000000000000000000009c54563900000000000000000000000000000000000000000000000000000000000000000000000000000000941b0319c0b1090810fba842b372e9f0795b2a96000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000009682e4e5f000000000000000000000000000000000000000000000000000000006430ae6a00000000000000000000000000000000000000000000000000000000274f255e00000000000000000000000000000000000000000000000000000000a828c47900000000000000000000000000000000000000000000000000000000f2f65960000000000000000000000000000000000000000000000000000000008a5b56900000000000000000000000000000000000000000000000000000000075829def000000000000000000000000000000000000000000000000000000003a805a3c000000000000000000000000000000000000000000000000000000002d80caa500000000000000000000000000000000000000000000000000000000000000000000000000000000429dbde7913c0ed51e4b21163760b92ee66ff5f50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000011f931c1c00000000000000000000000000000000000000000000000000000000000000000000000000000000ad6e96ff641af53cce4205dafecb8e3acd0490e30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000028da5cb5b00000000000000000000000000000000000000000000000000000000f2fde38b000000000000000000000000000000000000000000000000000000000000000000000000000000003bcf4185443a339517ad4e580067f178d1b68e1d000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000600000000000000000000000000000000000000000000000000000000000000005cdffacc60000000000000000000000000000000000000000000000000000000052ef6b2c00000000000000000000000000000000000000000000000000000000adfca15e000000000000000000000000000000000000000000000000000000007a0ed6270000000000000000000000000000000000000000000000000000000001ffc9a7000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "logIndex": 31, + "blockHash": "0x7df0c6ddae4e885b619eb6cf2f4603f54f5a284cdf4c92c23c13510677033f3b" } ], - "blockNumber": 9669994, - "cumulativeGasUsed": "3732792", + "blockNumber": 152627007, + "cumulativeGasUsed": "40235954", "status": 1, "byzantium": true }, "args": [ - "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", + "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", [ { - "facetAddress": "0x5CA66f7E40F28e0905DD641E7bF4Ec6930656636", + "facetAddress": "0xA08B01a4A170d6167433ce322C67a9f9C5b28557", "functionSelectors": [ "0x0511f2ec", "0x55b21ba2", @@ -2142,7 +2168,7 @@ "action": 0 }, { - "facetAddress": "0xa5D2340a71B0b10b82CB879B9F9a31d4C4595102", + "facetAddress": "0xf375135d20D8098287a3D6961BDDF78062486551", "functionSelectors": [ "0x6a5ac74c", "0xa4110dbe", @@ -2154,7 +2180,7 @@ "action": 0 }, { - "facetAddress": "0x7C488A0a555211A6300B8BE9A1937F31d41eFA2e", + "facetAddress": "0x74eCB927aA45de25fB4777E398A2e5514C2a681B", "functionSelectors": [ "0xebad22f8", "0x97b03b53" @@ -2162,7 +2188,7 @@ "action": 0 }, { - "facetAddress": "0x89f887186e23B04A98e2f1D6aD5E8Ee300d11359", + "facetAddress": "0x67E8A916284558989F2d85C4674F640eC2F1e283", "functionSelectors": [ "0x6e9960c3", "0x42e10bc8", @@ -2184,14 +2210,16 @@ "action": 0 }, { - "facetAddress": "0xdd76D7b1720b8Ee74218a28Eb6D54A52502d637b", + "facetAddress": "0x941B0319c0B1090810fbA842b372E9F0795B2A96", "functionSelectors": [ + "0x682e4e5f", "0x6430ae6a", "0x274f255e", "0xa828c479", "0xf2f65960", "0x8a5b5690", "0x75829def", + "0x3a805a3c", "0x2d80caa5" ], "action": 0 @@ -2229,8 +2257,8 @@ "initData": "0x2a84809100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000148e2b093000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" }, { - "initContract": "0xe14E811e93B36a5Cb0D74102919D19748cfB14CA", - "initData": "0xb36a27e70000000000000000000000002bc9019e6d9e6a26d7d8d8cdda4e5de9b787d7bb000000000000000000000000b38c80e2263a060bd077ece9b2c81a7a18ec74b50000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000e10" + "initContract": "0x8B54aF0d46B57D219e5f41F78ad7569E28eaE793", + "initData": "0xb36a27e700000000000000000000000082155ab6b6c1113cfb352c7573b010a88f5974bd000000000000000000000000ae9b102741a1b60c221e39cd9526ab38c9865ab30000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000271000000000000000000000000000000000000000000000000000000000000151800000000000000000000000000000000000000000000000000000000000093a800000000000000000000000000000000000000000000000000000000000000e10" } ] ], diff --git a/deployments/arbitrum/ThirdPartyFacet.json b/deployments/arbitrum/ThirdPartyFacet.json new file mode 100644 index 0000000..41c2098 --- /dev/null +++ b/deployments/arbitrum/ThirdPartyFacet.json @@ -0,0 +1,473 @@ +{ + "address": "0x74eCB927aA45de25fB4777E398A2e5514C2a681B", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "archaeologist", + "type": "address" + } + ], + "name": "ArchaeologistNotOnSarcophagus", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "signatures", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "publicKeys", + "type": "uint256" + } + ], + "name": "DifferentNumberOfSignaturesAndPublicKeys", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "embalmerClaimWindowEnd", + "type": "uint256" + } + ], + "name": "EmbalmerClaimWindowPassed", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "paymentAddress", + "type": "address" + }, + { + "internalType": "bytes", + "name": "publicKey", + "type": "bytes" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "internalType": "struct LibTypes.Signature", + "name": "signature", + "type": "tuple" + } + ], + "name": "InvalidAccusalSignature", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "resurrectionTime", + "type": "uint256" + } + ], + "name": "ResurrectionTimeInPast", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusAlreadyCleaned", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusCompromised", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusDoesNotExist", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "SarcophagusInactive", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "senderAddress", + "type": "address" + } + ], + "name": "SenderNotEmbalmerOrAdmin", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "embalmerClaimWindowEnd", + "type": "uint256" + } + ], + "name": "TooEarlyForAdminClean", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "currentTime", + "type": "uint256" + }, + { + "internalType": "uint256", + "name": "publishDeadline", + "type": "uint256" + } + ], + "name": "TooEarlyForClean", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "accuser", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalSlashedBondDistributed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "totalDiggingFeesDistributed", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address[]", + "name": "accusedArchAddresses", + "type": "address[]" + } + ], + "name": "AccuseArchaeologist", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "cleaner", + "type": "address" + } + ], + "name": "Clean", + "type": "event" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + }, + { + "internalType": "bytes[]", + "name": "publicKeys", + "type": "bytes[]" + }, + { + "components": [ + { + "internalType": "uint8", + "name": "v", + "type": "uint8" + }, + { + "internalType": "bytes32", + "name": "r", + "type": "bytes32" + }, + { + "internalType": "bytes32", + "name": "s", + "type": "bytes32" + } + ], + "internalType": "struct LibTypes.Signature[]", + "name": "signatures", + "type": "tuple[]" + }, + { + "internalType": "address", + "name": "paymentAddress", + "type": "address" + } + ], + "name": "accuse", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "sarcoId", + "type": "bytes32" + } + ], + "name": "clean", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } + ], + "transactionHash": "0x066b8898a667f751bb4e853070f9a0c9ac26181fc045041bf6f7b83dc9aada8c", + "receipt": { + "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", + "contractAddress": null, + "transactionIndex": 2, + "gasUsed": "21096863", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x06fe46a5944080089d65319b377ee47e8efc9317afb8c9228bc8b39ff05b7346", + "transactionHash": "0x066b8898a667f751bb4e853070f9a0c9ac26181fc045041bf6f7b83dc9aada8c", + "logs": [], + "blockNumber": 152626958, + "cumulativeGasUsed": "21949018", + "status": 1, + "byzantium": true + }, + "args": [], + "numDeployments": 1, + "solcInputHash": "69b6ccc89b7eaa4e346529a9a529edba", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistNotOnSarcophagus\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"signatures\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"publicKeys\",\"type\":\"uint256\"}],\"name\":\"DifferentNumberOfSignaturesAndPublicKeys\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindowEnd\",\"type\":\"uint256\"}],\"name\":\"EmbalmerClaimWindowPassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"paymentAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct LibTypes.Signature\",\"name\":\"signature\",\"type\":\"tuple\"}],\"name\":\"InvalidAccusalSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeInPast\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusAlreadyCleaned\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusCompromised\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"SenderNotEmbalmerOrAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindowEnd\",\"type\":\"uint256\"}],\"name\":\"TooEarlyForAdminClean\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"publishDeadline\",\"type\":\"uint256\"}],\"name\":\"TooEarlyForClean\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"accuser\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSlashedBondDistributed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDiggingFeesDistributed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"accusedArchAddresses\",\"type\":\"address[]\"}],\"name\":\"AccuseArchaeologist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"cleaner\",\"type\":\"address\"}],\"name\":\"Clean\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"publicKeys\",\"type\":\"bytes[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct LibTypes.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"paymentAddress\",\"type\":\"address\"}],\"name\":\"accuse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"clean\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)\":[{\"params\":{\"publicKeys\":\"the number of public keys passed into the accuse call\",\"signatures\":\"the number of signatures passed into the accuse call\"}}],\"EmbalmerClaimWindowPassed(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed clean attempt\",\"embalmerClaimWindowEnd\":\"Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\"}}],\"InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))\":[{\"params\":{\"paymentAddress\":\"payment address that should have been signed\",\"publicKey\":\"publicKey that should be derived from signing key\",\"sarcoId\":\"that should have been signed\",\"signature\":\"invalid signature\"}}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed accuse attempt\",\"resurrectionTime\":\"Resurrection timestamp which has already passed\"}}],\"SarcophagusAlreadyCleaned(bytes32)\":[{\"params\":{\"sarcoId\":\"ID of sarcophagus archaeologist has attempted to publish a private key on\"}}],\"SenderNotEmbalmerOrAdmin(address)\":[{\"params\":{\"senderAddress\":\"Address of sender\"}}],\"TooEarlyForAdminClean(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed clean attempt\",\"embalmerClaimWindowEnd\":\"Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\"}}],\"TooEarlyForClean(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed clean attempt\",\"publishDeadline\":\"Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\"}}]},\"kind\":\"dev\",\"methods\":{\"accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)\":{\"params\":{\"paymentAddress\":\"the address to which rewards should be sent if successful\",\"publicKeys\":\"an array of public keys corresponding to leaked private keys - order must match order of signatures\",\"sarcoId\":\"The identifier of the sarcophagus having leaked private keys\",\"signatures\":\"an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\"}},\"clean(bytes32)\":{\"params\":{\"sarcoId\":\"The identifier of the sarcophagus to clean\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)\":[{\"notice\":\"Emitted when accuse is called with an unequal numbers of public keys and signatures\"}],\"EmbalmerClaimWindowPassed(uint256,uint256)\":[{\"notice\":\"Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\"}],\"InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))\":[{\"notice\":\"Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\"}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"notice\":\"Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\"}],\"SarcophagusAlreadyCleaned(bytes32)\":[{\"notice\":\"Clean has been called on a sarcophagus that has already been cleaned\"}],\"SenderNotEmbalmerOrAdmin(address)\":[{\"notice\":\"Clean has been called by someone other than the admin or embalmer of the sarcophagus\"}],\"TooEarlyForAdminClean(uint256,uint256)\":[{\"notice\":\"Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\"}],\"TooEarlyForClean(uint256,uint256)\":[{\"notice\":\"Clean has been called before the deadline for archaeologists to publish private keys has passed\"}]},\"kind\":\"user\",\"methods\":{\"accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)\":{\"notice\":\"Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id and payment address generated with the leaked private keys If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus state will be updated to Accused and bonds for all remaining unaccused archaeologists will be returned\"},\"clean(bytes32)\":{\"notice\":\"If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod, their locked bonds and diggingFees may be claimed by either the embalmer or the admin embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will be able to claim remaining locked bond and diggingFees\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ThirdPartyFacet.sol\":\"ThirdPartyFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\n\\ncontract EmbalmerFacet {\\n /// @notice Emitted when a sarcophagus is created\\n /// @param sarcoId Id of the new sarcophagus\\n /// @param name Name of the new sarcophagus\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\n /// @param embalmer Address of embalmer\\n /// @param recipient Address of recipient\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\n event CreateSarcophagus(\\n bytes32 indexed sarcoId,\\n string name,\\n uint256 resurrectionTime,\\n uint256 creationTime,\\n address indexed embalmer,\\n address indexed recipient,\\n address[] cursedArchaeologists,\\n uint256 totalDiggingFees,\\n string arweaveTxId\\n );\\n\\n /// @notice Emitted when a sarcophagus is rewrapped\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\n event RewrapSarcophagus(\\n bytes32 indexed sarcoId,\\n uint256 resurrectionTime,\\n uint256 totalDiggingFees,\\n uint256 rewrapSarcophagusProtocolFees\\n );\\n\\n /// @notice Emitted when a sarcophagus is buried\\n /// @param sarcoId Id of sarcophagus that was buried\\n event BurySarcophagus(bytes32 indexed sarcoId);\\n\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\n struct SarcophagusParams {\\n string name;\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\n uint256 maximumRewrapInterval;\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\n uint256 maximumResurrectionTime;\\n address recipientAddress;\\n uint256 resurrectionTime;\\n uint8 threshold;\\n uint256 creationTime;\\n }\\n\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\n struct CurseParams {\\n bytes publicKey;\\n address archAddress;\\n uint256 diggingFeePerSecond;\\n uint256 curseFee;\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\n /// @param sarcoId Id that is already in use\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\n /// @param currentTime Timestamp of the failed create attempt\\n /// @param creationTime Time when the sarcophagus parameters were created\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\n error SarcophagusParametersExpired(\\n uint256 currentTime,\\n uint256 creationTime,\\n uint256 creationDeadline\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\n error NoArchaeologistsProvided();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\n error ThresholdCannotBeZero();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\n uint8 threshold,\\n uint256 totalNumberOfArchaeologists\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\n /// @param currentTime Timestamp of the failed rewrap attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\n /// @param publicKey the duplicated public key\\n error DuplicatePublicKey(bytes publicKey);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\n error ResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\n error ResurrectionTimePastMaxResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 maxResurrectionTime\\n );\\n\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\n\\n error NewResurrectionTimeIsZero();\\n\\n error NewResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 previousResurrectionTime\\n );\\n\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\n /// of the sarcophagus until its resurrection time.\\n ///\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\n /// - `creationTime` of sarcophagus\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\n ///\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param sarcophagusParams params to set on sarcophagus being created\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\n function createSarcophagus(\\n bytes32 sarcoId,\\n SarcophagusParams calldata sarcophagusParams,\\n CurseParams[] calldata selectedArchaeologists,\\n string calldata arweaveTxId\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n // Confirm that sarcophagus with supplied id doesn't already exist\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\n revert SarcophagusAlreadyExists(sarcoId);\\n }\\n\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\n // off by its cursed archaeologists.\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\n revert SarcophagusParametersExpired(\\n block.timestamp,\\n sarcophagusParams.creationTime,\\n sarcophagusParams.creationTime + s.expirationThreshold\\n );\\n }\\n\\n // Confirm that resurrection time is in the future\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\n }\\n\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\n if (\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\n sarcophagusParams.resurrectionTime\\n ) {\\n revert ResurrectionTimeTooFarInFuture(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumRewrapInterval,\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the resurrection time is less than the max resurrection time\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumResurrectionTime\\n );\\n }\\n\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // track total digging fees due upon creation of sarcophagus\\n uint256 totalDiggingFees;\\n\\n {\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\n // Validate archaeologist and threshold lengths\\n if (nSelectedArchs == 0) {\\n revert NoArchaeologistsProvided();\\n }\\n\\n if (sarcophagusParams.threshold == 0) {\\n revert ThresholdCannotBeZero();\\n }\\n\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\n // used to distribute keyshares among archaeologists\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\n sarcophagusParams.threshold,\\n nSelectedArchs\\n );\\n }\\n\\n // create the sarcophagus\\n sarcophagus.name = sarcophagusParams.name;\\n sarcophagus.threshold = sarcophagusParams.threshold;\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\n sarcophagus.arweaveTxId = arweaveTxId;\\n sarcophagus.embalmerAddress = msg.sender;\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\n\\n for (uint256 i; i < nSelectedArchs; ) {\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\n\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\n if (\\n sarcophagus\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\n .publicKey\\n .length != 0\\n ) {\\n revert ArchaeologistListContainsDuplicate(\\n selectedArchaeologists[i].archAddress\\n );\\n }\\n\\n // Confirm archaeologist is not re-using a key pair\\n if (\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\n address(0)\\n ) {\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\n }\\n\\n LibUtils.verifyArchaeologistSignature(\\n sarcophagusParams.maximumRewrapInterval,\\n sarcophagusParams.maximumResurrectionTime,\\n sarcophagusParams.creationTime,\\n selectedArchaeologists[i]\\n );\\n\\n // Curse the archaeologist on this sarcophagus\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\n sarcoId,\\n selectedArchaeologists[i],\\n i\\n );\\n\\n totalDiggingFees += diggingFeesDue;\\n\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\n s.publicKeyToArchaeologistAddress[\\n selectedArchaeologists[i].publicKey\\n ] = selectedArchaeologists[i].archAddress;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n s.totalProtocolFees += protocolFees;\\n s.sarcoToken.transferFrom(\\n msg.sender,\\n address(this),\\n totalDiggingFees + protocolFees\\n );\\n }\\n emit CreateSarcophagus(\\n sarcoId,\\n sarcophagusParams.name,\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.creationTime,\\n msg.sender,\\n sarcophagusParams.recipientAddress,\\n sarcophagus.cursedArchaeologistAddresses,\\n totalDiggingFees,\\n arweaveTxId\\n );\\n }\\n\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param resurrectionTime the new resurrection time\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n\\n // Confirm resurrection time has not yet passed\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time is in future\\n if (block.timestamp >= resurrectionTime) {\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\n revert NewResurrectionTimeTooFarInFuture(\\n resurrectionTime,\\n sarcophagus.maximumRewrapInterval,\\n block.timestamp + sarcophagus.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n resurrectionTime,\\n sarcophagus.maximumResurrectionTime\\n );\\n }\\n\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\n uint256 totalDiggingFees;\\n\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\n\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n if (!cursedArchaeologist.isAccused) {\\n // Previous digging fees calculation ignores curseFee\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (resurrectionTime - block.timestamp);\\n\\n // If the new digging fees are greater than the previous digging fees, we need to\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\n if (newDiggingFees > prevDiggingFees) {\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\n if (cursedBondIncrease > prevDiggingFees) {\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n resurrectionTime,\\n sarcophagus.resurrectionTime\\n );\\n }\\n\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond += cursedBondIncrease;\\n\\n // Rewards are now previous digging fees - difference\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\n } else if (newDiggingFees < prevDiggingFees) {\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // Decrease archaeologist's cursed bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond -= cursedBondDecrease;\\n\\n // Increase archaeologist's free bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .freeBond += cursedBondDecrease;\\n\\n // Rewards are equal to the previous digging fees\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n } else {\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n }\\n\\n // Add digging fees due for the new interval\\n totalDiggingFees += newDiggingFees;\\n\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n // Pay archaeologists the curse fee to their rewards\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n\\n // Add the protocol fee to the total protocol fees in storage\\n s.totalProtocolFees += protocolFees;\\n\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\n sarcophagus.resurrectionTime = resurrectionTime;\\n sarcophagus.previousRewrapTime = block.timestamp;\\n\\n if (!sarcophagus.isRewrapped) {\\n sarcophagus.isRewrapped = true;\\n }\\n\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\n\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\n }\\n\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n function burySarcophagus(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n // Confirm that the current resurrection time is in the future\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\n if (!cursedArchaeologist.isAccused) {\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Set resurrection time to infinity\\n sarcophagus.resurrectionTime = type(uint256).max;\\n\\n emit BurySarcophagus(sarcoId);\\n }\\n}\\n\",\"keccak256\":\"0x6f608191836cb34a89292cbad9d19962144f57439e8acade82a5a6ffaf8f248a\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\ncontract ThirdPartyFacet {\\n event AccuseArchaeologist(\\n bytes32 indexed sarcoId,\\n address indexed accuser,\\n uint256 totalSlashedBondDistributed,\\n uint256 totalDiggingFeesDistributed,\\n address[] accusedArchAddresses\\n );\\n\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\n\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\n\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\n\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\n /// @param senderAddress Address of sender\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\n\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\n /// @param currentTime Timestamp of the failed accuse attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\n /// @param signatures the number of signatures passed into the accuse call\\n /// @param publicKeys the number of public keys passed into the accuse call\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\n\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\n /// @param sarcoId that should have been signed\\n /// @param paymentAddress payment address that should have been signed\\n /// @param publicKey publicKey that should be derived from signing key\\n /// @param signature invalid signature\\n error InvalidAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes publicKey,\\n LibTypes.Signature signature\\n );\\n\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\n /// be able to claim remaining locked bond and diggingFees\\n /// @param sarcoId The identifier of the sarcophagus to clean\\n function clean(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer or admin\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not already been cleaned\\n if (sarcophagus.isCleaned) {\\n revert SarcophagusAlreadyCleaned(sarcoId);\\n }\\n\\n // Confirm that the resurrectionTime + gracePeriod have passed\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\n }\\n\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\n if (\\n msg.sender == sarcophagus.embalmerAddress &&\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert EmbalmerClaimWindowPassed(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // if sender is admin, confirm embalmerClaimWindow has passed\\n if (\\n msg.sender == LibDiamond.contractOwner() &&\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert TooEarlyForAdminClean(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\n uint256 totalDiggingFeesAndLockedBonds;\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\n\\n // Punish archaeologists that failed to publish their private key in time\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n if (!sarcophagus.isRewrapped) {\\n diggingFeesDue += cursedArchaeologist.curseFee;\\n }\\n\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\n\\n // slash the archaeologist's locked bond for the sarcophagus\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\n // this to the contract's protocol fees\\n if (msg.sender == sarcophagus.embalmerAddress) {\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\n } else {\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\n }\\n\\n sarcophagus.isCleaned = true;\\n emit Clean(sarcoId, msg.sender);\\n }\\n\\n /**\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\n * and payment address generated with the leaked private keys\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\n *\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\n * returned\\n *\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\n * @param paymentAddress the address to which rewards should be sent if successful\\n */\\n function accuse(\\n bytes32 sarcoId,\\n bytes[] calldata publicKeys,\\n LibTypes.Signature[] calldata signatures,\\n address paymentAddress\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // verify that current time is not past resurrection time\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n uint256 nSigs = signatures.length;\\n\\n if (nSigs != publicKeys.length) {\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\n }\\n\\n address[] memory accusedArchAddresses = new address[](nSigs);\\n\\n // track the combined locked bond across all archaeologists being accused in this call\\n uint256 totalCursedBond;\\n uint256 accusalCount;\\n for (uint256 i; i < nSigs; ) {\\n if (\\n !LibUtils.verifyAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n )\\n ) {\\n revert InvalidAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n );\\n }\\n\\n // look up the archaeologist responsible for the publicKey\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\n .cursedArchaeologists[accusedArchaeologistAddress];\\n\\n // verify the accused archaeologist is cursed on the sarcophagus\\n if (accusedArchaeologist.publicKey.length == 0) {\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\n }\\n\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\n if (accusedArchaeologist.isAccused) {\\n unchecked {\\n ++i;\\n }\\n continue;\\n }\\n\\n // mark the archaeologist on the sarcophagus as having been accused\\n accusedArchaeologist.isAccused = true;\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\n\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\n sarcophagus.cursedBondPercentage) / 10000;\\n\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\n if (!sarcophagus.isRewrapped) {\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\n }\\n\\n totalCursedBond += cursedBondDue;\\n\\n // Slash the offending archaeologists bond\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\n if (accusalCount == 0) {\\n return;\\n }\\n\\n {\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\n if (accusalCount >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n } else {\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\n uint256 totalAccusals;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n if (\\n sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n ++totalAccusals;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\n if (totalAccusals >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n }\\n }\\n\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\n // be returned to the remaining well behaved archaeologists\\n if (sarcophagus.isCompromised) {\\n // iterate through all archaeologist addresses on the sarcophagus\\n for (uint256 i; i < nCursedArchs; ) {\\n // if the archaeologist has never been accused, release their locked bond back to them\\n if (\\n !sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n LibBonds.freeArchaeologist(\\n sarcoId,\\n sarcophagus.cursedArchaeologistAddresses[i]\\n );\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\n s.sarcoToken.transfer(\\n sarcophagus.embalmerAddress,\\n totalDiggingFees + halfTotalCursedBond\\n );\\n\\n // transfer the other half of the cursed bond to the transaction caller\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\n\\n emit AccuseArchaeologist(\\n sarcoId,\\n msg.sender,\\n totalCursedBond,\\n totalDiggingFees,\\n accusedArchAddresses\\n );\\n }\\n}\\n\",\"keccak256\":\"0x6d493c3c0d5bd584f4432f4c559fd431cbff1f47f5587d7453ef918fe91190c2\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\n\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\nlibrary LibBonds {\\n /// @notice Bonds the archaeologist to a sarcophagus.\\n /// This does the following:\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\n ///\\n /// @return the amount of digging fees due the embalmer for this curse\\n function curseArchaeologist(\\n bytes32 sarcoId,\\n EmbalmerFacet.CurseParams calldata archaeologist,\\n uint256 index\\n ) internal returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\n publicKey: archaeologist.publicKey,\\n privateKey: 0,\\n isAccused: false,\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\n curseFee: archaeologist.curseFee\\n });\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\n\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\n + archaeologist.curseFee;\\n\\n // Use cursed bond percentage to determine how much bond to lock up\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\n\\n // Transfer bond to curse from free bond to cursed bond\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\n\\n return diggingFeesDue;\\n }\\n\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\n /// @param archaeologistAddress the address of the archaeologist to free\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\n .sarcophagi[sarcoId]\\n .cursedArchaeologists[archaeologistAddress];\\n\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n // Include curse fee in bond amount being released\\n uint256 cursedBondAmount = ((diggingFeeAmount + cursedArchaeologist.curseFee) * sarcophagus.cursedBondPercentage) / 10000;\\n\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\n\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\n }\\n\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\n }\\n}\\n\",\"keccak256\":\"0x1ce4949867d00310a878d0671312e3c9b51c3301586df45dfc63bc43f16bd1d9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title A collection of Errors\\n * @notice This library defines all of the Errors that the Sarcophagus system\\n * uses.\\n */\\nlibrary LibErrors {\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\n\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\n\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\n\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\n\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\n\\n error SarcophagusInactive(bytes32 sarcoId);\\n\\n error SarcophagusCompromised(bytes32 sarcoId);\\n\\n error SenderNotEmbalmer(address sender, address embalmer);\\n\\n error InvalidSignature(\\n // address recovered from signature via ecrecover\\n address recoveredAddress,\\n // address we expected to have signed the data\\n address expectedAddress\\n );\\n}\\n\",\"keccak256\":\"0xed77e67ab300a74738cd8ec5fe8e3bd5c166b87410051ceaabe0a7ec2e45b967\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Types shared across facets for the Sarcophagus diamond\\n */\\nlibrary LibTypes {\\n struct Sarcophagus {\\n // Also used for existence checks -- does not exist if 0\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\n bool isCompromised;\\n bool isCleaned;\\n bool isRewrapped;\\n uint8 threshold;\\n string name;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] cursedArchaeologistAddresses;\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\n uint256 cursedBondPercentage;\\n }\\n\\n struct CursedArchaeologist {\\n uint256 diggingFeePerSecond;\\n // Also used for publish checks -- has not published if 0\\n bytes32 privateKey;\\n // Also used for curse checks -- is not bonded if length is 0\\n bytes publicKey;\\n bool isAccused;\\n uint256 curseFee;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n struct ArchaeologistProfile {\\n // Also used for existence checks -- does not exist if 0\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string peerId;\\n uint256 minimumDiggingFeePerSecond;\\n uint256 freeBond;\\n uint256 cursedBond;\\n uint256 curseFee;\\n }\\n}\\n\",\"keccak256\":\"0x1b2f2f8c309ec6d6f4895143d290b5d99daacfee6bfd2443dfe74dc0f29e8678\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\nimport \\\"./LibTypes.sol\\\";\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\n/**\\n * @title Utility functions used within the Sarcophagus system\\n * @notice This library implements various functions that are used throughout\\n * Sarcophagus, mainly to DRY up the codebase\\n * @dev these functions are all stateless, public, pure/view\\n */\\nlibrary LibUtils {\\n /**\\n * @notice The archaeologist needs to sign off on two pieces of data\\n * to guarantee their unrwap will be successful\\n *\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\n * @param curseParams parameters of curse signed by archaeologist\\n */\\n function verifyArchaeologistSignature(\\n uint256 agreedMaximumRewrapInterval,\\n uint256 maximumResurrectionTime,\\n uint256 timestamp,\\n EmbalmerFacet.CurseParams calldata curseParams\\n ) internal pure {\\n // Hash the hash of the data payload\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(\\n abi.encode(\\n curseParams.publicKey,\\n agreedMaximumRewrapInterval,\\n maximumResurrectionTime,\\n curseParams.diggingFeePerSecond,\\n timestamp,\\n curseParams.curseFee\\n )\\n )\\n )\\n );\\n\\n // Generate the address from the signature.\\n // ecrecover should always return a valid address.\\n address recoveredAddress = ecrecover(\\n messageHash,\\n curseParams.v,\\n curseParams.r,\\n curseParams.s\\n );\\n\\n if (recoveredAddress != curseParams.archAddress) {\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\n }\\n }\\n\\n /// @notice Verifies that a signature and public key were created from the same private key\\n /// @param sarcoId the sarcoId that was signed\\n /// @param paymentAddress the payment address that was signed\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\n /// @param signature signature on the sarco id and payment address\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\n function verifyAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes calldata publicKey,\\n LibTypes.Signature calldata signature\\n ) internal pure returns (bool) {\\n // removes the 0x04 prefix from an uncompressed public key\\n uint256 pubKeyLength = publicKey.length;\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\n for (uint256 i = 1; i < pubKeyLength; ) {\\n truncatedPublicKey[i - 1] = publicKey[i];\\n unchecked {\\n ++i;\\n }\\n }\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(abi.encode(sarcoId, paymentAddress))\\n )\\n );\\n // Use ecrecover to get the address that signed the message\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\n\\n address publicKeyAddress = address(\\n uint160(\\n uint256(keccak256(truncatedPublicKey)) &\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n )\\n );\\n\\n return signingAddress == publicKeyAddress;\\n }\\n\\n /// @notice Checks if an archaeologist profile exists and\\n /// reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check existence of\\n function revertIfArchProfileExists(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\n }\\n }\\n\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check lack of existence of\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\n }\\n }\\n\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\n /// @return The protocol fees amount\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\n }\\n}\\n\",\"keccak256\":\"0x1b411278faa2f19d4fb8f558fb1ce33f35cc367cca58b7229d5c2f8848201b48\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\n/**\\n * Global diamond storage struct to be shared across facets\\n */\\nstruct AppStorage {\\n // SARCO token contract\\n IERC20 sarcoToken;\\n // The Admin address allowed to call Admin Facet functions\\n address admin;\\n // total protocol fees available to be withdrawn by the admin\\n uint256 totalProtocolFees;\\n /**\\n * Protocol level admin configurations\\n */\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\n uint256 protocolFeeBasePercentage;\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\n uint256 cursedBondPercentage;\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\n uint256 gracePeriod;\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\n uint256 expirationThreshold;\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\n uint256 embalmerClaimWindow;\\n // registered archaeologist addresses\\n address[] archaeologistProfileAddresses;\\n // public key => archaeologist address\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\n // sarcophagus id => sarcophagus object\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\n // archaeologist address => profile\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\n // current balance of rewards available for the archaeologist to withdraw\\n mapping(address => uint256) archaeologistRewards;\\n}\\n\\nlibrary LibAppStorage {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\n\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n s.slot := position\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07df02177bdd1ecc43723d2c46b8d81ecc84b49c40b7c85478ef4c4650b02335\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50612182806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806397b03b531461003b578063ebad22f814610057575b600080fd5b61005560048036038101906100509190611772565b610073565b005b610071600480360381019061006c91906118b8565b610885565b005b600061007d611280565b9050600081600a016000848152602001908152602001600020905060008160000154036100e157826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100d8919061196e565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561017457506101446112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156101b657336040517fd5fa066e0000000000000000000000000000000000000000000000000000000081526004016101ad9190611998565b60405180910390fd5b8060020160009054906101000a900460ff161561020a57826040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610201919061196e565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361027257826040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610269919061196e565b60405180910390fd5b8060020160019054906101000a900460ff16156102c657826040517fc921f1850000000000000000000000000000000000000000000000000000000081526004016102bd919061196e565b60405180910390fd5b816005015481600001546102da91906119ec565b42116103325742826005015482600001546102f591906119ec565b6040517f808b7d7c000000000000000000000000000000000000000000000000000000008152600401610329929190611a2f565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156103b257508160070154826005015482600001546103a591906119ec565b6103af91906119ec565b42115b1561041857428260070154836005015483600001546103d191906119ec565b6103db91906119ec565b6040517f569861b100000000000000000000000000000000000000000000000000000000815260040161040f929190611a2f565b60405180910390fd5b6104206112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561047c575081600701548260050154826000015461046e91906119ec565b61047891906119ec565b4211155b156104e2574282600701548360050154836000015461049b91906119ec565b6104a591906119ec565b6040517ff88af35b0000000000000000000000000000000000000000000000000000000081526004016104d9929190611a2f565b60405180910390fd5b6000808260090180549050905060005b818110156106dd57600084600a01600086600901848154811061051857610517611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff161580156105a457506000801b8160010154145b156106d1576000856001015486600001546105bf9190611a87565b82600001546105ce9190611abb565b90508560020160029054906101000a900460ff166105f9578160040154816105f691906119ec565b90505b600061271087600b01548361060e9190611abb565b6106189190611b2c565b9050808261062691906119ec565b8661063191906119ec565b95508088600b0160008960090187815481106106505761064f611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546106c79190611a87565b9250508190555050505b816001019150506104f2565b508260070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603610801578360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016107b8929190611b5d565b6020604051808303816000875af11580156107d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fb9190611bbe565b5061081d565b8184600201600082825461081591906119ec565b925050819055505b60018360020160016101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16857ffa165ffb1378fffa7397821a24fb52e993eab195619a2573789fca8a9e12b26660405160405180910390a35050505050565b600061088f611280565b9050600081600a016000898152602001908152602001600020905060008160000154036108f357876040517f018da6880000000000000000000000000000000000000000000000000000000081526004016108ea919061196e565b60405180910390fd5b8060000154421115610942574281600001546040517f2458293a000000000000000000000000000000000000000000000000000000008152600401610939929190611a2f565b60405180910390fd5b8060020160009054906101000a900460ff161561099657876040517f9af72b8600000000000000000000000000000000000000000000000000000000815260040161098d919061196e565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036109fe57876040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016109f5919061196e565b60405180910390fd5b6000858590509050878790508114610a525780888890506040517fcc1d5b80000000000000000000000000000000000000000000000000000000008152600401610a49929190611a2f565b60405180910390fd5b60008167ffffffffffffffff811115610a6e57610a6d611beb565b5b604051908082528060200260200182016040528015610a9c5781602001602082028036833780820191505090505b50905060008060005b84811015610e1857610af58d898e8e85818110610ac557610ac4611a58565b5b9050602002810190610ad79190611c29565b8e8e87818110610aea57610ae9611a58565b5b9050606002016112e0565b610b79578c888d8d84818110610b0e57610b0d611a58565b5b9050602002810190610b209190611c29565b8d8d86818110610b3357610b32611a58565b5b9050606002016040517f272bd265000000000000000000000000000000000000000000000000000000008152600401610b70959493929190611dc9565b60405180910390fd5b6000876009018d8d84818110610b9257610b91611a58565b5b9050602002810190610ba49190611c29565b604051610bb2929190611e47565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600087600a0160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002018054610c3990611e8f565b905003610c7d57336040517f82881f03000000000000000000000000000000000000000000000000000000008152600401610c749190611998565b60405180910390fd5b8060030160009054906101000a900460ff1615610ca1578260010192505050610e13565b60018160030160006101000a81548160ff02191690831515021790555081868580610ccb90611ec0565b965081518110610cde57610cdd611a58565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600061271089600b01548a600101548b60000154610d369190611a87565b8460000154610d459190611abb565b610d4f9190611abb565b610d599190611b2c565b90508860020160029054906101000a900460ff16610da05761271089600b01548360040154610d889190611abb565b610d929190611b2c565b81610d9d91906119ec565b90505b8086610dac91906119ec565b9550808a600b0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254610e029190611a87565b925050819055508360010193505050505b610aa5565b5060008103610e2c57505050505050611278565b6000856009018054905090508560020160039054906101000a900460ff1660ff168210610e755760018660020160006101000a81548160ff021916908315150217905550610f6c565b6000805b82811015610f305787600a016000896009018381548110610e9d57610e9c611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1615610f255781610f2290611ec0565b91505b806001019050610e79565b508660020160039054906101000a900460ff1660ff168110610f6a5760018760020160006101000a81548160ff0219169083151502179055505b505b8560020160009054906101000a900460ff161561107c5760005b8181101561107a5786600a016000886009018381548110610faa57610fa9611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1661106f5761106e8e88600901838154811061103e5761103d611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166114f0565b5b806001019050610f86565b505b506000600183901c9050600061271087600b015461109a9190611b2c565b846110a59190611b2c565b90508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8860070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848461111891906119ec565b6040518363ffffffff1660e01b8152600401611135929190611b5d565b6020604051808303816000875af1158015611154573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111789190611bbe565b508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a846040518363ffffffff1660e01b81526004016111d8929190611b5d565b6020604051808303816000875af11580156111f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121b9190611bbe565b503373ffffffffffffffffffffffffffffffffffffffff168e7fe9dec50cc13b92f93757042597e26d7b2af2ac85e441e773d4701a50093ec8d886848960405161126793929190611fc6565b60405180910390a350505050505050505b505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b60006112b7611705565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008084849050905060006001826112f89190611a87565b67ffffffffffffffff81111561131157611310611beb565b5b6040519080825280601f01601f1916602001820160405280156113435781602001600182028036833780820191505090505b5090506000600190505b828110156113cb5786868281811061136857611367611a58565b5b9050013560f81c60f81b826001836113809190611a87565b8151811061139157611390611a58565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080600101905061134d565b50600088886040516020016113e1929190612004565b6040516020818303038152906040528051906020012060405160200161140791906120a5565b604051602081830303815290604052805190602001209050600060018287600001602081019061143791906120cb565b886020013589604001356040516000815260200160405260405161145e9493929190612107565b6020604051602081039080840390855afa158015611480573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff848051906020012060001c1690508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149550505050505095945050505050565b60006114fa611280565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546115849190611a87565b82600001546115939190611abb565b9050600061271084600b01548460040154846115af91906119ec565b6115b99190611abb565b6115c39190611b2c565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546116199190611a87565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401600082825461167491906119ec565b925050819055508360020160029054906101000a900460ff166116a4578260040154826116a191906119ec565b91505b8185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546116f591906119ec565b9250508190555050505050505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b600080fd5b600080fd5b6000819050919050565b61174f8161173c565b811461175a57600080fd5b50565b60008135905061176c81611746565b92915050565b60006020828403121561178857611787611732565b5b60006117968482850161175d565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126117c4576117c361179f565b5b8235905067ffffffffffffffff8111156117e1576117e06117a4565b5b6020830191508360208202830111156117fd576117fc6117a9565b5b9250929050565b60008083601f84011261181a5761181961179f565b5b8235905067ffffffffffffffff811115611837576118366117a4565b5b602083019150836060820283011115611853576118526117a9565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006118858261185a565b9050919050565b6118958161187a565b81146118a057600080fd5b50565b6000813590506118b28161188c565b92915050565b600080600080600080608087890312156118d5576118d4611732565b5b60006118e389828a0161175d565b965050602087013567ffffffffffffffff81111561190457611903611737565b5b61191089828a016117ae565b9550955050604087013567ffffffffffffffff81111561193357611932611737565b5b61193f89828a01611804565b9350935050606061195289828a016118a3565b9150509295509295509295565b6119688161173c565b82525050565b6000602082019050611983600083018461195f565b92915050565b6119928161187a565b82525050565b60006020820190506119ad6000830184611989565b92915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006119f7826119b3565b9150611a02836119b3565b9250828201905080821115611a1a57611a196119bd565b5b92915050565b611a29816119b3565b82525050565b6000604082019050611a446000830185611a20565b611a516020830184611a20565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000611a92826119b3565b9150611a9d836119b3565b9250828203905081811115611ab557611ab46119bd565b5b92915050565b6000611ac6826119b3565b9150611ad1836119b3565b9250828202611adf816119b3565b91508282048414831517611af657611af56119bd565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611b37826119b3565b9150611b42836119b3565b925082611b5257611b51611afd565b5b828204905092915050565b6000604082019050611b726000830185611989565b611b7f6020830184611a20565b9392505050565b60008115159050919050565b611b9b81611b86565b8114611ba657600080fd5b50565b600081519050611bb881611b92565b92915050565b600060208284031215611bd457611bd3611732565b5b6000611be284828501611ba9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112611c4657611c45611c1a565b5b80840192508235915067ffffffffffffffff821115611c6857611c67611c1f565b5b602083019250600182023603831315611c8457611c83611c24565b5b509250929050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b6000611cc98385611c8c565b9350611cd6838584611c9d565b611cdf83611cac565b840190509392505050565b600060ff82169050919050565b611d0081611cea565b8114611d0b57600080fd5b50565b600081359050611d1d81611cf7565b92915050565b6000611d326020840184611d0e565b905092915050565b611d4381611cea565b82525050565b6000611d58602084018461175d565b905092915050565b611d698161173c565b82525050565b60608201611d806000830183611d23565b611d8d6000850182611d3a565b50611d9b6020830183611d49565b611da86020850182611d60565b50611db66040830183611d49565b611dc36040850182611d60565b50505050565b600060c082019050611dde600083018861195f565b611deb6020830187611989565b8181036040830152611dfe818587611cbd565b9050611e0d6060830184611d6f565b9695505050505050565b600081905092915050565b6000611e2e8385611e17565b9350611e3b838584611c9d565b82840190509392505050565b6000611e54828486611e22565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611ea757607f821691505b602082108103611eba57611eb9611e60565b5b50919050565b6000611ecb826119b3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611efd57611efc6119bd565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611f3d8161187a565b82525050565b6000611f4f8383611f34565b60208301905092915050565b6000602082019050919050565b6000611f7382611f08565b611f7d8185611f13565b9350611f8883611f24565b8060005b83811015611fb9578151611fa08882611f43565b9750611fab83611f5b565b925050600181019050611f8c565b5085935050505092915050565b6000606082019050611fdb6000830186611a20565b611fe86020830185611a20565b8181036040830152611ffa8184611f68565b9050949350505050565b6000604082019050612019600083018561195f565b6120266020830184611989565b9392505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061206e601c8361202d565b915061207982612038565b601c82019050919050565b6000819050919050565b61209f61209a8261173c565b612084565b82525050565b60006120b082612061565b91506120bc828461208e565b60208201915081905092915050565b6000602082840312156120e1576120e0611732565b5b60006120ef84828501611d0e565b91505092915050565b61210181611cea565b82525050565b600060808201905061211c600083018761195f565b61212960208301866120f8565b612136604083018561195f565b612143606083018461195f565b9594505050505056fea264697066735822122045ed4ce721d4b3987b3f90fbb331c6fda4926c8265d045b0c842ba7bcb8e6b8c64736f6c63430008120033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806397b03b531461003b578063ebad22f814610057575b600080fd5b61005560048036038101906100509190611772565b610073565b005b610071600480360381019061006c91906118b8565b610885565b005b600061007d611280565b9050600081600a016000848152602001908152602001600020905060008160000154036100e157826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100d8919061196e565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561017457506101446112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156101b657336040517fd5fa066e0000000000000000000000000000000000000000000000000000000081526004016101ad9190611998565b60405180910390fd5b8060020160009054906101000a900460ff161561020a57826040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610201919061196e565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361027257826040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610269919061196e565b60405180910390fd5b8060020160019054906101000a900460ff16156102c657826040517fc921f1850000000000000000000000000000000000000000000000000000000081526004016102bd919061196e565b60405180910390fd5b816005015481600001546102da91906119ec565b42116103325742826005015482600001546102f591906119ec565b6040517f808b7d7c000000000000000000000000000000000000000000000000000000008152600401610329929190611a2f565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156103b257508160070154826005015482600001546103a591906119ec565b6103af91906119ec565b42115b1561041857428260070154836005015483600001546103d191906119ec565b6103db91906119ec565b6040517f569861b100000000000000000000000000000000000000000000000000000000815260040161040f929190611a2f565b60405180910390fd5b6104206112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561047c575081600701548260050154826000015461046e91906119ec565b61047891906119ec565b4211155b156104e2574282600701548360050154836000015461049b91906119ec565b6104a591906119ec565b6040517ff88af35b0000000000000000000000000000000000000000000000000000000081526004016104d9929190611a2f565b60405180910390fd5b6000808260090180549050905060005b818110156106dd57600084600a01600086600901848154811061051857610517611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff161580156105a457506000801b8160010154145b156106d1576000856001015486600001546105bf9190611a87565b82600001546105ce9190611abb565b90508560020160029054906101000a900460ff166105f9578160040154816105f691906119ec565b90505b600061271087600b01548361060e9190611abb565b6106189190611b2c565b9050808261062691906119ec565b8661063191906119ec565b95508088600b0160008960090187815481106106505761064f611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546106c79190611a87565b9250508190555050505b816001019150506104f2565b508260070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603610801578360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016107b8929190611b5d565b6020604051808303816000875af11580156107d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fb9190611bbe565b5061081d565b8184600201600082825461081591906119ec565b925050819055505b60018360020160016101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16857ffa165ffb1378fffa7397821a24fb52e993eab195619a2573789fca8a9e12b26660405160405180910390a35050505050565b600061088f611280565b9050600081600a016000898152602001908152602001600020905060008160000154036108f357876040517f018da6880000000000000000000000000000000000000000000000000000000081526004016108ea919061196e565b60405180910390fd5b8060000154421115610942574281600001546040517f2458293a000000000000000000000000000000000000000000000000000000008152600401610939929190611a2f565b60405180910390fd5b8060020160009054906101000a900460ff161561099657876040517f9af72b8600000000000000000000000000000000000000000000000000000000815260040161098d919061196e565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036109fe57876040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016109f5919061196e565b60405180910390fd5b6000858590509050878790508114610a525780888890506040517fcc1d5b80000000000000000000000000000000000000000000000000000000008152600401610a49929190611a2f565b60405180910390fd5b60008167ffffffffffffffff811115610a6e57610a6d611beb565b5b604051908082528060200260200182016040528015610a9c5781602001602082028036833780820191505090505b50905060008060005b84811015610e1857610af58d898e8e85818110610ac557610ac4611a58565b5b9050602002810190610ad79190611c29565b8e8e87818110610aea57610ae9611a58565b5b9050606002016112e0565b610b79578c888d8d84818110610b0e57610b0d611a58565b5b9050602002810190610b209190611c29565b8d8d86818110610b3357610b32611a58565b5b9050606002016040517f272bd265000000000000000000000000000000000000000000000000000000008152600401610b70959493929190611dc9565b60405180910390fd5b6000876009018d8d84818110610b9257610b91611a58565b5b9050602002810190610ba49190611c29565b604051610bb2929190611e47565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600087600a0160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002018054610c3990611e8f565b905003610c7d57336040517f82881f03000000000000000000000000000000000000000000000000000000008152600401610c749190611998565b60405180910390fd5b8060030160009054906101000a900460ff1615610ca1578260010192505050610e13565b60018160030160006101000a81548160ff02191690831515021790555081868580610ccb90611ec0565b965081518110610cde57610cdd611a58565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600061271089600b01548a600101548b60000154610d369190611a87565b8460000154610d459190611abb565b610d4f9190611abb565b610d599190611b2c565b90508860020160029054906101000a900460ff16610da05761271089600b01548360040154610d889190611abb565b610d929190611b2c565b81610d9d91906119ec565b90505b8086610dac91906119ec565b9550808a600b0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254610e029190611a87565b925050819055508360010193505050505b610aa5565b5060008103610e2c57505050505050611278565b6000856009018054905090508560020160039054906101000a900460ff1660ff168210610e755760018660020160006101000a81548160ff021916908315150217905550610f6c565b6000805b82811015610f305787600a016000896009018381548110610e9d57610e9c611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1615610f255781610f2290611ec0565b91505b806001019050610e79565b508660020160039054906101000a900460ff1660ff168110610f6a5760018760020160006101000a81548160ff0219169083151502179055505b505b8560020160009054906101000a900460ff161561107c5760005b8181101561107a5786600a016000886009018381548110610faa57610fa9611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1661106f5761106e8e88600901838154811061103e5761103d611a58565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166114f0565b5b806001019050610f86565b505b506000600183901c9050600061271087600b015461109a9190611b2c565b846110a59190611b2c565b90508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8860070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848461111891906119ec565b6040518363ffffffff1660e01b8152600401611135929190611b5d565b6020604051808303816000875af1158015611154573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111789190611bbe565b508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a846040518363ffffffff1660e01b81526004016111d8929190611b5d565b6020604051808303816000875af11580156111f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121b9190611bbe565b503373ffffffffffffffffffffffffffffffffffffffff168e7fe9dec50cc13b92f93757042597e26d7b2af2ac85e441e773d4701a50093ec8d886848960405161126793929190611fc6565b60405180910390a350505050505050505b505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b60006112b7611705565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008084849050905060006001826112f89190611a87565b67ffffffffffffffff81111561131157611310611beb565b5b6040519080825280601f01601f1916602001820160405280156113435781602001600182028036833780820191505090505b5090506000600190505b828110156113cb5786868281811061136857611367611a58565b5b9050013560f81c60f81b826001836113809190611a87565b8151811061139157611390611a58565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080600101905061134d565b50600088886040516020016113e1929190612004565b6040516020818303038152906040528051906020012060405160200161140791906120a5565b604051602081830303815290604052805190602001209050600060018287600001602081019061143791906120cb565b886020013589604001356040516000815260200160405260405161145e9493929190612107565b6020604051602081039080840390855afa158015611480573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff848051906020012060001c1690508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149550505050505095945050505050565b60006114fa611280565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546115849190611a87565b82600001546115939190611abb565b9050600061271084600b01548460040154846115af91906119ec565b6115b99190611abb565b6115c39190611b2c565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546116199190611a87565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401600082825461167491906119ec565b925050819055508360020160029054906101000a900460ff166116a4578260040154826116a191906119ec565b91505b8185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546116f591906119ec565b9250508190555050505050505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b600080fd5b600080fd5b6000819050919050565b61174f8161173c565b811461175a57600080fd5b50565b60008135905061176c81611746565b92915050565b60006020828403121561178857611787611732565b5b60006117968482850161175d565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126117c4576117c361179f565b5b8235905067ffffffffffffffff8111156117e1576117e06117a4565b5b6020830191508360208202830111156117fd576117fc6117a9565b5b9250929050565b60008083601f84011261181a5761181961179f565b5b8235905067ffffffffffffffff811115611837576118366117a4565b5b602083019150836060820283011115611853576118526117a9565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006118858261185a565b9050919050565b6118958161187a565b81146118a057600080fd5b50565b6000813590506118b28161188c565b92915050565b600080600080600080608087890312156118d5576118d4611732565b5b60006118e389828a0161175d565b965050602087013567ffffffffffffffff81111561190457611903611737565b5b61191089828a016117ae565b9550955050604087013567ffffffffffffffff81111561193357611932611737565b5b61193f89828a01611804565b9350935050606061195289828a016118a3565b9150509295509295509295565b6119688161173c565b82525050565b6000602082019050611983600083018461195f565b92915050565b6119928161187a565b82525050565b60006020820190506119ad6000830184611989565b92915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006119f7826119b3565b9150611a02836119b3565b9250828201905080821115611a1a57611a196119bd565b5b92915050565b611a29816119b3565b82525050565b6000604082019050611a446000830185611a20565b611a516020830184611a20565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000611a92826119b3565b9150611a9d836119b3565b9250828203905081811115611ab557611ab46119bd565b5b92915050565b6000611ac6826119b3565b9150611ad1836119b3565b9250828202611adf816119b3565b91508282048414831517611af657611af56119bd565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611b37826119b3565b9150611b42836119b3565b925082611b5257611b51611afd565b5b828204905092915050565b6000604082019050611b726000830185611989565b611b7f6020830184611a20565b9392505050565b60008115159050919050565b611b9b81611b86565b8114611ba657600080fd5b50565b600081519050611bb881611b92565b92915050565b600060208284031215611bd457611bd3611732565b5b6000611be284828501611ba9565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112611c4657611c45611c1a565b5b80840192508235915067ffffffffffffffff821115611c6857611c67611c1f565b5b602083019250600182023603831315611c8457611c83611c24565b5b509250929050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b6000611cc98385611c8c565b9350611cd6838584611c9d565b611cdf83611cac565b840190509392505050565b600060ff82169050919050565b611d0081611cea565b8114611d0b57600080fd5b50565b600081359050611d1d81611cf7565b92915050565b6000611d326020840184611d0e565b905092915050565b611d4381611cea565b82525050565b6000611d58602084018461175d565b905092915050565b611d698161173c565b82525050565b60608201611d806000830183611d23565b611d8d6000850182611d3a565b50611d9b6020830183611d49565b611da86020850182611d60565b50611db66040830183611d49565b611dc36040850182611d60565b50505050565b600060c082019050611dde600083018861195f565b611deb6020830187611989565b8181036040830152611dfe818587611cbd565b9050611e0d6060830184611d6f565b9695505050505050565b600081905092915050565b6000611e2e8385611e17565b9350611e3b838584611c9d565b82840190509392505050565b6000611e54828486611e22565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611ea757607f821691505b602082108103611eba57611eb9611e60565b5b50919050565b6000611ecb826119b3565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611efd57611efc6119bd565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611f3d8161187a565b82525050565b6000611f4f8383611f34565b60208301905092915050565b6000602082019050919050565b6000611f7382611f08565b611f7d8185611f13565b9350611f8883611f24565b8060005b83811015611fb9578151611fa08882611f43565b9750611fab83611f5b565b925050600181019050611f8c565b5085935050505092915050565b6000606082019050611fdb6000830186611a20565b611fe86020830185611a20565b8181036040830152611ffa8184611f68565b9050949350505050565b6000604082019050612019600083018561195f565b6120266020830184611989565b9392505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061206e601c8361202d565b915061207982612038565b601c82019050919050565b6000819050919050565b61209f61209a8261173c565b612084565b82525050565b60006120b082612061565b91506120bc828461208e565b60208201915081905092915050565b6000602082840312156120e1576120e0611732565b5b60006120ef84828501611d0e565b91505092915050565b61210181611cea565b82525050565b600060808201905061211c600083018761195f565b61212960208301866120f8565b612136604083018561195f565b612143606083018461195f565b9594505050505056fea264697066735822122045ed4ce721d4b3987b3f90fbb331c6fda4926c8265d045b0c842ba7bcb8e6b8c64736f6c63430008120033", + "devdoc": { + "errors": { + "DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)": [ + { + "params": { + "publicKeys": "the number of public keys passed into the accuse call", + "signatures": "the number of signatures passed into the accuse call" + } + } + ], + "EmbalmerClaimWindowPassed(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed clean attempt", + "embalmerClaimWindowEnd": "Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow" + } + } + ], + "InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))": [ + { + "params": { + "paymentAddress": "payment address that should have been signed", + "publicKey": "publicKey that should be derived from signing key", + "sarcoId": "that should have been signed", + "signature": "invalid signature" + } + } + ], + "ResurrectionTimeInPast(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed accuse attempt", + "resurrectionTime": "Resurrection timestamp which has already passed" + } + } + ], + "SarcophagusAlreadyCleaned(bytes32)": [ + { + "params": { + "sarcoId": "ID of sarcophagus archaeologist has attempted to publish a private key on" + } + } + ], + "SenderNotEmbalmerOrAdmin(address)": [ + { + "params": { + "senderAddress": "Address of sender" + } + } + ], + "TooEarlyForAdminClean(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed clean attempt", + "embalmerClaimWindowEnd": "Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow" + } + } + ], + "TooEarlyForClean(uint256,uint256)": [ + { + "params": { + "currentTime": "Timestamp of the failed clean attempt", + "publishDeadline": "Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod" + } + } + ] + }, + "kind": "dev", + "methods": { + "accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)": { + "params": { + "paymentAddress": "the address to which rewards should be sent if successful", + "publicKeys": "an array of public keys corresponding to leaked private keys - order must match order of signatures", + "sarcoId": "The identifier of the sarcophagus having leaked private keys", + "signatures": "an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys" + } + }, + "clean(bytes32)": { + "params": { + "sarcoId": "The identifier of the sarcophagus to clean" + } + } + }, + "version": 1 + }, + "userdoc": { + "errors": { + "DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)": [ + { + "notice": "Emitted when accuse is called with an unequal numbers of public keys and signatures" + } + ], + "EmbalmerClaimWindowPassed(uint256,uint256)": [ + { + "notice": "Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed" + } + ], + "InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))": [ + { + "notice": "Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey" + } + ], + "ResurrectionTimeInPast(uint256,uint256)": [ + { + "notice": "Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed" + } + ], + "SarcophagusAlreadyCleaned(bytes32)": [ + { + "notice": "Clean has been called on a sarcophagus that has already been cleaned" + } + ], + "SenderNotEmbalmerOrAdmin(address)": [ + { + "notice": "Clean has been called by someone other than the admin or embalmer of the sarcophagus" + } + ], + "TooEarlyForAdminClean(uint256,uint256)": [ + { + "notice": "Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed" + } + ], + "TooEarlyForClean(uint256,uint256)": [ + { + "notice": "Clean has been called before the deadline for archaeologists to publish private keys has passed" + } + ] + }, + "kind": "user", + "methods": { + "accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)": { + "notice": "Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id and payment address generated with the leaked private keys If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus state will be updated to Accused and bonds for all remaining unaccused archaeologists will be returned" + }, + "clean(bytes32)": { + "notice": "If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod, their locked bonds and diggingFees may be claimed by either the embalmer or the admin embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will be able to claim remaining locked bond and diggingFees" + } + }, + "version": 1 + }, + "storageLayout": { + "storage": [], + "types": null + } +} \ No newline at end of file diff --git a/deployments/baseGoerli/ViewStateFacet.json b/deployments/arbitrum/ViewStateFacet.json similarity index 53% rename from deployments/baseGoerli/ViewStateFacet.json rename to deployments/arbitrum/ViewStateFacet.json index cd861e1..7ee6c8d 100644 --- a/deployments/baseGoerli/ViewStateFacet.json +++ b/deployments/arbitrum/ViewStateFacet.json @@ -1,5 +1,5 @@ { - "address": "0x89f887186e23B04A98e2f1D6aD5E8Ee300d11359", + "address": "0x67E8A916284558989F2d85C4674F640eC2F1e283", "abi": [ { "inputs": [ @@ -468,28 +468,28 @@ "type": "function" } ], - "transactionHash": "0xea13ee3db2e5ebc74ef2e2d42ed544dc540c12a5a34f8f54d9a214d5519f8beb", + "transactionHash": "0x5aef86dbef96454c2852b0f7b68893969823d5931e2f6f6a2e9716fc0f53dfa0", "receipt": { "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", + "from": "0xAE9B102741a1B60C221e39CD9526Ab38c9865AB3", "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "1705869", + "transactionIndex": 2, + "gasUsed": "18194393", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0xd48fcd06bfba8dac3b2cf63a2315cb2234b1016e96dd05e84d5056f797db6f64", - "transactionHash": "0xea13ee3db2e5ebc74ef2e2d42ed544dc540c12a5a34f8f54d9a214d5519f8beb", + "blockHash": "0x7f8d009ad48cc3ea7d337c1de9c3c213fcadf05f353d6c823ec12b29598a4c62", + "transactionHash": "0x5aef86dbef96454c2852b0f7b68893969823d5931e2f6f6a2e9716fc0f53dfa0", "logs": [], - "blockNumber": 9669975, - "cumulativeGasUsed": "1756262", + "blockNumber": 152626962, + "cumulativeGasUsed": "20413702", "status": 1, "byzantium": true }, "args": [], "numDeployments": 1, - "solcInputHash": "b7fcd450a9977c08df561a1e7df764e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistProfileExistsShouldBe\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"getAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getArchaeologistProfile\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"internalType\":\"struct LibTypes.ArchaeologistProfile\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getArchaeologistProfileAddressAtIndex\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getArchaeologistProfileAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"}],\"name\":\"getArchaeologistProfiles\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"internalType\":\"struct LibTypes.ArchaeologistProfile[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getCursedBond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedBondPercentage\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEmbalmerClaimWindow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpirationThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getFreeBond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGracePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getProtocolFeeBasePercentage\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"getSarcophagus\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"previousRewrapTime\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isCompromised\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCleaned\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"threshold\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"arweaveTxId\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"embalmerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipientAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"archaeologistAddresses\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"publishedPrivateKeyCount\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"hasLockedBond\",\"type\":\"bool\"}],\"internalType\":\"struct ViewStateFacet.SarcophagusResponse\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getSarcophagusArchaeologist\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"diggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isAccused\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"internalType\":\"struct LibTypes.CursedArchaeologist\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalProtocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAdmin()\":{\"returns\":{\"_0\":\"The admin address\"}},\"getArchaeologistProfile(address)\":{\"params\":{\"archaeologist\":\"The archaeologist account's address\"},\"returns\":{\"_0\":\"the Archaeologist object\"}},\"getArchaeologistProfileAddressAtIndex(uint256)\":{\"params\":{\"index\":\"The index of the registered archaeologist\"},\"returns\":{\"_0\":\"address of the archaeologist\"}},\"getArchaeologistProfileAddresses()\":{\"returns\":{\"_0\":\"addresses of registered archaeologists\"}},\"getArchaeologistProfiles(address[])\":{\"params\":{\"addresses\":\"The list of archaeologist addresses\"},\"returns\":{\"_0\":\"The list of archaeologist profiles\"}},\"getCursedBond(address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose cursed bond is being returned\"}},\"getCursedBondPercentage()\":{\"returns\":{\"_0\":\"The cursed bond percentage - cursedBondPercentage\"}},\"getEmbalmerClaimWindow()\":{\"returns\":{\"_0\":\"The embalmer claim window\"}},\"getExpirationThreshold()\":{\"returns\":{\"_0\":\"The expiration threshold\"}},\"getFreeBond(address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose free bond is being returned\"}},\"getGracePeriod()\":{\"returns\":{\"_0\":\"The resurrection grace period\"}},\"getProtocolFeeBasePercentage()\":{\"returns\":{\"_0\":\"The protocol fee base percentage - protocolFeeBasePercentage\"}},\"getRewards(address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose reward is being returned\"}},\"getSarcophagus(bytes32)\":{\"params\":{\"sarcoId\":\"The identifier of the sarcophagus being returned\"}},\"getSarcophagusArchaeologist(bytes32,address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose data is being returned\",\"sarcoId\":\"The identifier of the sarcophagus whose data is being returned\"}},\"getTotalProtocolFees()\":{\"returns\":{\"_0\":\"The total protocol fees\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAdmin()\":{\"notice\":\"Get the admin address from diamond storage\"},\"getArchaeologistProfile(address)\":{\"notice\":\"Given an archaeologist address, return that archaeologist's profile\"},\"getArchaeologistProfileAddressAtIndex(uint256)\":{\"notice\":\"Given an index (of the full archaeologist array), return the archaeologist address at that index\"},\"getArchaeologistProfileAddresses()\":{\"notice\":\"Return the list of registereed archaeologist addresses.\"},\"getArchaeologistProfiles(address[])\":{\"notice\":\"Gets archaeologist profiles given a list of archaeologist addresses. If an invalid address is included, simply leaves it out of the list.\"},\"getCursedBond(address)\":{\"notice\":\"Returns the amount of cursed bond stored in the contract for an archaeologist.\"},\"getCursedBondPercentage()\":{\"notice\":\"Get the cursed bond percentage from diamond storage\"},\"getEmbalmerClaimWindow()\":{\"notice\":\"Gets the window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys\"},\"getExpirationThreshold()\":{\"notice\":\"Gets the expiration threshold after which a sarcophagus must be renegotiated\"},\"getFreeBond(address)\":{\"notice\":\"Returns the amount of free bond stored in the contract for an archaeologist.\"},\"getGracePeriod()\":{\"notice\":\"Gets the grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time passes\"},\"getProtocolFeeBasePercentage()\":{\"notice\":\"Get the protocol fee base percentage from diamond storage\"},\"getRewards(address)\":{\"notice\":\"Returns the amount of rewards stored in the contract for an archaeologist.\"},\"getSarcophagus(bytes32)\":{\"notice\":\"Returns data on the sarcophagus with the supplied id includes aggregate data on cursed archaeologists associated with the sarcophagus - publishedPrivateKeyCount - the total number of private keys published by archaeologists on the sarcophagus - hasLockedBond - true if archaeologists still have bond locked in the contract for this sarcophagus\"},\"getSarcophagusArchaeologist(bytes32,address)\":{\"notice\":\"Returns the data stored on a sarcophagus for an archaeologist.\"},\"getTotalProtocolFees()\":{\"notice\":\"Gets the total protocol fees from diamond storage\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ViewStateFacet.sol\":\"ViewStateFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\n\\r\\ncontract EmbalmerFacet {\\r\\n /// @notice Emitted when a sarcophagus is created\\r\\n /// @param sarcoId Id of the new sarcophagus\\r\\n /// @param name Name of the new sarcophagus\\r\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\r\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\r\\n /// @param embalmer Address of embalmer\\r\\n /// @param recipient Address of recipient\\r\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\r\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\r\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\r\\n event CreateSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n string name,\\r\\n uint256 resurrectionTime,\\r\\n uint256 creationTime,\\r\\n address indexed embalmer,\\r\\n address indexed recipient,\\r\\n address[] cursedArchaeologists,\\r\\n uint256 totalDiggingFees,\\r\\n string arweaveTxId\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is rewrapped\\r\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\r\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\r\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\r\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\r\\n event RewrapSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n uint256 resurrectionTime,\\r\\n uint256 totalDiggingFees,\\r\\n uint256 rewrapSarcophagusProtocolFees\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is buried\\r\\n /// @param sarcoId Id of sarcophagus that was buried\\r\\n event BurySarcophagus(bytes32 indexed sarcoId);\\r\\n\\r\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\r\\n struct SarcophagusParams {\\r\\n string name;\\r\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\r\\n uint256 maximumRewrapInterval;\\r\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\r\\n uint256 maximumResurrectionTime;\\r\\n address recipientAddress;\\r\\n uint256 resurrectionTime;\\r\\n uint8 threshold;\\r\\n uint256 creationTime;\\r\\n }\\r\\n\\r\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\r\\n struct CurseParams {\\r\\n bytes publicKey;\\r\\n address archAddress;\\r\\n uint256 diggingFeePerSecond;\\r\\n uint256 curseFee;\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\r\\n /// @param sarcoId Id that is already in use\\r\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\r\\n /// @param currentTime Timestamp of the failed create attempt\\r\\n /// @param creationTime Time when the sarcophagus parameters were created\\r\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\r\\n error SarcophagusParametersExpired(\\r\\n uint256 currentTime,\\r\\n uint256 creationTime,\\r\\n uint256 creationDeadline\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\r\\n error NoArchaeologistsProvided();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\r\\n error ThresholdCannotBeZero();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\r\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n uint8 threshold,\\r\\n uint256 totalNumberOfArchaeologists\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\r\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\r\\n /// @param currentTime Timestamp of the failed rewrap attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\r\\n /// @param publicKey the duplicated public key\\r\\n error DuplicatePublicKey(bytes publicKey);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\r\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\r\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\r\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\r\\n error ResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\r\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\r\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\r\\n error ResurrectionTimePastMaxResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 maxResurrectionTime\\r\\n );\\r\\n\\r\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\r\\n\\r\\n error NewResurrectionTimeIsZero();\\r\\n\\r\\n error NewResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 previousResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\r\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\r\\n /// of the sarcophagus until its resurrection time.\\r\\n ///\\r\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\r\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\r\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\r\\n /// - `creationTime` of sarcophagus\\r\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\r\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\r\\n ///\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param sarcophagusParams params to set on sarcophagus being created\\r\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\r\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\r\\n function createSarcophagus(\\r\\n bytes32 sarcoId,\\r\\n SarcophagusParams calldata sarcophagusParams,\\r\\n CurseParams[] calldata selectedArchaeologists,\\r\\n string calldata arweaveTxId\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n // Confirm that sarcophagus with supplied id doesn't already exist\\r\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\r\\n revert SarcophagusAlreadyExists(sarcoId);\\r\\n }\\r\\n\\r\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\r\\n // off by its cursed archaeologists.\\r\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\r\\n revert SarcophagusParametersExpired(\\r\\n block.timestamp,\\r\\n sarcophagusParams.creationTime,\\r\\n sarcophagusParams.creationTime + s.expirationThreshold\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\r\\n if (\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\r\\n sarcophagusParams.resurrectionTime\\r\\n ) {\\r\\n revert ResurrectionTimeTooFarInFuture(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the resurrection time is less than the max resurrection time\\r\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // track total digging fees due upon creation of sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n {\\r\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\r\\n // Validate archaeologist and threshold lengths\\r\\n if (nSelectedArchs == 0) {\\r\\n revert NoArchaeologistsProvided();\\r\\n }\\r\\n\\r\\n if (sarcophagusParams.threshold == 0) {\\r\\n revert ThresholdCannotBeZero();\\r\\n }\\r\\n\\r\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\r\\n // used to distribute keyshares among archaeologists\\r\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\r\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n sarcophagusParams.threshold,\\r\\n nSelectedArchs\\r\\n );\\r\\n }\\r\\n\\r\\n // create the sarcophagus\\r\\n sarcophagus.name = sarcophagusParams.name;\\r\\n sarcophagus.threshold = sarcophagusParams.threshold;\\r\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\r\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\r\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\r\\n sarcophagus.arweaveTxId = arweaveTxId;\\r\\n sarcophagus.embalmerAddress = msg.sender;\\r\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\r\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\r\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\r\\n\\r\\n for (uint256 i; i < nSelectedArchs; ) {\\r\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\r\\n\\r\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\r\\n .publicKey\\r\\n .length != 0\\r\\n ) {\\r\\n revert ArchaeologistListContainsDuplicate(\\r\\n selectedArchaeologists[i].archAddress\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm archaeologist is not re-using a key pair\\r\\n if (\\r\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\r\\n address(0)\\r\\n ) {\\r\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\r\\n }\\r\\n\\r\\n LibUtils.verifyArchaeologistSignature(\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n sarcophagusParams.maximumResurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n selectedArchaeologists[i]\\r\\n );\\r\\n\\r\\n // Curse the archaeologist on this sarcophagus\\r\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\r\\n sarcoId,\\r\\n selectedArchaeologists[i],\\r\\n i\\r\\n );\\r\\n\\r\\n totalDiggingFees += diggingFeesDue;\\r\\n\\r\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\r\\n s.publicKeyToArchaeologistAddress[\\r\\n selectedArchaeologists[i].publicKey\\r\\n ] = selectedArchaeologists[i].archAddress;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n s.totalProtocolFees += protocolFees;\\r\\n s.sarcoToken.transferFrom(\\r\\n msg.sender,\\r\\n address(this),\\r\\n totalDiggingFees + protocolFees\\r\\n );\\r\\n }\\r\\n emit CreateSarcophagus(\\r\\n sarcoId,\\r\\n sarcophagusParams.name,\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n msg.sender,\\r\\n sarcophagusParams.recipientAddress,\\r\\n sarcophagus.cursedArchaeologistAddresses,\\r\\n totalDiggingFees,\\r\\n arweaveTxId\\r\\n );\\r\\n }\\r\\n\\r\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param resurrectionTime the new resurrection time\\r\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n\\r\\n // Confirm resurrection time has not yet passed\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time is in future\\r\\n if (block.timestamp >= resurrectionTime) {\\r\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\r\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\r\\n revert NewResurrectionTimeTooFarInFuture(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagus.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\r\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\r\\n\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n // Previous digging fees calculation ignores curseFee\\r\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\r\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (resurrectionTime - block.timestamp);\\r\\n\\r\\n // If the new digging fees are greater than the previous digging fees, we need to\\r\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\r\\n if (newDiggingFees > prevDiggingFees) {\\r\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\r\\n if (cursedBondIncrease > prevDiggingFees) {\\r\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.resurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond += cursedBondIncrease;\\r\\n\\r\\n // Rewards are now previous digging fees - difference\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\r\\n } else if (newDiggingFees < prevDiggingFees) {\\r\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\r\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // Decrease archaeologist's cursed bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond -= cursedBondDecrease;\\r\\n\\r\\n // Increase archaeologist's free bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .freeBond += cursedBondDecrease;\\r\\n\\r\\n // Rewards are equal to the previous digging fees\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n } else {\\r\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n }\\r\\n\\r\\n // Add digging fees due for the new interval\\r\\n totalDiggingFees += newDiggingFees;\\r\\n\\r\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee and unlock the curseFee bond\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n // Pay archaeologists the curse fee to their rewards\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\r\\n\\r\\n // Unlock the curseFee cursed bond by debiting the cursed bond and crediting free bond\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].cursedBond -= ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].freeBond += ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n }\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n\\r\\n // Add the protocol fee to the total protocol fees in storage\\r\\n s.totalProtocolFees += protocolFees;\\r\\n\\r\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\r\\n sarcophagus.resurrectionTime = resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = block.timestamp;\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n sarcophagus.isRewrapped = true;\\r\\n }\\r\\n\\r\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\r\\n\\r\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\r\\n }\\r\\n\\r\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\r\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n function burySarcophagus(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n // Confirm that the current resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Set resurrection time to infinity\\r\\n sarcophagus.resurrectionTime = type(uint256).max;\\r\\n\\r\\n emit BurySarcophagus(sarcoId);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x9b019288bbff9433124bcccab5f8099b19e9f3bf1a9588221c30b4c5da1106dc\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\ncontract ThirdPartyFacet {\\r\\n event AccuseArchaeologist(\\r\\n bytes32 indexed sarcoId,\\r\\n address indexed accuser,\\r\\n uint256 totalSlashedBondDistributed,\\r\\n uint256 totalDiggingFeesDistributed,\\r\\n address[] accusedArchAddresses\\r\\n );\\r\\n\\r\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\r\\n\\r\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\r\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\r\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\r\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\r\\n\\r\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\r\\n /// @param senderAddress Address of sender\\r\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\r\\n\\r\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\r\\n /// @param currentTime Timestamp of the failed accuse attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\r\\n /// @param signatures the number of signatures passed into the accuse call\\r\\n /// @param publicKeys the number of public keys passed into the accuse call\\r\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\r\\n /// @param sarcoId that should have been signed\\r\\n /// @param paymentAddress payment address that should have been signed\\r\\n /// @param publicKey publicKey that should be derived from signing key\\r\\n /// @param signature invalid signature\\r\\n error InvalidAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes publicKey,\\r\\n LibTypes.Signature signature\\r\\n );\\r\\n\\r\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\r\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\r\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\r\\n /// be able to claim remaining locked bond and diggingFees\\r\\n /// @param sarcoId The identifier of the sarcophagus to clean\\r\\n function clean(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer or admin\\r\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\r\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not already been cleaned\\r\\n if (sarcophagus.isCleaned) {\\r\\n revert SarcophagusAlreadyCleaned(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm that the resurrectionTime + gracePeriod have passed\\r\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\r\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\r\\n }\\r\\n\\r\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\r\\n if (\\r\\n msg.sender == sarcophagus.embalmerAddress &&\\r\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert EmbalmerClaimWindowPassed(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // if sender is admin, confirm embalmerClaimWindow has passed\\r\\n if (\\r\\n msg.sender == LibDiamond.contractOwner() &&\\r\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert TooEarlyForAdminClean(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\r\\n uint256 totalDiggingFeesAndLockedBonds;\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\r\\n\\r\\n // Punish archaeologists that failed to publish their private key in time\\r\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\r\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeesDue += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\r\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\r\\n\\r\\n // slash the archaeologist's locked bond for the sarcophagus\\r\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\r\\n // this to the contract's protocol fees\\r\\n if (msg.sender == sarcophagus.embalmerAddress) {\\r\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\r\\n } else {\\r\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\r\\n }\\r\\n\\r\\n sarcophagus.isCleaned = true;\\r\\n emit Clean(sarcoId, msg.sender);\\r\\n }\\r\\n\\r\\n /**\\r\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\r\\n * and payment address generated with the leaked private keys\\r\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\r\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\r\\n *\\r\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\r\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\r\\n * returned\\r\\n *\\r\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\r\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\r\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\r\\n * @param paymentAddress the address to which rewards should be sent if successful\\r\\n */\\r\\n function accuse(\\r\\n bytes32 sarcoId,\\r\\n bytes[] calldata publicKeys,\\r\\n LibTypes.Signature[] calldata signatures,\\r\\n address paymentAddress\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // verify that current time is not past resurrection time\\r\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n uint256 nSigs = signatures.length;\\r\\n\\r\\n if (nSigs != publicKeys.length) {\\r\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\r\\n }\\r\\n\\r\\n address[] memory accusedArchAddresses = new address[](nSigs);\\r\\n\\r\\n // track the combined locked bond across all archaeologists being accused in this call\\r\\n uint256 totalCursedBond;\\r\\n uint256 accusalCount;\\r\\n for (uint256 i; i < nSigs; ) {\\r\\n if (\\r\\n !LibUtils.verifyAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n )\\r\\n ) {\\r\\n revert InvalidAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n );\\r\\n }\\r\\n\\r\\n // look up the archaeologist responsible for the publicKey\\r\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\r\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[accusedArchaeologistAddress];\\r\\n\\r\\n // verify the accused archaeologist is cursed on the sarcophagus\\r\\n if (accusedArchaeologist.publicKey.length == 0) {\\r\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\r\\n }\\r\\n\\r\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\r\\n if (accusedArchaeologist.isAccused) {\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n continue;\\r\\n }\\r\\n\\r\\n // mark the archaeologist on the sarcophagus as having been accused\\r\\n accusedArchaeologist.isAccused = true;\\r\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\r\\n\\r\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\r\\n sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\r\\n }\\r\\n\\r\\n totalCursedBond += cursedBondDue;\\r\\n\\r\\n // Slash the offending archaeologists bond\\r\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\r\\n if (accusalCount == 0) {\\r\\n return;\\r\\n }\\r\\n\\r\\n {\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\r\\n if (accusalCount >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n } else {\\r\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\r\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\r\\n uint256 totalAccusals;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n ++totalAccusals;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\r\\n if (totalAccusals >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n }\\r\\n }\\r\\n\\r\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\r\\n // be returned to the remaining well behaved archaeologists\\r\\n if (sarcophagus.isCompromised) {\\r\\n // iterate through all archaeologist addresses on the sarcophagus\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n // if the archaeologist has never been accused, release their locked bond back to them\\r\\n if (\\r\\n !sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n LibBonds.freeArchaeologist(\\r\\n sarcoId,\\r\\n sarcophagus.cursedArchaeologistAddresses[i]\\r\\n );\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\r\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\r\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\r\\n s.sarcoToken.transfer(\\r\\n sarcophagus.embalmerAddress,\\r\\n totalDiggingFees + halfTotalCursedBond\\r\\n );\\r\\n\\r\\n // transfer the other half of the cursed bond to the transaction caller\\r\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\r\\n\\r\\n emit AccuseArchaeologist(\\r\\n sarcoId,\\r\\n msg.sender,\\r\\n totalCursedBond,\\r\\n totalDiggingFees,\\r\\n accusedArchAddresses\\r\\n );\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xc4a28de898fe399da500fae3d4cd8ff0a300f3dedbc2548d8c54940fd76a7ea1\",\"license\":\"Unlicense\"},\"contracts/facets/ViewStateFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport \\\"../libraries/LibUtils.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\n\\r\\ncontract ViewStateFacet {\\r\\n /// @notice Get the admin address from diamond storage\\r\\n /// @return The admin address\\r\\n function getAdmin() external view returns (address) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.admin;\\r\\n }\\r\\n\\r\\n /// @notice Gets the total protocol fees from diamond storage\\r\\n /// @return The total protocol fees\\r\\n function getTotalProtocolFees() external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.totalProtocolFees;\\r\\n }\\r\\n\\r\\n /// @notice Get the protocol fee base percentage from diamond storage\\r\\n /// @return The protocol fee base percentage - protocolFeeBasePercentage\\r\\n function getProtocolFeeBasePercentage() external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.protocolFeeBasePercentage;\\r\\n }\\r\\n\\r\\n /// @notice Get the cursed bond percentage from diamond storage\\r\\n /// @return The cursed bond percentage - cursedBondPercentage\\r\\n function getCursedBondPercentage() external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.cursedBondPercentage;\\r\\n }\\r\\n\\r\\n /// @notice Gets archaeologist profiles given a list of archaeologist addresses.\\r\\n /// If an invalid address is included, simply leaves it out of the list.\\r\\n /// @param addresses The list of archaeologist addresses\\r\\n /// @return The list of archaeologist profiles\\r\\n function getArchaeologistProfiles(\\r\\n address[] memory addresses\\r\\n ) external view returns (LibTypes.ArchaeologistProfile[] memory) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n uint256 nAddresses = addresses.length;\\r\\n LibTypes.ArchaeologistProfile[] memory profiles = new LibTypes.ArchaeologistProfile[](\\r\\n nAddresses\\r\\n );\\r\\n\\r\\n for (uint256 i; i < nAddresses; ) {\\r\\n // Skip unregistered archaeologists\\r\\n if (s.archaeologistProfiles[addresses[i]].maximumRewrapInterval == 0) {\\r\\n continue;\\r\\n }\\r\\n profiles[i] = s.archaeologistProfiles[addresses[i]];\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n return profiles;\\r\\n }\\r\\n\\r\\n /// @notice Gets the grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time passes\\r\\n /// @return The resurrection grace period\\r\\n function getGracePeriod() external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.gracePeriod;\\r\\n }\\r\\n\\r\\n /// @notice Gets the window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys\\r\\n /// @return The embalmer claim window\\r\\n function getEmbalmerClaimWindow() external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.embalmerClaimWindow;\\r\\n }\\r\\n\\r\\n /// @notice Gets the expiration threshold after which a sarcophagus must be renegotiated\\r\\n /// @return The expiration threshold\\r\\n function getExpirationThreshold() external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.expirationThreshold;\\r\\n }\\r\\n\\r\\n /// @notice Given an archaeologist address, return that archaeologist's\\r\\n /// profile\\r\\n /// @param archaeologist The archaeologist account's address\\r\\n /// @return the Archaeologist object\\r\\n function getArchaeologistProfile(\\r\\n address archaeologist\\r\\n ) external view returns (LibTypes.ArchaeologistProfile memory) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibUtils.revertIfArchProfileDoesNotExist(archaeologist);\\r\\n return s.archaeologistProfiles[archaeologist];\\r\\n }\\r\\n\\r\\n /// @notice Return the list of registereed archaeologist addresses.\\r\\n /// @return addresses of registered archaeologists\\r\\n function getArchaeologistProfileAddresses() external view returns (address[] memory) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.archaeologistProfileAddresses;\\r\\n }\\r\\n\\r\\n /// @notice Given an index (of the full archaeologist array), return the\\r\\n /// archaeologist address at that index\\r\\n /// @param index The index of the registered archaeologist\\r\\n /// @return address of the archaeologist\\r\\n function getArchaeologistProfileAddressAtIndex(uint256 index) external view returns (address) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.archaeologistProfileAddresses[index];\\r\\n }\\r\\n\\r\\n /// @notice Returns the amount of free bond stored in the contract for an\\r\\n /// archaeologist.\\r\\n /// @param archaeologist The address of the archaeologist whose\\r\\n /// free bond is being returned\\r\\n function getFreeBond(address archaeologist) external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.archaeologistProfiles[archaeologist].freeBond;\\r\\n }\\r\\n\\r\\n /// @notice Returns the amount of rewards stored in the contract for an\\r\\n /// archaeologist.\\r\\n /// @param archaeologist The address of the archaeologist whose\\r\\n /// reward is being returned\\r\\n function getRewards(address archaeologist) external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.archaeologistRewards[archaeologist];\\r\\n }\\r\\n\\r\\n /// @notice Returns the amount of cursed bond stored in the contract for an\\r\\n /// archaeologist.\\r\\n /// @param archaeologist The address of the archaeologist whose\\r\\n /// cursed bond is being returned\\r\\n function getCursedBond(address archaeologist) external view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.archaeologistProfiles[archaeologist].cursedBond;\\r\\n }\\r\\n\\r\\n struct SarcophagusResponse {\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n string name;\\r\\n uint8 threshold;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n uint256 cursedBondPercentage;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] archaeologistAddresses;\\r\\n uint8 publishedPrivateKeyCount;\\r\\n bool hasLockedBond;\\r\\n }\\r\\n\\r\\n /// @notice Returns data on the sarcophagus with the supplied id\\r\\n /// includes aggregate data on cursed archaeologists associated with the sarcophagus\\r\\n /// - publishedPrivateKeyCount - the total number of private keys published by archaeologists on the sarcophagus\\r\\n /// - hasLockedBond - true if archaeologists still have bond locked in the contract for this sarcophagus\\r\\n /// @param sarcoId The identifier of the sarcophagus being returned\\r\\n function getSarcophagus(bytes32 sarcoId) external view returns (SarcophagusResponse memory) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n uint8 publishedPrivateKeyCount;\\r\\n bool hasLockedBond;\\r\\n uint256 archsLength = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n for (uint256 i; i < archsLength; ) {\\r\\n // archaeologist has published a private key\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .privateKey != 0\\r\\n ) {\\r\\n ++publishedPrivateKeyCount;\\r\\n } else if (\\r\\n !sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused &&\\r\\n !sarcophagus.isCompromised &&\\r\\n !sarcophagus.isCleaned &&\\r\\n sarcophagus.resurrectionTime != type(uint256).max\\r\\n ) {\\r\\n // if the sarcophagus is not compromised, buried, or cleaned and\\r\\n // one or more unaccused archaeologists hasn't published a private key there is locked bond on the sarcophagus\\r\\n hasLockedBond = true;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n return\\r\\n SarcophagusResponse({\\r\\n resurrectionTime: sarcophagus.resurrectionTime,\\r\\n previousRewrapTime: sarcophagus.previousRewrapTime,\\r\\n isCompromised: sarcophagus.isCompromised,\\r\\n isCleaned: sarcophagus.isCleaned,\\r\\n name: sarcophagus.name,\\r\\n threshold: sarcophagus.threshold,\\r\\n maximumRewrapInterval: sarcophagus.maximumRewrapInterval,\\r\\n maximumResurrectionTime: sarcophagus.maximumResurrectionTime,\\r\\n cursedBondPercentage: sarcophagus.cursedBondPercentage,\\r\\n arweaveTxId: sarcophagus.arweaveTxId,\\r\\n embalmerAddress: sarcophagus.embalmerAddress,\\r\\n recipientAddress: sarcophagus.recipientAddress,\\r\\n archaeologistAddresses: sarcophagus.cursedArchaeologistAddresses,\\r\\n publishedPrivateKeyCount: publishedPrivateKeyCount,\\r\\n hasLockedBond: hasLockedBond\\r\\n });\\r\\n }\\r\\n\\r\\n /// @notice Returns the data stored on a sarcophagus for an archaeologist.\\r\\n /// @param sarcoId The identifier of the sarcophagus whose data is being\\r\\n /// returned\\r\\n /// @param archaeologist The address of the archaeologist whose data is\\r\\n /// being returned\\r\\n function getSarcophagusArchaeologist(\\r\\n bytes32 sarcoId,\\r\\n address archaeologist\\r\\n ) external view returns (LibTypes.CursedArchaeologist memory) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n return s.sarcophagi[sarcoId].cursedArchaeologists[archaeologist];\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x0b9edef8cd2f9c6a5e2a73dae6417ef14b407ac9a4ab564608a4b2153ce58e47\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\r\\n\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\nlibrary LibBonds {\\r\\n /// @notice Bonds the archaeologist to a sarcophagus.\\r\\n /// This does the following:\\r\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\r\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\r\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\r\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\r\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\r\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\r\\n ///\\r\\n /// @return the amount of digging fees due the embalmer for this curse\\r\\n function curseArchaeologist(\\r\\n bytes32 sarcoId,\\r\\n EmbalmerFacet.CurseParams calldata archaeologist,\\r\\n uint256 index\\r\\n ) internal returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\r\\n publicKey: archaeologist.publicKey,\\r\\n privateKey: 0,\\r\\n isAccused: false,\\r\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\r\\n curseFee: archaeologist.curseFee\\r\\n });\\r\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\r\\n\\r\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\r\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\r\\n + archaeologist.curseFee;\\r\\n\\r\\n // Use cursed bond percentage to determine how much bond to lock up\\r\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\r\\n\\r\\n // Transfer bond to curse from free bond to cursed bond\\r\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\r\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\r\\n\\r\\n return diggingFeesDue;\\r\\n }\\r\\n\\r\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\r\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\r\\n /// @param archaeologistAddress the address of the archaeologist to free\\r\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\r\\n .sarcophagi[sarcoId]\\r\\n .cursedArchaeologists[archaeologistAddress];\\r\\n\\r\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\r\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondAmount = (diggingFeeAmount * sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\r\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\r\\n\\r\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x8c0a7c621ffa042eee7a312fb919102bf8af87daf434bfc07819acb5b3c06dd9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title A collection of Errors\\r\\n * @notice This library defines all of the Errors that the Sarcophagus system\\r\\n * uses.\\r\\n */\\r\\nlibrary LibErrors {\\r\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\r\\n\\r\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\r\\n\\r\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\r\\n\\r\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\r\\n\\r\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusInactive(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusCompromised(bytes32 sarcoId);\\r\\n\\r\\n error SenderNotEmbalmer(address sender, address embalmer);\\r\\n\\r\\n error InvalidSignature(\\r\\n // address recovered from signature via ecrecover\\r\\n address recoveredAddress,\\r\\n // address we expected to have signed the data\\r\\n address expectedAddress\\r\\n );\\r\\n}\\r\\n\",\"keccak256\":\"0xa0a8e8a9d339d070e5bf21d4b0462e5eb947a60acec58d0cb1013006b6d73cac\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Types shared across facets for the Sarcophagus diamond\\r\\n */\\r\\nlibrary LibTypes {\\r\\n struct Sarcophagus {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n bool isRewrapped;\\r\\n uint8 threshold;\\r\\n string name;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] cursedArchaeologistAddresses;\\r\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\r\\n uint256 cursedBondPercentage;\\r\\n }\\r\\n\\r\\n struct CursedArchaeologist {\\r\\n uint256 diggingFeePerSecond;\\r\\n // Also used for publish checks -- has not published if 0\\r\\n bytes32 privateKey;\\r\\n // Also used for curse checks -- is not bonded if length is 0\\r\\n bytes publicKey;\\r\\n bool isAccused;\\r\\n uint256 curseFee;\\r\\n }\\r\\n\\r\\n struct Signature {\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n struct ArchaeologistProfile {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string peerId;\\r\\n uint256 minimumDiggingFeePerSecond;\\r\\n uint256 freeBond;\\r\\n uint256 cursedBond;\\r\\n uint256 curseFee;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x096d9660852c5179b16d71abe3a818282db9e980fdc431efa77bd92577d60fb8\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\r\\nimport \\\"./LibTypes.sol\\\";\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\n/**\\r\\n * @title Utility functions used within the Sarcophagus system\\r\\n * @notice This library implements various functions that are used throughout\\r\\n * Sarcophagus, mainly to DRY up the codebase\\r\\n * @dev these functions are all stateless, public, pure/view\\r\\n */\\r\\nlibrary LibUtils {\\r\\n /**\\r\\n * @notice The archaeologist needs to sign off on two pieces of data\\r\\n * to guarantee their unrwap will be successful\\r\\n *\\r\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\r\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\r\\n * @param curseParams parameters of curse signed by archaeologist\\r\\n */\\r\\n function verifyArchaeologistSignature(\\r\\n uint256 agreedMaximumRewrapInterval,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 timestamp,\\r\\n EmbalmerFacet.CurseParams calldata curseParams\\r\\n ) internal pure {\\r\\n // Hash the hash of the data payload\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(\\r\\n abi.encode(\\r\\n curseParams.publicKey,\\r\\n agreedMaximumRewrapInterval,\\r\\n maximumResurrectionTime,\\r\\n curseParams.diggingFeePerSecond,\\r\\n timestamp,\\r\\n curseParams.curseFee\\r\\n )\\r\\n )\\r\\n )\\r\\n );\\r\\n\\r\\n // Generate the address from the signature.\\r\\n // ecrecover should always return a valid address.\\r\\n address recoveredAddress = ecrecover(\\r\\n messageHash,\\r\\n curseParams.v,\\r\\n curseParams.r,\\r\\n curseParams.s\\r\\n );\\r\\n\\r\\n if (recoveredAddress != curseParams.archAddress) {\\r\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Verifies that a signature and public key were created from the same private key\\r\\n /// @param sarcoId the sarcoId that was signed\\r\\n /// @param paymentAddress the payment address that was signed\\r\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\r\\n /// @param signature signature on the sarco id and payment address\\r\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\r\\n function verifyAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes calldata publicKey,\\r\\n LibTypes.Signature calldata signature\\r\\n ) internal pure returns (bool) {\\r\\n // removes the 0x04 prefix from an uncompressed public key\\r\\n uint256 pubKeyLength = publicKey.length;\\r\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\r\\n for (uint256 i = 1; i < pubKeyLength; ) {\\r\\n truncatedPublicKey[i - 1] = publicKey[i];\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(abi.encode(sarcoId, paymentAddress))\\r\\n )\\r\\n );\\r\\n // Use ecrecover to get the address that signed the message\\r\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\r\\n\\r\\n address publicKeyAddress = address(\\r\\n uint160(\\r\\n uint256(keccak256(truncatedPublicKey)) &\\r\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\r\\n )\\r\\n );\\r\\n\\r\\n return signingAddress == publicKeyAddress;\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile exists and\\r\\n /// reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check existence of\\r\\n function revertIfArchProfileExists(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check lack of existence of\\r\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\r\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\r\\n /// @return The protocol fees amount\\r\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x4e6fa08e9f931ba0ef0c2c5b0938be70124d00b94c86a3a4ae303472cd5c8fb8\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\n/**\\r\\n * Global diamond storage struct to be shared across facets\\r\\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\\r\\n */\\r\\nstruct AppStorage {\\r\\n // SARCO token contract\\r\\n IERC20 sarcoToken;\\r\\n // The Admin address allowed to call Admin Facet functions\\r\\n address admin;\\r\\n // total protocol fees available to be withdrawn by the admin\\r\\n uint256 totalProtocolFees;\\r\\n /**\\r\\n * Protocol level admin configurations\\r\\n */\\r\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\r\\n uint256 protocolFeeBasePercentage;\\r\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\r\\n uint256 cursedBondPercentage;\\r\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\r\\n uint256 gracePeriod;\\r\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\r\\n uint256 expirationThreshold;\\r\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\r\\n uint256 embalmerClaimWindow;\\r\\n // registered archaeologist addresses\\r\\n address[] archaeologistProfileAddresses;\\r\\n // public key => archaeologist address\\r\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\r\\n // sarcophagus id => sarcophagus object\\r\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\r\\n // archaeologist address => profile\\r\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\r\\n // current balance of rewards available for the archaeologist to withdraw\\r\\n mapping(address => uint256) archaeologistRewards;\\r\\n}\\r\\n\\r\\nlibrary LibAppStorage {\\r\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\r\\n\\r\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n assembly {\\r\\n s.slot := position\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x66f7100a037fcc417379e68914a8831d867f3701c39419f8f04a3af27008438c\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50611de3806100206000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80638fbd55d211610097578063dbd1838811610066578063dbd18388146102d9578063dc231f43146102f7578063dcfcb90114610327578063de116f061461034557610100565b80638fbd55d21461023d5780639c5456391461026d5780639fdaded11461028b578063a9328dcc146102a957610100565b80636e9960c3116100d35780636e9960c3146101a157806379ee54f7146101bf5780637aa9fd2f146101ef57806387927ce61461020d57610100565b806331baea67146101055780633fbb89301461012357806342e10bc81461014157806357babbaf14610171575b600080fd5b61010d610375565b60405161011a9190611221565b60405180910390f35b61012b61038d565b604051610138919061132c565b60405180910390f35b61015b6004803603810190610156919061138e565b61042a565b60405161016891906114f6565b60405180910390f35b61018b60048036038101906101869190611544565b610569565b6040516101989190611580565b60405180910390f35b6101a96105bf565b6040516101b69190611580565b60405180910390f35b6101d960048036038101906101d4919061138e565b6105f7565b6040516101e69190611221565b60405180910390f35b6101f761064e565b6040516102049190611221565b60405180910390f35b6102276004803603810190610222919061138e565b610666565b6040516102349190611221565b60405180910390f35b6102576004803603810190610252919061138e565b6106c0565b6040516102649190611221565b60405180910390f35b61027561071a565b6040516102829190611221565b60405180910390f35b610293610732565b6040516102a09190611221565b60405180910390f35b6102c360048036038101906102be91906116e3565b61074a565b6040516102d0919061188a565b60405180910390f35b6102e1610992565b6040516102ee9190611221565b60405180910390f35b610311600480360381019061030c91906118e2565b6109aa565b60405161031e9190611a17565b60405180910390f35b61032f610af2565b60405161033c9190611221565b60405180910390f35b61035f600480360381019061035a9190611a39565b610b0a565b60405161036c9190611c42565b60405180910390f35b600080610380611020565b9050806007015491505090565b60606000610399611020565b90508060080180548060200260200160405190810160405280929190818152602001828054801561041f57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116103d5575b505050505091505090565b6104326110e9565b600061043c611020565b90506104478361104d565b80600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546104b790611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546104e390611c93565b80156105305780601f1061050557610100808354040283529160200191610530565b820191906000526020600020905b81548152906001019060200180831161051357829003601f168201915b50505050508152602001600382015481526020016004820154815260200160058201548152602001600682015481525050915050919050565b600080610574611020565b905080600801838154811061058c5761058b611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6000806105ca611020565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b600080610602611020565b905080600c0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054915050919050565b600080610659611020565b9050806006015491505090565b600080610671611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154915050919050565b6000806106cb611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040154915050919050565b600080610725611020565b9050806002015491505090565b60008061073d611020565b9050806003015491505090565b60606000610756611020565b905060008351905060008167ffffffffffffffff81111561077a576107796115a0565b5b6040519080825280602002602001820160405280156107b357816020015b6107a06110e9565b8152602001906001900390816107985790505b50905060005b8281101561098657600084600b0160008884815181106107dc576107db611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403156109815783600b01600087838151811061084157610840611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546108b290611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546108de90611c93565b801561092b5780601f106109005761010080835404028352916020019161092b565b820191906000526020600020905b81548152906001019060200180831161090e57829003601f168201915b5050505050815260200160038201548152602001600482015481526020016005820154815260200160068201548152505082828151811061096f5761096e611cc4565b5b60200260200101819052508060010190505b6107b9565b50809350505050919050565b60008061099d611020565b9050806005015491505090565b6109b2611126565b60006109bc611020565b905080600a016000858152602001908152602001600020600a0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820154815260200160018201548152602001600282018054610a4290611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6e90611c93565b8015610abb5780601f10610a9057610100808354040283529160200191610abb565b820191906000526020600020905b815481529060010190602001808311610a9e57829003601f168201915b505050505081526020016003820160009054906101000a900460ff1615151515815260200160048201548152505091505092915050565b600080610afd611020565b9050806004015491505090565b610b1261115a565b6000610b1c611020565b9050600081600a01600085815260200190815260200160002090506000816000015403610b8057836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610b779190611d02565b60405180910390fd5b60008060008360090180549050905060005b81811015610d48576000801b85600a016000876009018481548110610bba57610bb9611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015414610c395783610c3290611d4c565b9350610d3d565b84600a016000866009018381548110610c5557610c54611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff16158015610ce757508460020160009054906101000a900460ff16155b8015610d0257508460020160019054906101000a900460ff16155b8015610d3257507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff856000015414155b15610d3c57600192505b5b806001019050610b92565b50604051806101e0016040528085600001548152602001856001015481526020018560020160009054906101000a900460ff16151581526020018560020160019054906101000a900460ff1615158152602001856003018054610daa90611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd690611c93565b8015610e235780601f10610df857610100808354040283529160200191610e23565b820191906000526020600020905b815481529060010190602001808311610e0657829003601f168201915b505050505081526020018560020160039054906101000a900460ff1660ff168152602001856004015481526020018560050154815260200185600b01548152602001856006018054610e7490611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610ea090611c93565b8015610eed5780601f10610ec257610100808354040283529160200191610eed565b820191906000526020600020905b815481529060010190602001808311610ed057829003601f168201915b505050505081526020018560070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018560080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185600901805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610fb1575b505050505081526020018460ff16815260200183151581525095505050505050919050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000611057611020565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154036110e5576001826040517f2eeb35710000000000000000000000000000000000000000000000000000000081526004016110dc929190611d84565b60405180910390fd5b5050565b6040518060e00160405280600081526020016000815260200160608152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280600081526020016000801916815260200160608152602001600015158152602001600081525090565b604051806101e00160405280600081526020016000815260200160001515815260200160001515815260200160608152602001600060ff16815260200160008152602001600081526020016000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600060ff1681526020016000151581525090565b6000819050919050565b61121b81611208565b82525050565b60006020820190506112366000830184611212565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061129382611268565b9050919050565b6112a381611288565b82525050565b60006112b5838361129a565b60208301905092915050565b6000602082019050919050565b60006112d98261123c565b6112e38185611247565b93506112ee83611258565b8060005b8381101561131f57815161130688826112a9565b9750611311836112c1565b9250506001810190506112f2565b5085935050505092915050565b6000602082019050818103600083015261134681846112ce565b905092915050565b6000604051905090565b600080fd5b600080fd5b61136b81611288565b811461137657600080fd5b50565b60008135905061138881611362565b92915050565b6000602082840312156113a4576113a3611358565b5b60006113b284828501611379565b91505092915050565b6113c481611208565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156114045780820151818401526020810190506113e9565b60008484015250505050565b6000601f19601f8301169050919050565b600061142c826113ca565b61143681856113d5565b93506114468185602086016113e6565b61144f81611410565b840191505092915050565b600060e08301600083015161147260008601826113bb565b50602083015161148560208601826113bb565b506040830151848203604086015261149d8282611421565b91505060608301516114b260608601826113bb565b5060808301516114c560808601826113bb565b5060a08301516114d860a08601826113bb565b5060c08301516114eb60c08601826113bb565b508091505092915050565b60006020820190508181036000830152611510818461145a565b905092915050565b61152181611208565b811461152c57600080fd5b50565b60008135905061153e81611518565b92915050565b60006020828403121561155a57611559611358565b5b60006115688482850161152f565b91505092915050565b61157a81611288565b82525050565b60006020820190506115956000830184611571565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6115d882611410565b810181811067ffffffffffffffff821117156115f7576115f66115a0565b5b80604052505050565b600061160a61134e565b905061161682826115cf565b919050565b600067ffffffffffffffff821115611636576116356115a0565b5b602082029050602081019050919050565b600080fd5b600061165f61165a8461161b565b611600565b9050808382526020820190506020840283018581111561168257611681611647565b5b835b818110156116ab57806116978882611379565b845260208401935050602081019050611684565b5050509392505050565b600082601f8301126116ca576116c961159b565b5b81356116da84826020860161164c565b91505092915050565b6000602082840312156116f9576116f8611358565b5b600082013567ffffffffffffffff8111156117175761171661135d565b5b611723848285016116b5565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600060e08301600083015161177060008601826113bb565b50602083015161178360208601826113bb565b506040830151848203604086015261179b8282611421565b91505060608301516117b060608601826113bb565b5060808301516117c360808601826113bb565b5060a08301516117d660a08601826113bb565b5060c08301516117e960c08601826113bb565b508091505092915050565b60006118008383611758565b905092915050565b6000602082019050919050565b60006118208261172c565b61182a8185611737565b93508360208202850161183c85611748565b8060005b85811015611878578484038952815161185985826117f4565b945061186483611808565b925060208a01995050600181019050611840565b50829750879550505050505092915050565b600060208201905081810360008301526118a48184611815565b905092915050565b6000819050919050565b6118bf816118ac565b81146118ca57600080fd5b50565b6000813590506118dc816118b6565b92915050565b600080604083850312156118f9576118f8611358565b5b6000611907858286016118cd565b925050602061191885828601611379565b9150509250929050565b61192b816118ac565b82525050565b600081519050919050565b600082825260208201905092915050565b600061195882611931565b611962818561193c565b93506119728185602086016113e6565b61197b81611410565b840191505092915050565b60008115159050919050565b61199b81611986565b82525050565b600060a0830160008301516119b960008601826113bb565b5060208301516119cc6020860182611922565b50604083015184820360408601526119e4828261194d565b91505060608301516119f96060860182611992565b506080830151611a0c60808601826113bb565b508091505092915050565b60006020820190508181036000830152611a3181846119a1565b905092915050565b600060208284031215611a4f57611a4e611358565b5b6000611a5d848285016118cd565b91505092915050565b600060ff82169050919050565b611a7c81611a66565b82525050565b600082825260208201905092915050565b6000611a9e8261123c565b611aa88185611a82565b9350611ab383611258565b8060005b83811015611ae4578151611acb88826112a9565b9750611ad6836112c1565b925050600181019050611ab7565b5085935050505092915050565b60006101e083016000830151611b0a60008601826113bb565b506020830151611b1d60208601826113bb565b506040830151611b306040860182611992565b506060830151611b436060860182611992565b5060808301518482036080860152611b5b8282611421565b91505060a0830151611b7060a0860182611a73565b5060c0830151611b8360c08601826113bb565b5060e0830151611b9660e08601826113bb565b50610100830151611bab6101008601826113bb565b50610120830151848203610120860152611bc58282611421565b915050610140830151611bdc61014086018261129a565b50610160830151611bf161016086018261129a565b50610180830151848203610180860152611c0b8282611a93565b9150506101a0830151611c226101a0860182611a73565b506101c0830151611c376101c0860182611992565b508091505092915050565b60006020820190508181036000830152611c5c8184611af1565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611cab57607f821691505b602082108103611cbe57611cbd611c64565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b611cfc816118ac565b82525050565b6000602082019050611d176000830184611cf3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611d5782611a66565b915060ff8203611d6a57611d69611d1d565b5b600182019050919050565b611d7e81611986565b82525050565b6000604082019050611d996000830185611d75565b611da66020830184611571565b939250505056fea2646970667358221220897335e7e1893ab40b8d6de94b56162cf3190a876e37b616dc0f4e9057f2481564736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80638fbd55d211610097578063dbd1838811610066578063dbd18388146102d9578063dc231f43146102f7578063dcfcb90114610327578063de116f061461034557610100565b80638fbd55d21461023d5780639c5456391461026d5780639fdaded11461028b578063a9328dcc146102a957610100565b80636e9960c3116100d35780636e9960c3146101a157806379ee54f7146101bf5780637aa9fd2f146101ef57806387927ce61461020d57610100565b806331baea67146101055780633fbb89301461012357806342e10bc81461014157806357babbaf14610171575b600080fd5b61010d610375565b60405161011a9190611221565b60405180910390f35b61012b61038d565b604051610138919061132c565b60405180910390f35b61015b6004803603810190610156919061138e565b61042a565b60405161016891906114f6565b60405180910390f35b61018b60048036038101906101869190611544565b610569565b6040516101989190611580565b60405180910390f35b6101a96105bf565b6040516101b69190611580565b60405180910390f35b6101d960048036038101906101d4919061138e565b6105f7565b6040516101e69190611221565b60405180910390f35b6101f761064e565b6040516102049190611221565b60405180910390f35b6102276004803603810190610222919061138e565b610666565b6040516102349190611221565b60405180910390f35b6102576004803603810190610252919061138e565b6106c0565b6040516102649190611221565b60405180910390f35b61027561071a565b6040516102829190611221565b60405180910390f35b610293610732565b6040516102a09190611221565b60405180910390f35b6102c360048036038101906102be91906116e3565b61074a565b6040516102d0919061188a565b60405180910390f35b6102e1610992565b6040516102ee9190611221565b60405180910390f35b610311600480360381019061030c91906118e2565b6109aa565b60405161031e9190611a17565b60405180910390f35b61032f610af2565b60405161033c9190611221565b60405180910390f35b61035f600480360381019061035a9190611a39565b610b0a565b60405161036c9190611c42565b60405180910390f35b600080610380611020565b9050806007015491505090565b60606000610399611020565b90508060080180548060200260200160405190810160405280929190818152602001828054801561041f57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116103d5575b505050505091505090565b6104326110e9565b600061043c611020565b90506104478361104d565b80600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546104b790611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546104e390611c93565b80156105305780601f1061050557610100808354040283529160200191610530565b820191906000526020600020905b81548152906001019060200180831161051357829003601f168201915b50505050508152602001600382015481526020016004820154815260200160058201548152602001600682015481525050915050919050565b600080610574611020565b905080600801838154811061058c5761058b611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6000806105ca611020565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b600080610602611020565b905080600c0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054915050919050565b600080610659611020565b9050806006015491505090565b600080610671611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154915050919050565b6000806106cb611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040154915050919050565b600080610725611020565b9050806002015491505090565b60008061073d611020565b9050806003015491505090565b60606000610756611020565b905060008351905060008167ffffffffffffffff81111561077a576107796115a0565b5b6040519080825280602002602001820160405280156107b357816020015b6107a06110e9565b8152602001906001900390816107985790505b50905060005b8281101561098657600084600b0160008884815181106107dc576107db611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403156109815783600b01600087838151811061084157610840611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546108b290611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546108de90611c93565b801561092b5780601f106109005761010080835404028352916020019161092b565b820191906000526020600020905b81548152906001019060200180831161090e57829003601f168201915b5050505050815260200160038201548152602001600482015481526020016005820154815260200160068201548152505082828151811061096f5761096e611cc4565b5b60200260200101819052508060010190505b6107b9565b50809350505050919050565b60008061099d611020565b9050806005015491505090565b6109b2611126565b60006109bc611020565b905080600a016000858152602001908152602001600020600a0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820154815260200160018201548152602001600282018054610a4290611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6e90611c93565b8015610abb5780601f10610a9057610100808354040283529160200191610abb565b820191906000526020600020905b815481529060010190602001808311610a9e57829003601f168201915b505050505081526020016003820160009054906101000a900460ff1615151515815260200160048201548152505091505092915050565b600080610afd611020565b9050806004015491505090565b610b1261115a565b6000610b1c611020565b9050600081600a01600085815260200190815260200160002090506000816000015403610b8057836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610b779190611d02565b60405180910390fd5b60008060008360090180549050905060005b81811015610d48576000801b85600a016000876009018481548110610bba57610bb9611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015414610c395783610c3290611d4c565b9350610d3d565b84600a016000866009018381548110610c5557610c54611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff16158015610ce757508460020160009054906101000a900460ff16155b8015610d0257508460020160019054906101000a900460ff16155b8015610d3257507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff856000015414155b15610d3c57600192505b5b806001019050610b92565b50604051806101e0016040528085600001548152602001856001015481526020018560020160009054906101000a900460ff16151581526020018560020160019054906101000a900460ff1615158152602001856003018054610daa90611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd690611c93565b8015610e235780601f10610df857610100808354040283529160200191610e23565b820191906000526020600020905b815481529060010190602001808311610e0657829003601f168201915b505050505081526020018560020160039054906101000a900460ff1660ff168152602001856004015481526020018560050154815260200185600b01548152602001856006018054610e7490611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610ea090611c93565b8015610eed5780601f10610ec257610100808354040283529160200191610eed565b820191906000526020600020905b815481529060010190602001808311610ed057829003601f168201915b505050505081526020018560070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018560080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185600901805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610fb1575b505050505081526020018460ff16815260200183151581525095505050505050919050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000611057611020565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154036110e5576001826040517f2eeb35710000000000000000000000000000000000000000000000000000000081526004016110dc929190611d84565b60405180910390fd5b5050565b6040518060e00160405280600081526020016000815260200160608152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280600081526020016000801916815260200160608152602001600015158152602001600081525090565b604051806101e00160405280600081526020016000815260200160001515815260200160001515815260200160608152602001600060ff16815260200160008152602001600081526020016000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600060ff1681526020016000151581525090565b6000819050919050565b61121b81611208565b82525050565b60006020820190506112366000830184611212565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061129382611268565b9050919050565b6112a381611288565b82525050565b60006112b5838361129a565b60208301905092915050565b6000602082019050919050565b60006112d98261123c565b6112e38185611247565b93506112ee83611258565b8060005b8381101561131f57815161130688826112a9565b9750611311836112c1565b9250506001810190506112f2565b5085935050505092915050565b6000602082019050818103600083015261134681846112ce565b905092915050565b6000604051905090565b600080fd5b600080fd5b61136b81611288565b811461137657600080fd5b50565b60008135905061138881611362565b92915050565b6000602082840312156113a4576113a3611358565b5b60006113b284828501611379565b91505092915050565b6113c481611208565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156114045780820151818401526020810190506113e9565b60008484015250505050565b6000601f19601f8301169050919050565b600061142c826113ca565b61143681856113d5565b93506114468185602086016113e6565b61144f81611410565b840191505092915050565b600060e08301600083015161147260008601826113bb565b50602083015161148560208601826113bb565b506040830151848203604086015261149d8282611421565b91505060608301516114b260608601826113bb565b5060808301516114c560808601826113bb565b5060a08301516114d860a08601826113bb565b5060c08301516114eb60c08601826113bb565b508091505092915050565b60006020820190508181036000830152611510818461145a565b905092915050565b61152181611208565b811461152c57600080fd5b50565b60008135905061153e81611518565b92915050565b60006020828403121561155a57611559611358565b5b60006115688482850161152f565b91505092915050565b61157a81611288565b82525050565b60006020820190506115956000830184611571565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6115d882611410565b810181811067ffffffffffffffff821117156115f7576115f66115a0565b5b80604052505050565b600061160a61134e565b905061161682826115cf565b919050565b600067ffffffffffffffff821115611636576116356115a0565b5b602082029050602081019050919050565b600080fd5b600061165f61165a8461161b565b611600565b9050808382526020820190506020840283018581111561168257611681611647565b5b835b818110156116ab57806116978882611379565b845260208401935050602081019050611684565b5050509392505050565b600082601f8301126116ca576116c961159b565b5b81356116da84826020860161164c565b91505092915050565b6000602082840312156116f9576116f8611358565b5b600082013567ffffffffffffffff8111156117175761171661135d565b5b611723848285016116b5565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600060e08301600083015161177060008601826113bb565b50602083015161178360208601826113bb565b506040830151848203604086015261179b8282611421565b91505060608301516117b060608601826113bb565b5060808301516117c360808601826113bb565b5060a08301516117d660a08601826113bb565b5060c08301516117e960c08601826113bb565b508091505092915050565b60006118008383611758565b905092915050565b6000602082019050919050565b60006118208261172c565b61182a8185611737565b93508360208202850161183c85611748565b8060005b85811015611878578484038952815161185985826117f4565b945061186483611808565b925060208a01995050600181019050611840565b50829750879550505050505092915050565b600060208201905081810360008301526118a48184611815565b905092915050565b6000819050919050565b6118bf816118ac565b81146118ca57600080fd5b50565b6000813590506118dc816118b6565b92915050565b600080604083850312156118f9576118f8611358565b5b6000611907858286016118cd565b925050602061191885828601611379565b9150509250929050565b61192b816118ac565b82525050565b600081519050919050565b600082825260208201905092915050565b600061195882611931565b611962818561193c565b93506119728185602086016113e6565b61197b81611410565b840191505092915050565b60008115159050919050565b61199b81611986565b82525050565b600060a0830160008301516119b960008601826113bb565b5060208301516119cc6020860182611922565b50604083015184820360408601526119e4828261194d565b91505060608301516119f96060860182611992565b506080830151611a0c60808601826113bb565b508091505092915050565b60006020820190508181036000830152611a3181846119a1565b905092915050565b600060208284031215611a4f57611a4e611358565b5b6000611a5d848285016118cd565b91505092915050565b600060ff82169050919050565b611a7c81611a66565b82525050565b600082825260208201905092915050565b6000611a9e8261123c565b611aa88185611a82565b9350611ab383611258565b8060005b83811015611ae4578151611acb88826112a9565b9750611ad6836112c1565b925050600181019050611ab7565b5085935050505092915050565b60006101e083016000830151611b0a60008601826113bb565b506020830151611b1d60208601826113bb565b506040830151611b306040860182611992565b506060830151611b436060860182611992565b5060808301518482036080860152611b5b8282611421565b91505060a0830151611b7060a0860182611a73565b5060c0830151611b8360c08601826113bb565b5060e0830151611b9660e08601826113bb565b50610100830151611bab6101008601826113bb565b50610120830151848203610120860152611bc58282611421565b915050610140830151611bdc61014086018261129a565b50610160830151611bf161016086018261129a565b50610180830151848203610180860152611c0b8282611a93565b9150506101a0830151611c226101a0860182611a73565b506101c0830151611c376101c0860182611992565b508091505092915050565b60006020820190508181036000830152611c5c8184611af1565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611cab57607f821691505b602082108103611cbe57611cbd611c64565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b611cfc816118ac565b82525050565b6000602082019050611d176000830184611cf3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611d5782611a66565b915060ff8203611d6a57611d69611d1d565b5b600182019050919050565b611d7e81611986565b82525050565b6000604082019050611d996000830185611d75565b611da66020830184611571565b939250505056fea2646970667358221220897335e7e1893ab40b8d6de94b56162cf3190a876e37b616dc0f4e9057f2481564736f6c63430008120033", + "solcInputHash": "69b6ccc89b7eaa4e346529a9a529edba", + "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistProfileExistsShouldBe\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"getAdmin\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getArchaeologistProfile\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"internalType\":\"struct LibTypes.ArchaeologistProfile\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getArchaeologistProfileAddressAtIndex\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getArchaeologistProfileAddresses\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"addresses\",\"type\":\"address[]\"}],\"name\":\"getArchaeologistProfiles\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"internalType\":\"struct LibTypes.ArchaeologistProfile[]\",\"name\":\"\",\"type\":\"tuple[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getCursedBond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getCursedBondPercentage\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getEmbalmerClaimWindow\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getExpirationThreshold\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getFreeBond\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getGracePeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getProtocolFeeBasePercentage\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getRewards\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"getSarcophagus\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"previousRewrapTime\",\"type\":\"uint256\"},{\"internalType\":\"bool\",\"name\":\"isCompromised\",\"type\":\"bool\"},{\"internalType\":\"bool\",\"name\":\"isCleaned\",\"type\":\"bool\"},{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint8\",\"name\":\"threshold\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"},{\"internalType\":\"string\",\"name\":\"arweaveTxId\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"embalmerAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"recipientAddress\",\"type\":\"address\"},{\"internalType\":\"address[]\",\"name\":\"archaeologistAddresses\",\"type\":\"address[]\"},{\"internalType\":\"uint8\",\"name\":\"publishedPrivateKeyCount\",\"type\":\"uint8\"},{\"internalType\":\"bool\",\"name\":\"hasLockedBond\",\"type\":\"bool\"}],\"internalType\":\"struct ViewStateFacet.SarcophagusResponse\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"getSarcophagusArchaeologist\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"diggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bool\",\"name\":\"isAccused\",\"type\":\"bool\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"internalType\":\"struct LibTypes.CursedArchaeologist\",\"name\":\"\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTotalProtocolFees\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"getAdmin()\":{\"returns\":{\"_0\":\"The admin address\"}},\"getArchaeologistProfile(address)\":{\"params\":{\"archaeologist\":\"The archaeologist account's address\"},\"returns\":{\"_0\":\"the Archaeologist object\"}},\"getArchaeologistProfileAddressAtIndex(uint256)\":{\"params\":{\"index\":\"The index of the registered archaeologist\"},\"returns\":{\"_0\":\"address of the archaeologist\"}},\"getArchaeologistProfileAddresses()\":{\"returns\":{\"_0\":\"addresses of registered archaeologists\"}},\"getArchaeologistProfiles(address[])\":{\"params\":{\"addresses\":\"The list of archaeologist addresses\"},\"returns\":{\"_0\":\"The list of archaeologist profiles\"}},\"getCursedBond(address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose cursed bond is being returned\"}},\"getCursedBondPercentage()\":{\"returns\":{\"_0\":\"The cursed bond percentage - cursedBondPercentage\"}},\"getEmbalmerClaimWindow()\":{\"returns\":{\"_0\":\"The embalmer claim window\"}},\"getExpirationThreshold()\":{\"returns\":{\"_0\":\"The expiration threshold\"}},\"getFreeBond(address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose free bond is being returned\"}},\"getGracePeriod()\":{\"returns\":{\"_0\":\"The resurrection grace period\"}},\"getProtocolFeeBasePercentage()\":{\"returns\":{\"_0\":\"The protocol fee base percentage - protocolFeeBasePercentage\"}},\"getRewards(address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose reward is being returned\"}},\"getSarcophagus(bytes32)\":{\"params\":{\"sarcoId\":\"The identifier of the sarcophagus being returned\"}},\"getSarcophagusArchaeologist(bytes32,address)\":{\"params\":{\"archaeologist\":\"The address of the archaeologist whose data is being returned\",\"sarcoId\":\"The identifier of the sarcophagus whose data is being returned\"}},\"getTotalProtocolFees()\":{\"returns\":{\"_0\":\"The total protocol fees\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"getAdmin()\":{\"notice\":\"Get the admin address from diamond storage\"},\"getArchaeologistProfile(address)\":{\"notice\":\"Given an archaeologist address, return that archaeologist's profile\"},\"getArchaeologistProfileAddressAtIndex(uint256)\":{\"notice\":\"Given an index (of the full archaeologist array), return the archaeologist address at that index\"},\"getArchaeologistProfileAddresses()\":{\"notice\":\"Return the list of registereed archaeologist addresses.\"},\"getArchaeologistProfiles(address[])\":{\"notice\":\"Gets archaeologist profiles given a list of archaeologist addresses. If an invalid address is included, simply leaves it out of the list.\"},\"getCursedBond(address)\":{\"notice\":\"Returns the amount of cursed bond stored in the contract for an archaeologist.\"},\"getCursedBondPercentage()\":{\"notice\":\"Get the cursed bond percentage from diamond storage\"},\"getEmbalmerClaimWindow()\":{\"notice\":\"Gets the window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys\"},\"getExpirationThreshold()\":{\"notice\":\"Gets the expiration threshold after which a sarcophagus must be renegotiated\"},\"getFreeBond(address)\":{\"notice\":\"Returns the amount of free bond stored in the contract for an archaeologist.\"},\"getGracePeriod()\":{\"notice\":\"Gets the grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time passes\"},\"getProtocolFeeBasePercentage()\":{\"notice\":\"Get the protocol fee base percentage from diamond storage\"},\"getRewards(address)\":{\"notice\":\"Returns the amount of rewards stored in the contract for an archaeologist.\"},\"getSarcophagus(bytes32)\":{\"notice\":\"Returns data on the sarcophagus with the supplied id includes aggregate data on cursed archaeologists associated with the sarcophagus - publishedPrivateKeyCount - the total number of private keys published by archaeologists on the sarcophagus - hasLockedBond - true if archaeologists still have bond locked in the contract for this sarcophagus\"},\"getSarcophagusArchaeologist(bytes32,address)\":{\"notice\":\"Returns the data stored on a sarcophagus for an archaeologist.\"},\"getTotalProtocolFees()\":{\"notice\":\"Gets the total protocol fees from diamond storage\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ViewStateFacet.sol\":\"ViewStateFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\n\\ncontract EmbalmerFacet {\\n /// @notice Emitted when a sarcophagus is created\\n /// @param sarcoId Id of the new sarcophagus\\n /// @param name Name of the new sarcophagus\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\n /// @param embalmer Address of embalmer\\n /// @param recipient Address of recipient\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\n event CreateSarcophagus(\\n bytes32 indexed sarcoId,\\n string name,\\n uint256 resurrectionTime,\\n uint256 creationTime,\\n address indexed embalmer,\\n address indexed recipient,\\n address[] cursedArchaeologists,\\n uint256 totalDiggingFees,\\n string arweaveTxId\\n );\\n\\n /// @notice Emitted when a sarcophagus is rewrapped\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\n event RewrapSarcophagus(\\n bytes32 indexed sarcoId,\\n uint256 resurrectionTime,\\n uint256 totalDiggingFees,\\n uint256 rewrapSarcophagusProtocolFees\\n );\\n\\n /// @notice Emitted when a sarcophagus is buried\\n /// @param sarcoId Id of sarcophagus that was buried\\n event BurySarcophagus(bytes32 indexed sarcoId);\\n\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\n struct SarcophagusParams {\\n string name;\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\n uint256 maximumRewrapInterval;\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\n uint256 maximumResurrectionTime;\\n address recipientAddress;\\n uint256 resurrectionTime;\\n uint8 threshold;\\n uint256 creationTime;\\n }\\n\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\n struct CurseParams {\\n bytes publicKey;\\n address archAddress;\\n uint256 diggingFeePerSecond;\\n uint256 curseFee;\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\n /// @param sarcoId Id that is already in use\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\n /// @param currentTime Timestamp of the failed create attempt\\n /// @param creationTime Time when the sarcophagus parameters were created\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\n error SarcophagusParametersExpired(\\n uint256 currentTime,\\n uint256 creationTime,\\n uint256 creationDeadline\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\n error NoArchaeologistsProvided();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\n error ThresholdCannotBeZero();\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\n uint8 threshold,\\n uint256 totalNumberOfArchaeologists\\n );\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\n /// @param currentTime Timestamp of the failed rewrap attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\n /// @param publicKey the duplicated public key\\n error DuplicatePublicKey(bytes publicKey);\\n\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\n error ResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\n error ResurrectionTimePastMaxResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 maxResurrectionTime\\n );\\n\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\n\\n error NewResurrectionTimeIsZero();\\n\\n error NewResurrectionTimeTooFarInFuture(\\n uint256 resurrectionTime,\\n uint256 sarcophagusMaximumRewrapInterval,\\n uint256 maximumPermissibleResurrectionTime\\n );\\n\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n uint256 resurrectionTime,\\n uint256 previousResurrectionTime\\n );\\n\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\n /// of the sarcophagus until its resurrection time.\\n ///\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\n /// - `creationTime` of sarcophagus\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\n ///\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param sarcophagusParams params to set on sarcophagus being created\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\n function createSarcophagus(\\n bytes32 sarcoId,\\n SarcophagusParams calldata sarcophagusParams,\\n CurseParams[] calldata selectedArchaeologists,\\n string calldata arweaveTxId\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n // Confirm that sarcophagus with supplied id doesn't already exist\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\n revert SarcophagusAlreadyExists(sarcoId);\\n }\\n\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\n // off by its cursed archaeologists.\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\n revert SarcophagusParametersExpired(\\n block.timestamp,\\n sarcophagusParams.creationTime,\\n sarcophagusParams.creationTime + s.expirationThreshold\\n );\\n }\\n\\n // Confirm that resurrection time is in the future\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\n }\\n\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\n if (\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\n sarcophagusParams.resurrectionTime\\n ) {\\n revert ResurrectionTimeTooFarInFuture(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumRewrapInterval,\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the resurrection time is less than the max resurrection time\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.maximumResurrectionTime\\n );\\n }\\n\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // track total digging fees due upon creation of sarcophagus\\n uint256 totalDiggingFees;\\n\\n {\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\n // Validate archaeologist and threshold lengths\\n if (nSelectedArchs == 0) {\\n revert NoArchaeologistsProvided();\\n }\\n\\n if (sarcophagusParams.threshold == 0) {\\n revert ThresholdCannotBeZero();\\n }\\n\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\n // used to distribute keyshares among archaeologists\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\n sarcophagusParams.threshold,\\n nSelectedArchs\\n );\\n }\\n\\n // create the sarcophagus\\n sarcophagus.name = sarcophagusParams.name;\\n sarcophagus.threshold = sarcophagusParams.threshold;\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\n sarcophagus.arweaveTxId = arweaveTxId;\\n sarcophagus.embalmerAddress = msg.sender;\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\n\\n for (uint256 i; i < nSelectedArchs; ) {\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\n\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\n if (\\n sarcophagus\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\n .publicKey\\n .length != 0\\n ) {\\n revert ArchaeologistListContainsDuplicate(\\n selectedArchaeologists[i].archAddress\\n );\\n }\\n\\n // Confirm archaeologist is not re-using a key pair\\n if (\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\n address(0)\\n ) {\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\n }\\n\\n LibUtils.verifyArchaeologistSignature(\\n sarcophagusParams.maximumRewrapInterval,\\n sarcophagusParams.maximumResurrectionTime,\\n sarcophagusParams.creationTime,\\n selectedArchaeologists[i]\\n );\\n\\n // Curse the archaeologist on this sarcophagus\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\n sarcoId,\\n selectedArchaeologists[i],\\n i\\n );\\n\\n totalDiggingFees += diggingFeesDue;\\n\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\n s.publicKeyToArchaeologistAddress[\\n selectedArchaeologists[i].publicKey\\n ] = selectedArchaeologists[i].archAddress;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n s.totalProtocolFees += protocolFees;\\n s.sarcoToken.transferFrom(\\n msg.sender,\\n address(this),\\n totalDiggingFees + protocolFees\\n );\\n }\\n emit CreateSarcophagus(\\n sarcoId,\\n sarcophagusParams.name,\\n sarcophagusParams.resurrectionTime,\\n sarcophagusParams.creationTime,\\n msg.sender,\\n sarcophagusParams.recipientAddress,\\n sarcophagus.cursedArchaeologistAddresses,\\n totalDiggingFees,\\n arweaveTxId\\n );\\n }\\n\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n /// @param resurrectionTime the new resurrection time\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n\\n // Confirm resurrection time has not yet passed\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time is in future\\n if (block.timestamp >= resurrectionTime) {\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\n }\\n\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\n revert NewResurrectionTimeTooFarInFuture(\\n resurrectionTime,\\n sarcophagus.maximumRewrapInterval,\\n block.timestamp + sarcophagus.maximumRewrapInterval\\n );\\n }\\n\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\n revert ResurrectionTimePastMaxResurrectionTime(\\n resurrectionTime,\\n sarcophagus.maximumResurrectionTime\\n );\\n }\\n\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\n uint256 totalDiggingFees;\\n\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\n\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n if (!cursedArchaeologist.isAccused) {\\n // Previous digging fees calculation ignores curseFee\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\n (resurrectionTime - block.timestamp);\\n\\n // If the new digging fees are greater than the previous digging fees, we need to\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\n if (newDiggingFees > prevDiggingFees) {\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\n if (cursedBondIncrease > prevDiggingFees) {\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\n resurrectionTime,\\n sarcophagus.resurrectionTime\\n );\\n }\\n\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond += cursedBondIncrease;\\n\\n // Rewards are now previous digging fees - difference\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\n } else if (newDiggingFees < prevDiggingFees) {\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\n cursedBondPercentage) / 10000;\\n\\n // Decrease archaeologist's cursed bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .cursedBond -= cursedBondDecrease;\\n\\n // Increase archaeologist's free bond by the difference\\n s\\n .archaeologistProfiles[archaeologistAddresses[i]]\\n .freeBond += cursedBondDecrease;\\n\\n // Rewards are equal to the previous digging fees\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n } else {\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\n }\\n\\n // Add digging fees due for the new interval\\n totalDiggingFees += newDiggingFees;\\n\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n // Pay archaeologists the curse fee to their rewards\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\n }\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\n\\n // Add the protocol fee to the total protocol fees in storage\\n s.totalProtocolFees += protocolFees;\\n\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\n sarcophagus.resurrectionTime = resurrectionTime;\\n sarcophagus.previousRewrapTime = block.timestamp;\\n\\n if (!sarcophagus.isRewrapped) {\\n sarcophagus.isRewrapped = true;\\n }\\n\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\n\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\n }\\n\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\n /// @param sarcoId the identifier of the sarcophagus\\n function burySarcophagus(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer\\n if (sarcophagus.embalmerAddress != msg.sender) {\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\n }\\n // Confirm that the current resurrection time is in the future\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\n uint256 nArchAddresses = archaeologistAddresses.length;\\n for (uint256 i; i < nArchAddresses; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[archaeologistAddresses[i]];\\n\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\n if (!cursedArchaeologist.isAccused) {\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Set resurrection time to infinity\\n sarcophagus.resurrectionTime = type(uint256).max;\\n\\n emit BurySarcophagus(sarcoId);\\n }\\n}\\n\",\"keccak256\":\"0x6f608191836cb34a89292cbad9d19962144f57439e8acade82a5a6ffaf8f248a\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\ncontract ThirdPartyFacet {\\n event AccuseArchaeologist(\\n bytes32 indexed sarcoId,\\n address indexed accuser,\\n uint256 totalSlashedBondDistributed,\\n uint256 totalDiggingFeesDistributed,\\n address[] accusedArchAddresses\\n );\\n\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\n\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\n\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\n\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\n /// @param senderAddress Address of sender\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\n\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\n /// @param currentTime Timestamp of the failed clean attempt\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\n\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\n /// @param currentTime Timestamp of the failed accuse attempt\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\n\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\n /// @param signatures the number of signatures passed into the accuse call\\n /// @param publicKeys the number of public keys passed into the accuse call\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\n\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\n /// @param sarcoId that should have been signed\\n /// @param paymentAddress payment address that should have been signed\\n /// @param publicKey publicKey that should be derived from signing key\\n /// @param signature invalid signature\\n error InvalidAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes publicKey,\\n LibTypes.Signature signature\\n );\\n\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\n /// be able to claim remaining locked bond and diggingFees\\n /// @param sarcoId The identifier of the sarcophagus to clean\\n function clean(bytes32 sarcoId) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm the sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // Confirm tx sender is embalmer or admin\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n // Confirm the sarcophagus has not already been cleaned\\n if (sarcophagus.isCleaned) {\\n revert SarcophagusAlreadyCleaned(sarcoId);\\n }\\n\\n // Confirm that the resurrectionTime + gracePeriod have passed\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\n }\\n\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\n if (\\n msg.sender == sarcophagus.embalmerAddress &&\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert EmbalmerClaimWindowPassed(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // if sender is admin, confirm embalmerClaimWindow has passed\\n if (\\n msg.sender == LibDiamond.contractOwner() &&\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n ) {\\n revert TooEarlyForAdminClean(\\n block.timestamp,\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\n );\\n }\\n\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\n uint256 totalDiggingFeesAndLockedBonds;\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\n\\n // Punish archaeologists that failed to publish their private key in time\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n if (!sarcophagus.isRewrapped) {\\n diggingFeesDue += cursedArchaeologist.curseFee;\\n }\\n\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\n\\n // slash the archaeologist's locked bond for the sarcophagus\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\n // this to the contract's protocol fees\\n if (msg.sender == sarcophagus.embalmerAddress) {\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\n } else {\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\n }\\n\\n sarcophagus.isCleaned = true;\\n emit Clean(sarcoId, msg.sender);\\n }\\n\\n /**\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\n * and payment address generated with the leaked private keys\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\n *\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\n * returned\\n *\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\n * @param paymentAddress the address to which rewards should be sent if successful\\n */\\n function accuse(\\n bytes32 sarcoId,\\n bytes[] calldata publicKeys,\\n LibTypes.Signature[] calldata signatures,\\n address paymentAddress\\n ) external {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n // verify that current time is not past resurrection time\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\n }\\n\\n // Confirm the sarcophagus has not been compromised\\n if (sarcophagus.isCompromised) {\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\n }\\n\\n // Confirm the sarcophagus is not buried\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\n revert LibErrors.SarcophagusInactive(sarcoId);\\n }\\n\\n uint256 nSigs = signatures.length;\\n\\n if (nSigs != publicKeys.length) {\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\n }\\n\\n address[] memory accusedArchAddresses = new address[](nSigs);\\n\\n // track the combined locked bond across all archaeologists being accused in this call\\n uint256 totalCursedBond;\\n uint256 accusalCount;\\n for (uint256 i; i < nSigs; ) {\\n if (\\n !LibUtils.verifyAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n )\\n ) {\\n revert InvalidAccusalSignature(\\n sarcoId,\\n paymentAddress,\\n publicKeys[i],\\n signatures[i]\\n );\\n }\\n\\n // look up the archaeologist responsible for the publicKey\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\n .cursedArchaeologists[accusedArchaeologistAddress];\\n\\n // verify the accused archaeologist is cursed on the sarcophagus\\n if (accusedArchaeologist.publicKey.length == 0) {\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\n }\\n\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\n if (accusedArchaeologist.isAccused) {\\n unchecked {\\n ++i;\\n }\\n continue;\\n }\\n\\n // mark the archaeologist on the sarcophagus as having been accused\\n accusedArchaeologist.isAccused = true;\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\n\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\n sarcophagus.cursedBondPercentage) / 10000;\\n\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\n if (!sarcophagus.isRewrapped) {\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\n }\\n\\n totalCursedBond += cursedBondDue;\\n\\n // Slash the offending archaeologists bond\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\n unchecked {\\n ++i;\\n }\\n }\\n\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\n if (accusalCount == 0) {\\n return;\\n }\\n\\n {\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\n\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\n if (accusalCount >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n } else {\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\n uint256 totalAccusals;\\n\\n for (uint256 i; i < nCursedArchs; ) {\\n if (\\n sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n ++totalAccusals;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\n if (totalAccusals >= sarcophagus.threshold) {\\n sarcophagus.isCompromised = true;\\n }\\n }\\n\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\n // be returned to the remaining well behaved archaeologists\\n if (sarcophagus.isCompromised) {\\n // iterate through all archaeologist addresses on the sarcophagus\\n for (uint256 i; i < nCursedArchs; ) {\\n // if the archaeologist has never been accused, release their locked bond back to them\\n if (\\n !sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused\\n ) {\\n LibBonds.freeArchaeologist(\\n sarcoId,\\n sarcophagus.cursedArchaeologistAddresses[i]\\n );\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n }\\n }\\n\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\n s.sarcoToken.transfer(\\n sarcophagus.embalmerAddress,\\n totalDiggingFees + halfTotalCursedBond\\n );\\n\\n // transfer the other half of the cursed bond to the transaction caller\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\n\\n emit AccuseArchaeologist(\\n sarcoId,\\n msg.sender,\\n totalCursedBond,\\n totalDiggingFees,\\n accusedArchAddresses\\n );\\n }\\n}\\n\",\"keccak256\":\"0x6d493c3c0d5bd584f4432f4c559fd431cbff1f47f5587d7453ef918fe91190c2\",\"license\":\"Unlicense\"},\"contracts/facets/ViewStateFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport \\\"../libraries/LibUtils.sol\\\";\\nimport \\\"../storage/LibAppStorage.sol\\\";\\n\\ncontract ViewStateFacet {\\n /// @notice Get the admin address from diamond storage\\n /// @return The admin address\\n function getAdmin() external view returns (address) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.admin;\\n }\\n\\n /// @notice Gets the total protocol fees from diamond storage\\n /// @return The total protocol fees\\n function getTotalProtocolFees() external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.totalProtocolFees;\\n }\\n\\n /// @notice Get the protocol fee base percentage from diamond storage\\n /// @return The protocol fee base percentage - protocolFeeBasePercentage\\n function getProtocolFeeBasePercentage() external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.protocolFeeBasePercentage;\\n }\\n\\n /// @notice Get the cursed bond percentage from diamond storage\\n /// @return The cursed bond percentage - cursedBondPercentage\\n function getCursedBondPercentage() external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.cursedBondPercentage;\\n }\\n\\n /// @notice Gets archaeologist profiles given a list of archaeologist addresses.\\n /// If an invalid address is included, simply leaves it out of the list.\\n /// @param addresses The list of archaeologist addresses\\n /// @return The list of archaeologist profiles\\n function getArchaeologistProfiles(\\n address[] memory addresses\\n ) external view returns (LibTypes.ArchaeologistProfile[] memory) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n uint256 nAddresses = addresses.length;\\n LibTypes.ArchaeologistProfile[] memory profiles = new LibTypes.ArchaeologistProfile[](\\n nAddresses\\n );\\n\\n for (uint256 i; i < nAddresses; ) {\\n // Skip unregistered archaeologists\\n if (s.archaeologistProfiles[addresses[i]].maximumRewrapInterval == 0) {\\n continue;\\n }\\n profiles[i] = s.archaeologistProfiles[addresses[i]];\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return profiles;\\n }\\n\\n /// @notice Gets the grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time passes\\n /// @return The resurrection grace period\\n function getGracePeriod() external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.gracePeriod;\\n }\\n\\n /// @notice Gets the window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys\\n /// @return The embalmer claim window\\n function getEmbalmerClaimWindow() external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.embalmerClaimWindow;\\n }\\n\\n /// @notice Gets the expiration threshold after which a sarcophagus must be renegotiated\\n /// @return The expiration threshold\\n function getExpirationThreshold() external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.expirationThreshold;\\n }\\n\\n /// @notice Given an archaeologist address, return that archaeologist's\\n /// profile\\n /// @param archaeologist The archaeologist account's address\\n /// @return the Archaeologist object\\n function getArchaeologistProfile(\\n address archaeologist\\n ) external view returns (LibTypes.ArchaeologistProfile memory) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibUtils.revertIfArchProfileDoesNotExist(archaeologist);\\n return s.archaeologistProfiles[archaeologist];\\n }\\n\\n /// @notice Return the list of registereed archaeologist addresses.\\n /// @return addresses of registered archaeologists\\n function getArchaeologistProfileAddresses() external view returns (address[] memory) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.archaeologistProfileAddresses;\\n }\\n\\n /// @notice Given an index (of the full archaeologist array), return the\\n /// archaeologist address at that index\\n /// @param index The index of the registered archaeologist\\n /// @return address of the archaeologist\\n function getArchaeologistProfileAddressAtIndex(uint256 index) external view returns (address) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.archaeologistProfileAddresses[index];\\n }\\n\\n /// @notice Returns the amount of free bond stored in the contract for an\\n /// archaeologist.\\n /// @param archaeologist The address of the archaeologist whose\\n /// free bond is being returned\\n function getFreeBond(address archaeologist) external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.archaeologistProfiles[archaeologist].freeBond;\\n }\\n\\n /// @notice Returns the amount of rewards stored in the contract for an\\n /// archaeologist.\\n /// @param archaeologist The address of the archaeologist whose\\n /// reward is being returned\\n function getRewards(address archaeologist) external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.archaeologistRewards[archaeologist];\\n }\\n\\n /// @notice Returns the amount of cursed bond stored in the contract for an\\n /// archaeologist.\\n /// @param archaeologist The address of the archaeologist whose\\n /// cursed bond is being returned\\n function getCursedBond(address archaeologist) external view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.archaeologistProfiles[archaeologist].cursedBond;\\n }\\n\\n struct SarcophagusResponse {\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n bool isCompromised;\\n bool isCleaned;\\n string name;\\n uint8 threshold;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n uint256 cursedBondPercentage;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] archaeologistAddresses;\\n uint8 publishedPrivateKeyCount;\\n bool hasLockedBond;\\n }\\n\\n /// @notice Returns data on the sarcophagus with the supplied id\\n /// includes aggregate data on cursed archaeologists associated with the sarcophagus\\n /// - publishedPrivateKeyCount - the total number of private keys published by archaeologists on the sarcophagus\\n /// - hasLockedBond - true if archaeologists still have bond locked in the contract for this sarcophagus\\n /// @param sarcoId The identifier of the sarcophagus being returned\\n function getSarcophagus(bytes32 sarcoId) external view returns (SarcophagusResponse memory) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n // Confirm sarcophagus exists\\n if (sarcophagus.resurrectionTime == 0) {\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\n }\\n\\n uint8 publishedPrivateKeyCount;\\n bool hasLockedBond;\\n uint256 archsLength = sarcophagus.cursedArchaeologistAddresses.length;\\n for (uint256 i; i < archsLength; ) {\\n // archaeologist has published a private key\\n if (\\n sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .privateKey != 0\\n ) {\\n ++publishedPrivateKeyCount;\\n } else if (\\n !sarcophagus\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\n .isAccused &&\\n !sarcophagus.isCompromised &&\\n !sarcophagus.isCleaned &&\\n sarcophagus.resurrectionTime != type(uint256).max\\n ) {\\n // if the sarcophagus is not compromised, buried, or cleaned and\\n // one or more unaccused archaeologists hasn't published a private key there is locked bond on the sarcophagus\\n hasLockedBond = true;\\n }\\n unchecked {\\n ++i;\\n }\\n }\\n\\n return\\n SarcophagusResponse({\\n resurrectionTime: sarcophagus.resurrectionTime,\\n previousRewrapTime: sarcophagus.previousRewrapTime,\\n isCompromised: sarcophagus.isCompromised,\\n isCleaned: sarcophagus.isCleaned,\\n name: sarcophagus.name,\\n threshold: sarcophagus.threshold,\\n maximumRewrapInterval: sarcophagus.maximumRewrapInterval,\\n maximumResurrectionTime: sarcophagus.maximumResurrectionTime,\\n cursedBondPercentage: sarcophagus.cursedBondPercentage,\\n arweaveTxId: sarcophagus.arweaveTxId,\\n embalmerAddress: sarcophagus.embalmerAddress,\\n recipientAddress: sarcophagus.recipientAddress,\\n archaeologistAddresses: sarcophagus.cursedArchaeologistAddresses,\\n publishedPrivateKeyCount: publishedPrivateKeyCount,\\n hasLockedBond: hasLockedBond\\n });\\n }\\n\\n /// @notice Returns the data stored on a sarcophagus for an archaeologist.\\n /// @param sarcoId The identifier of the sarcophagus whose data is being\\n /// returned\\n /// @param archaeologist The address of the archaeologist whose data is\\n /// being returned\\n function getSarcophagusArchaeologist(\\n bytes32 sarcoId,\\n address archaeologist\\n ) external view returns (LibTypes.CursedArchaeologist memory) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n return s.sarcophagi[sarcoId].cursedArchaeologists[archaeologist];\\n }\\n}\\n\",\"keccak256\":\"0x1c5d394710346e8737dff08768308b224a4e1f8dba07778f17948e072b062cfb\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\n\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\nlibrary LibBonds {\\n /// @notice Bonds the archaeologist to a sarcophagus.\\n /// This does the following:\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\n ///\\n /// @return the amount of digging fees due the embalmer for this curse\\n function curseArchaeologist(\\n bytes32 sarcoId,\\n EmbalmerFacet.CurseParams calldata archaeologist,\\n uint256 index\\n ) internal returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\n publicKey: archaeologist.publicKey,\\n privateKey: 0,\\n isAccused: false,\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\n curseFee: archaeologist.curseFee\\n });\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\n\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\n + archaeologist.curseFee;\\n\\n // Use cursed bond percentage to determine how much bond to lock up\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\n\\n // Transfer bond to curse from free bond to cursed bond\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\n\\n return diggingFeesDue;\\n }\\n\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\n /// @param archaeologistAddress the address of the archaeologist to free\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\n\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\n .sarcophagi[sarcoId]\\n .cursedArchaeologists[archaeologistAddress];\\n\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\n\\n // Include curse fee in bond amount being released\\n uint256 cursedBondAmount = ((diggingFeeAmount + cursedArchaeologist.curseFee) * sarcophagus.cursedBondPercentage) / 10000;\\n\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\n\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\n if (!sarcophagus.isRewrapped) {\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\n }\\n\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\n }\\n}\\n\",\"keccak256\":\"0x1ce4949867d00310a878d0671312e3c9b51c3301586df45dfc63bc43f16bd1d9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title A collection of Errors\\n * @notice This library defines all of the Errors that the Sarcophagus system\\n * uses.\\n */\\nlibrary LibErrors {\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\n\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\n\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\n\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\n\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\n\\n error SarcophagusInactive(bytes32 sarcoId);\\n\\n error SarcophagusCompromised(bytes32 sarcoId);\\n\\n error SenderNotEmbalmer(address sender, address embalmer);\\n\\n error InvalidSignature(\\n // address recovered from signature via ecrecover\\n address recoveredAddress,\\n // address we expected to have signed the data\\n address expectedAddress\\n );\\n}\\n\",\"keccak256\":\"0xed77e67ab300a74738cd8ec5fe8e3bd5c166b87410051ceaabe0a7ec2e45b967\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\n/**\\n * @title Types shared across facets for the Sarcophagus diamond\\n */\\nlibrary LibTypes {\\n struct Sarcophagus {\\n // Also used for existence checks -- does not exist if 0\\n uint256 resurrectionTime;\\n uint256 previousRewrapTime;\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\n bool isCompromised;\\n bool isCleaned;\\n bool isRewrapped;\\n uint8 threshold;\\n string name;\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string arweaveTxId;\\n address embalmerAddress;\\n address recipientAddress;\\n address[] cursedArchaeologistAddresses;\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\n uint256 cursedBondPercentage;\\n }\\n\\n struct CursedArchaeologist {\\n uint256 diggingFeePerSecond;\\n // Also used for publish checks -- has not published if 0\\n bytes32 privateKey;\\n // Also used for curse checks -- is not bonded if length is 0\\n bytes publicKey;\\n bool isAccused;\\n uint256 curseFee;\\n }\\n\\n struct Signature {\\n uint8 v;\\n bytes32 r;\\n bytes32 s;\\n }\\n\\n struct ArchaeologistProfile {\\n // Also used for existence checks -- does not exist if 0\\n uint256 maximumRewrapInterval;\\n uint256 maximumResurrectionTime;\\n string peerId;\\n uint256 minimumDiggingFeePerSecond;\\n uint256 freeBond;\\n uint256 cursedBond;\\n uint256 curseFee;\\n }\\n}\\n\",\"keccak256\":\"0x1b2f2f8c309ec6d6f4895143d290b5d99daacfee6bfd2443dfe74dc0f29e8678\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"../storage/LibAppStorage.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\nimport \\\"./LibTypes.sol\\\";\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\n\\n/**\\n * @title Utility functions used within the Sarcophagus system\\n * @notice This library implements various functions that are used throughout\\n * Sarcophagus, mainly to DRY up the codebase\\n * @dev these functions are all stateless, public, pure/view\\n */\\nlibrary LibUtils {\\n /**\\n * @notice The archaeologist needs to sign off on two pieces of data\\n * to guarantee their unrwap will be successful\\n *\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\n * @param curseParams parameters of curse signed by archaeologist\\n */\\n function verifyArchaeologistSignature(\\n uint256 agreedMaximumRewrapInterval,\\n uint256 maximumResurrectionTime,\\n uint256 timestamp,\\n EmbalmerFacet.CurseParams calldata curseParams\\n ) internal pure {\\n // Hash the hash of the data payload\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(\\n abi.encode(\\n curseParams.publicKey,\\n agreedMaximumRewrapInterval,\\n maximumResurrectionTime,\\n curseParams.diggingFeePerSecond,\\n timestamp,\\n curseParams.curseFee\\n )\\n )\\n )\\n );\\n\\n // Generate the address from the signature.\\n // ecrecover should always return a valid address.\\n address recoveredAddress = ecrecover(\\n messageHash,\\n curseParams.v,\\n curseParams.r,\\n curseParams.s\\n );\\n\\n if (recoveredAddress != curseParams.archAddress) {\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\n }\\n }\\n\\n /// @notice Verifies that a signature and public key were created from the same private key\\n /// @param sarcoId the sarcoId that was signed\\n /// @param paymentAddress the payment address that was signed\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\n /// @param signature signature on the sarco id and payment address\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\n function verifyAccusalSignature(\\n bytes32 sarcoId,\\n address paymentAddress,\\n bytes calldata publicKey,\\n LibTypes.Signature calldata signature\\n ) internal pure returns (bool) {\\n // removes the 0x04 prefix from an uncompressed public key\\n uint256 pubKeyLength = publicKey.length;\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\n for (uint256 i = 1; i < pubKeyLength; ) {\\n truncatedPublicKey[i - 1] = publicKey[i];\\n unchecked {\\n ++i;\\n }\\n }\\n bytes32 messageHash = keccak256(\\n abi.encodePacked(\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\n keccak256(abi.encode(sarcoId, paymentAddress))\\n )\\n );\\n // Use ecrecover to get the address that signed the message\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\n\\n address publicKeyAddress = address(\\n uint160(\\n uint256(keccak256(truncatedPublicKey)) &\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\n )\\n );\\n\\n return signingAddress == publicKeyAddress;\\n }\\n\\n /// @notice Checks if an archaeologist profile exists and\\n /// reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check existence of\\n function revertIfArchProfileExists(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\n }\\n }\\n\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\n ///\\n /// @param archaeologist the archaeologist address to check lack of existence of\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\n }\\n }\\n\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\n /// @return The protocol fees amount\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\n AppStorage storage s = LibAppStorage.getAppStorage();\\n\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\n }\\n}\\n\",\"keccak256\":\"0x1b411278faa2f19d4fb8f558fb1ce33f35cc367cca58b7229d5c2f8848201b48\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\npragma solidity 0.8.18;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\nimport \\\"../libraries/LibTypes.sol\\\";\\n\\n/**\\n * Global diamond storage struct to be shared across facets\\n */\\nstruct AppStorage {\\n // SARCO token contract\\n IERC20 sarcoToken;\\n // The Admin address allowed to call Admin Facet functions\\n address admin;\\n // total protocol fees available to be withdrawn by the admin\\n uint256 totalProtocolFees;\\n /**\\n * Protocol level admin configurations\\n */\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\n uint256 protocolFeeBasePercentage;\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\n uint256 cursedBondPercentage;\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\n uint256 gracePeriod;\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\n uint256 expirationThreshold;\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\n uint256 embalmerClaimWindow;\\n // registered archaeologist addresses\\n address[] archaeologistProfileAddresses;\\n // public key => archaeologist address\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\n // sarcophagus id => sarcophagus object\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\n // archaeologist address => profile\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\n // current balance of rewards available for the archaeologist to withdraw\\n mapping(address => uint256) archaeologistRewards;\\n}\\n\\nlibrary LibAppStorage {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\n\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n s.slot := position\\n }\\n }\\n}\\n\",\"keccak256\":\"0x07df02177bdd1ecc43723d2c46b8d81ecc84b49c40b7c85478ef4c4650b02335\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x608060405234801561001057600080fd5b50611de3806100206000396000f3fe608060405234801561001057600080fd5b50600436106101005760003560e01c80638fbd55d211610097578063dbd1838811610066578063dbd18388146102d9578063dc231f43146102f7578063dcfcb90114610327578063de116f061461034557610100565b80638fbd55d21461023d5780639c5456391461026d5780639fdaded11461028b578063a9328dcc146102a957610100565b80636e9960c3116100d35780636e9960c3146101a157806379ee54f7146101bf5780637aa9fd2f146101ef57806387927ce61461020d57610100565b806331baea67146101055780633fbb89301461012357806342e10bc81461014157806357babbaf14610171575b600080fd5b61010d610375565b60405161011a9190611221565b60405180910390f35b61012b61038d565b604051610138919061132c565b60405180910390f35b61015b6004803603810190610156919061138e565b61042a565b60405161016891906114f6565b60405180910390f35b61018b60048036038101906101869190611544565b610569565b6040516101989190611580565b60405180910390f35b6101a96105bf565b6040516101b69190611580565b60405180910390f35b6101d960048036038101906101d4919061138e565b6105f7565b6040516101e69190611221565b60405180910390f35b6101f761064e565b6040516102049190611221565b60405180910390f35b6102276004803603810190610222919061138e565b610666565b6040516102349190611221565b60405180910390f35b6102576004803603810190610252919061138e565b6106c0565b6040516102649190611221565b60405180910390f35b61027561071a565b6040516102829190611221565b60405180910390f35b610293610732565b6040516102a09190611221565b60405180910390f35b6102c360048036038101906102be91906116e3565b61074a565b6040516102d0919061188a565b60405180910390f35b6102e1610992565b6040516102ee9190611221565b60405180910390f35b610311600480360381019061030c91906118e2565b6109aa565b60405161031e9190611a17565b60405180910390f35b61032f610af2565b60405161033c9190611221565b60405180910390f35b61035f600480360381019061035a9190611a39565b610b0a565b60405161036c9190611c42565b60405180910390f35b600080610380611020565b9050806007015491505090565b60606000610399611020565b90508060080180548060200260200160405190810160405280929190818152602001828054801561041f57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116103d5575b505050505091505090565b6104326110e9565b600061043c611020565b90506104478361104d565b80600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546104b790611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546104e390611c93565b80156105305780601f1061050557610100808354040283529160200191610530565b820191906000526020600020905b81548152906001019060200180831161051357829003601f168201915b50505050508152602001600382015481526020016004820154815260200160058201548152602001600682015481525050915050919050565b600080610574611020565b905080600801838154811061058c5761058b611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6000806105ca611020565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b600080610602611020565b905080600c0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054915050919050565b600080610659611020565b9050806006015491505090565b600080610671611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154915050919050565b6000806106cb611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040154915050919050565b600080610725611020565b9050806002015491505090565b60008061073d611020565b9050806003015491505090565b60606000610756611020565b905060008351905060008167ffffffffffffffff81111561077a576107796115a0565b5b6040519080825280602002602001820160405280156107b357816020015b6107a06110e9565b8152602001906001900390816107985790505b50905060005b8281101561098657600084600b0160008884815181106107dc576107db611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403156109815783600b01600087838151811061084157610840611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546108b290611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546108de90611c93565b801561092b5780601f106109005761010080835404028352916020019161092b565b820191906000526020600020905b81548152906001019060200180831161090e57829003601f168201915b5050505050815260200160038201548152602001600482015481526020016005820154815260200160068201548152505082828151811061096f5761096e611cc4565b5b60200260200101819052508060010190505b6107b9565b50809350505050919050565b60008061099d611020565b9050806005015491505090565b6109b2611126565b60006109bc611020565b905080600a016000858152602001908152602001600020600a0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820154815260200160018201548152602001600282018054610a4290611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6e90611c93565b8015610abb5780601f10610a9057610100808354040283529160200191610abb565b820191906000526020600020905b815481529060010190602001808311610a9e57829003601f168201915b505050505081526020016003820160009054906101000a900460ff1615151515815260200160048201548152505091505092915050565b600080610afd611020565b9050806004015491505090565b610b1261115a565b6000610b1c611020565b9050600081600a01600085815260200190815260200160002090506000816000015403610b8057836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610b779190611d02565b60405180910390fd5b60008060008360090180549050905060005b81811015610d48576000801b85600a016000876009018481548110610bba57610bb9611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015414610c395783610c3290611d4c565b9350610d3d565b84600a016000866009018381548110610c5557610c54611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff16158015610ce757508460020160009054906101000a900460ff16155b8015610d0257508460020160019054906101000a900460ff16155b8015610d3257507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff856000015414155b15610d3c57600192505b5b806001019050610b92565b50604051806101e0016040528085600001548152602001856001015481526020018560020160009054906101000a900460ff16151581526020018560020160019054906101000a900460ff1615158152602001856003018054610daa90611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd690611c93565b8015610e235780601f10610df857610100808354040283529160200191610e23565b820191906000526020600020905b815481529060010190602001808311610e0657829003601f168201915b505050505081526020018560020160039054906101000a900460ff1660ff168152602001856004015481526020018560050154815260200185600b01548152602001856006018054610e7490611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610ea090611c93565b8015610eed5780601f10610ec257610100808354040283529160200191610eed565b820191906000526020600020905b815481529060010190602001808311610ed057829003601f168201915b505050505081526020018560070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018560080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185600901805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610fb1575b505050505081526020018460ff16815260200183151581525095505050505050919050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000611057611020565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154036110e5576001826040517f2eeb35710000000000000000000000000000000000000000000000000000000081526004016110dc929190611d84565b60405180910390fd5b5050565b6040518060e00160405280600081526020016000815260200160608152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280600081526020016000801916815260200160608152602001600015158152602001600081525090565b604051806101e00160405280600081526020016000815260200160001515815260200160001515815260200160608152602001600060ff16815260200160008152602001600081526020016000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600060ff1681526020016000151581525090565b6000819050919050565b61121b81611208565b82525050565b60006020820190506112366000830184611212565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061129382611268565b9050919050565b6112a381611288565b82525050565b60006112b5838361129a565b60208301905092915050565b6000602082019050919050565b60006112d98261123c565b6112e38185611247565b93506112ee83611258565b8060005b8381101561131f57815161130688826112a9565b9750611311836112c1565b9250506001810190506112f2565b5085935050505092915050565b6000602082019050818103600083015261134681846112ce565b905092915050565b6000604051905090565b600080fd5b600080fd5b61136b81611288565b811461137657600080fd5b50565b60008135905061138881611362565b92915050565b6000602082840312156113a4576113a3611358565b5b60006113b284828501611379565b91505092915050565b6113c481611208565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156114045780820151818401526020810190506113e9565b60008484015250505050565b6000601f19601f8301169050919050565b600061142c826113ca565b61143681856113d5565b93506114468185602086016113e6565b61144f81611410565b840191505092915050565b600060e08301600083015161147260008601826113bb565b50602083015161148560208601826113bb565b506040830151848203604086015261149d8282611421565b91505060608301516114b260608601826113bb565b5060808301516114c560808601826113bb565b5060a08301516114d860a08601826113bb565b5060c08301516114eb60c08601826113bb565b508091505092915050565b60006020820190508181036000830152611510818461145a565b905092915050565b61152181611208565b811461152c57600080fd5b50565b60008135905061153e81611518565b92915050565b60006020828403121561155a57611559611358565b5b60006115688482850161152f565b91505092915050565b61157a81611288565b82525050565b60006020820190506115956000830184611571565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6115d882611410565b810181811067ffffffffffffffff821117156115f7576115f66115a0565b5b80604052505050565b600061160a61134e565b905061161682826115cf565b919050565b600067ffffffffffffffff821115611636576116356115a0565b5b602082029050602081019050919050565b600080fd5b600061165f61165a8461161b565b611600565b9050808382526020820190506020840283018581111561168257611681611647565b5b835b818110156116ab57806116978882611379565b845260208401935050602081019050611684565b5050509392505050565b600082601f8301126116ca576116c961159b565b5b81356116da84826020860161164c565b91505092915050565b6000602082840312156116f9576116f8611358565b5b600082013567ffffffffffffffff8111156117175761171661135d565b5b611723848285016116b5565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600060e08301600083015161177060008601826113bb565b50602083015161178360208601826113bb565b506040830151848203604086015261179b8282611421565b91505060608301516117b060608601826113bb565b5060808301516117c360808601826113bb565b5060a08301516117d660a08601826113bb565b5060c08301516117e960c08601826113bb565b508091505092915050565b60006118008383611758565b905092915050565b6000602082019050919050565b60006118208261172c565b61182a8185611737565b93508360208202850161183c85611748565b8060005b85811015611878578484038952815161185985826117f4565b945061186483611808565b925060208a01995050600181019050611840565b50829750879550505050505092915050565b600060208201905081810360008301526118a48184611815565b905092915050565b6000819050919050565b6118bf816118ac565b81146118ca57600080fd5b50565b6000813590506118dc816118b6565b92915050565b600080604083850312156118f9576118f8611358565b5b6000611907858286016118cd565b925050602061191885828601611379565b9150509250929050565b61192b816118ac565b82525050565b600081519050919050565b600082825260208201905092915050565b600061195882611931565b611962818561193c565b93506119728185602086016113e6565b61197b81611410565b840191505092915050565b60008115159050919050565b61199b81611986565b82525050565b600060a0830160008301516119b960008601826113bb565b5060208301516119cc6020860182611922565b50604083015184820360408601526119e4828261194d565b91505060608301516119f96060860182611992565b506080830151611a0c60808601826113bb565b508091505092915050565b60006020820190508181036000830152611a3181846119a1565b905092915050565b600060208284031215611a4f57611a4e611358565b5b6000611a5d848285016118cd565b91505092915050565b600060ff82169050919050565b611a7c81611a66565b82525050565b600082825260208201905092915050565b6000611a9e8261123c565b611aa88185611a82565b9350611ab383611258565b8060005b83811015611ae4578151611acb88826112a9565b9750611ad6836112c1565b925050600181019050611ab7565b5085935050505092915050565b60006101e083016000830151611b0a60008601826113bb565b506020830151611b1d60208601826113bb565b506040830151611b306040860182611992565b506060830151611b436060860182611992565b5060808301518482036080860152611b5b8282611421565b91505060a0830151611b7060a0860182611a73565b5060c0830151611b8360c08601826113bb565b5060e0830151611b9660e08601826113bb565b50610100830151611bab6101008601826113bb565b50610120830151848203610120860152611bc58282611421565b915050610140830151611bdc61014086018261129a565b50610160830151611bf161016086018261129a565b50610180830151848203610180860152611c0b8282611a93565b9150506101a0830151611c226101a0860182611a73565b506101c0830151611c376101c0860182611992565b508091505092915050565b60006020820190508181036000830152611c5c8184611af1565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611cab57607f821691505b602082108103611cbe57611cbd611c64565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b611cfc816118ac565b82525050565b6000602082019050611d176000830184611cf3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611d5782611a66565b915060ff8203611d6a57611d69611d1d565b5b600182019050919050565b611d7e81611986565b82525050565b6000604082019050611d996000830185611d75565b611da66020830184611571565b939250505056fea2646970667358221220d9b7b645b9e097edd26b48b07416dd07b190412249bb1e2930964721efecc56f64736f6c63430008120033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101005760003560e01c80638fbd55d211610097578063dbd1838811610066578063dbd18388146102d9578063dc231f43146102f7578063dcfcb90114610327578063de116f061461034557610100565b80638fbd55d21461023d5780639c5456391461026d5780639fdaded11461028b578063a9328dcc146102a957610100565b80636e9960c3116100d35780636e9960c3146101a157806379ee54f7146101bf5780637aa9fd2f146101ef57806387927ce61461020d57610100565b806331baea67146101055780633fbb89301461012357806342e10bc81461014157806357babbaf14610171575b600080fd5b61010d610375565b60405161011a9190611221565b60405180910390f35b61012b61038d565b604051610138919061132c565b60405180910390f35b61015b6004803603810190610156919061138e565b61042a565b60405161016891906114f6565b60405180910390f35b61018b60048036038101906101869190611544565b610569565b6040516101989190611580565b60405180910390f35b6101a96105bf565b6040516101b69190611580565b60405180910390f35b6101d960048036038101906101d4919061138e565b6105f7565b6040516101e69190611221565b60405180910390f35b6101f761064e565b6040516102049190611221565b60405180910390f35b6102276004803603810190610222919061138e565b610666565b6040516102349190611221565b60405180910390f35b6102576004803603810190610252919061138e565b6106c0565b6040516102649190611221565b60405180910390f35b61027561071a565b6040516102829190611221565b60405180910390f35b610293610732565b6040516102a09190611221565b60405180910390f35b6102c360048036038101906102be91906116e3565b61074a565b6040516102d0919061188a565b60405180910390f35b6102e1610992565b6040516102ee9190611221565b60405180910390f35b610311600480360381019061030c91906118e2565b6109aa565b60405161031e9190611a17565b60405180910390f35b61032f610af2565b60405161033c9190611221565b60405180910390f35b61035f600480360381019061035a9190611a39565b610b0a565b60405161036c9190611c42565b60405180910390f35b600080610380611020565b9050806007015491505090565b60606000610399611020565b90508060080180548060200260200160405190810160405280929190818152602001828054801561041f57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190600101908083116103d5575b505050505091505090565b6104326110e9565b600061043c611020565b90506104478361104d565b80600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546104b790611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546104e390611c93565b80156105305780601f1061050557610100808354040283529160200191610530565b820191906000526020600020905b81548152906001019060200180831161051357829003601f168201915b50505050508152602001600382015481526020016004820154815260200160058201548152602001600682015481525050915050919050565b600080610574611020565b905080600801838154811061058c5761058b611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16915050919050565b6000806105ca611020565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1691505090565b600080610602611020565b905080600c0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002054915050919050565b600080610659611020565b9050806006015491505090565b600080610671611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050154915050919050565b6000806106cb611020565b905080600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040154915050919050565b600080610725611020565b9050806002015491505090565b60008061073d611020565b9050806003015491505090565b60606000610756611020565b905060008351905060008167ffffffffffffffff81111561077a576107796115a0565b5b6040519080825280602002602001820160405280156107b357816020015b6107a06110e9565b8152602001906001900390816107985790505b50905060005b8281101561098657600084600b0160008884815181106107dc576107db611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403156109815783600b01600087838151811061084157610840611cc4565b5b602002602001015173ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060e001604052908160008201548152602001600182015481526020016002820180546108b290611c93565b80601f01602080910402602001604051908101604052809291908181526020018280546108de90611c93565b801561092b5780601f106109005761010080835404028352916020019161092b565b820191906000526020600020905b81548152906001019060200180831161090e57829003601f168201915b5050505050815260200160038201548152602001600482015481526020016005820154815260200160068201548152505082828151811061096f5761096e611cc4565b5b60200260200101819052508060010190505b6107b9565b50809350505050919050565b60008061099d611020565b9050806005015491505090565b6109b2611126565b60006109bc611020565b905080600a016000858152602001908152602001600020600a0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206040518060a00160405290816000820154815260200160018201548152602001600282018054610a4290611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610a6e90611c93565b8015610abb5780601f10610a9057610100808354040283529160200191610abb565b820191906000526020600020905b815481529060010190602001808311610a9e57829003601f168201915b505050505081526020016003820160009054906101000a900460ff1615151515815260200160048201548152505091505092915050565b600080610afd611020565b9050806004015491505090565b610b1261115a565b6000610b1c611020565b9050600081600a01600085815260200190815260200160002090506000816000015403610b8057836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610b779190611d02565b60405180910390fd5b60008060008360090180549050905060005b81811015610d48576000801b85600a016000876009018481548110610bba57610bb9611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206001015414610c395783610c3290611d4c565b9350610d3d565b84600a016000866009018381548110610c5557610c54611cc4565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff16158015610ce757508460020160009054906101000a900460ff16155b8015610d0257508460020160019054906101000a900460ff16155b8015610d3257507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff856000015414155b15610d3c57600192505b5b806001019050610b92565b50604051806101e0016040528085600001548152602001856001015481526020018560020160009054906101000a900460ff16151581526020018560020160019054906101000a900460ff1615158152602001856003018054610daa90611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610dd690611c93565b8015610e235780601f10610df857610100808354040283529160200191610e23565b820191906000526020600020905b815481529060010190602001808311610e0657829003601f168201915b505050505081526020018560020160039054906101000a900460ff1660ff168152602001856004015481526020018560050154815260200185600b01548152602001856006018054610e7490611c93565b80601f0160208091040260200160405190810160405280929190818152602001828054610ea090611c93565b8015610eed5780601f10610ec257610100808354040283529160200191610eed565b820191906000526020600020905b815481529060010190602001808311610ed057829003601f168201915b505050505081526020018560070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020018560080160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200185600901805480602002602001604051908101604052809291908181526020018280548015610ffb57602002820191906000526020600020905b8160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019060010190808311610fb1575b505050505081526020018460ff16815260200183151581525095505050505050919050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000611057611020565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060000154036110e5576001826040517f2eeb35710000000000000000000000000000000000000000000000000000000081526004016110dc929190611d84565b60405180910390fd5b5050565b6040518060e00160405280600081526020016000815260200160608152602001600081526020016000815260200160008152602001600081525090565b6040518060a00160405280600081526020016000801916815260200160608152602001600015158152602001600081525090565b604051806101e00160405280600081526020016000815260200160001515815260200160001515815260200160608152602001600060ff16815260200160008152602001600081526020016000815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600073ffffffffffffffffffffffffffffffffffffffff16815260200160608152602001600060ff1681526020016000151581525090565b6000819050919050565b61121b81611208565b82525050565b60006020820190506112366000830184611212565b92915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061129382611268565b9050919050565b6112a381611288565b82525050565b60006112b5838361129a565b60208301905092915050565b6000602082019050919050565b60006112d98261123c565b6112e38185611247565b93506112ee83611258565b8060005b8381101561131f57815161130688826112a9565b9750611311836112c1565b9250506001810190506112f2565b5085935050505092915050565b6000602082019050818103600083015261134681846112ce565b905092915050565b6000604051905090565b600080fd5b600080fd5b61136b81611288565b811461137657600080fd5b50565b60008135905061138881611362565b92915050565b6000602082840312156113a4576113a3611358565b5b60006113b284828501611379565b91505092915050565b6113c481611208565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b838110156114045780820151818401526020810190506113e9565b60008484015250505050565b6000601f19601f8301169050919050565b600061142c826113ca565b61143681856113d5565b93506114468185602086016113e6565b61144f81611410565b840191505092915050565b600060e08301600083015161147260008601826113bb565b50602083015161148560208601826113bb565b506040830151848203604086015261149d8282611421565b91505060608301516114b260608601826113bb565b5060808301516114c560808601826113bb565b5060a08301516114d860a08601826113bb565b5060c08301516114eb60c08601826113bb565b508091505092915050565b60006020820190508181036000830152611510818461145a565b905092915050565b61152181611208565b811461152c57600080fd5b50565b60008135905061153e81611518565b92915050565b60006020828403121561155a57611559611358565b5b60006115688482850161152f565b91505092915050565b61157a81611288565b82525050565b60006020820190506115956000830184611571565b92915050565b600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6115d882611410565b810181811067ffffffffffffffff821117156115f7576115f66115a0565b5b80604052505050565b600061160a61134e565b905061161682826115cf565b919050565b600067ffffffffffffffff821115611636576116356115a0565b5b602082029050602081019050919050565b600080fd5b600061165f61165a8461161b565b611600565b9050808382526020820190506020840283018581111561168257611681611647565b5b835b818110156116ab57806116978882611379565b845260208401935050602081019050611684565b5050509392505050565b600082601f8301126116ca576116c961159b565b5b81356116da84826020860161164c565b91505092915050565b6000602082840312156116f9576116f8611358565b5b600082013567ffffffffffffffff8111156117175761171661135d565b5b611723848285016116b5565b91505092915050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b600060e08301600083015161177060008601826113bb565b50602083015161178360208601826113bb565b506040830151848203604086015261179b8282611421565b91505060608301516117b060608601826113bb565b5060808301516117c360808601826113bb565b5060a08301516117d660a08601826113bb565b5060c08301516117e960c08601826113bb565b508091505092915050565b60006118008383611758565b905092915050565b6000602082019050919050565b60006118208261172c565b61182a8185611737565b93508360208202850161183c85611748565b8060005b85811015611878578484038952815161185985826117f4565b945061186483611808565b925060208a01995050600181019050611840565b50829750879550505050505092915050565b600060208201905081810360008301526118a48184611815565b905092915050565b6000819050919050565b6118bf816118ac565b81146118ca57600080fd5b50565b6000813590506118dc816118b6565b92915050565b600080604083850312156118f9576118f8611358565b5b6000611907858286016118cd565b925050602061191885828601611379565b9150509250929050565b61192b816118ac565b82525050565b600081519050919050565b600082825260208201905092915050565b600061195882611931565b611962818561193c565b93506119728185602086016113e6565b61197b81611410565b840191505092915050565b60008115159050919050565b61199b81611986565b82525050565b600060a0830160008301516119b960008601826113bb565b5060208301516119cc6020860182611922565b50604083015184820360408601526119e4828261194d565b91505060608301516119f96060860182611992565b506080830151611a0c60808601826113bb565b508091505092915050565b60006020820190508181036000830152611a3181846119a1565b905092915050565b600060208284031215611a4f57611a4e611358565b5b6000611a5d848285016118cd565b91505092915050565b600060ff82169050919050565b611a7c81611a66565b82525050565b600082825260208201905092915050565b6000611a9e8261123c565b611aa88185611a82565b9350611ab383611258565b8060005b83811015611ae4578151611acb88826112a9565b9750611ad6836112c1565b925050600181019050611ab7565b5085935050505092915050565b60006101e083016000830151611b0a60008601826113bb565b506020830151611b1d60208601826113bb565b506040830151611b306040860182611992565b506060830151611b436060860182611992565b5060808301518482036080860152611b5b8282611421565b91505060a0830151611b7060a0860182611a73565b5060c0830151611b8360c08601826113bb565b5060e0830151611b9660e08601826113bb565b50610100830151611bab6101008601826113bb565b50610120830151848203610120860152611bc58282611421565b915050610140830151611bdc61014086018261129a565b50610160830151611bf161016086018261129a565b50610180830151848203610180860152611c0b8282611a93565b9150506101a0830151611c226101a0860182611a73565b506101c0830151611c376101c0860182611992565b508091505092915050565b60006020820190508181036000830152611c5c8184611af1565b905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611cab57607f821691505b602082108103611cbe57611cbd611c64565b5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b611cfc816118ac565b82525050565b6000602082019050611d176000830184611cf3565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000611d5782611a66565b915060ff8203611d6a57611d69611d1d565b5b600182019050919050565b611d7e81611986565b82525050565b6000604082019050611d996000830185611d75565b611da66020830184611571565b939250505056fea2646970667358221220d9b7b645b9e097edd26b48b07416dd07b190412249bb1e2930964721efecc56f64736f6c63430008120033", "devdoc": { "kind": "dev", "methods": { diff --git a/deployments/baseGoerli/_DefaultDiamondCutFacet.json b/deployments/arbitrum/_DefaultDiamondCutFacet.json similarity index 97% rename from deployments/baseGoerli/_DefaultDiamondCutFacet.json rename to deployments/arbitrum/_DefaultDiamondCutFacet.json index 3c641e0..6be56d3 100644 --- a/deployments/baseGoerli/_DefaultDiamondCutFacet.json +++ b/deployments/arbitrum/_DefaultDiamondCutFacet.json @@ -84,22 +84,6 @@ "type": "function" } ], - "transactionHash": "0x49f14f237472348d201c98fec06e6c90af3751d8a72cc9afb3b58fcd6d7caafd", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 2, - "gasUsed": "1648898", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x28307f929de9785113f84bbbd28ae5c161e0feb87225473ee1aadb939954bf81", - "transactionHash": "0x49f14f237472348d201c98fec06e6c90af3751d8a72cc9afb3b58fcd6d7caafd", - "logs": [], - "blockNumber": 9669980, - "cumulativeGasUsed": "1737840", - "status": 1, - "byzantium": true - }, "args": [], "numDeployments": 1, "solcInputHash": "3fe12e823553336a8d0f950a5a792ac9", diff --git a/deployments/baseGoerli/_DefaultDiamondERC165Init.json b/deployments/arbitrum/_DefaultDiamondERC165Init.json similarity index 95% rename from deployments/baseGoerli/_DefaultDiamondERC165Init.json rename to deployments/arbitrum/_DefaultDiamondERC165Init.json index 3806993..94c6678 100644 --- a/deployments/baseGoerli/_DefaultDiamondERC165Init.json +++ b/deployments/arbitrum/_DefaultDiamondERC165Init.json @@ -20,22 +20,6 @@ "type": "function" } ], - "transactionHash": "0x4649665b16de0c503445ac647802c8fa677072a9ec0d47cff020333fc053b89e", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 2, - "gasUsed": "279490", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x4c48174c9226c2145de80478a4efd3501a7c3e0c75ee6bc10b716a0bf8eac740", - "transactionHash": "0x4649665b16de0c503445ac647802c8fa677072a9ec0d47cff020333fc053b89e", - "logs": [], - "blockNumber": 9669992, - "cumulativeGasUsed": "769506", - "status": 1, - "byzantium": true - }, "args": [], "numDeployments": 1, "solcInputHash": "3fe12e823553336a8d0f950a5a792ac9", diff --git a/deployments/baseGoerli/_DefaultDiamondLoupeFacet.json b/deployments/arbitrum/_DefaultDiamondLoupeFacet.json similarity index 96% rename from deployments/baseGoerli/_DefaultDiamondLoupeFacet.json rename to deployments/arbitrum/_DefaultDiamondLoupeFacet.json index 4e2bd4f..402ef0f 100644 --- a/deployments/baseGoerli/_DefaultDiamondLoupeFacet.json +++ b/deployments/arbitrum/_DefaultDiamondLoupeFacet.json @@ -97,22 +97,6 @@ "type": "function" } ], - "transactionHash": "0x38a7cc7c3f0509f21938997f92c1d3d6dc15a948a1d1aaa2e2b8dcbdecca24e9", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "511079", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x7e3520eac5bbff1d16d3fc6aa0f26b8a94e255842e51c4d4c2257785765a933a", - "transactionHash": "0x38a7cc7c3f0509f21938997f92c1d3d6dc15a948a1d1aaa2e2b8dcbdecca24e9", - "logs": [], - "blockNumber": 9669986, - "cumulativeGasUsed": "557920", - "status": 1, - "byzantium": true - }, "args": [], "numDeployments": 1, "solcInputHash": "3fe12e823553336a8d0f950a5a792ac9", diff --git a/deployments/baseGoerli/_DefaultDiamondOwnershipFacet.json b/deployments/arbitrum/_DefaultDiamondOwnershipFacet.json similarity index 94% rename from deployments/baseGoerli/_DefaultDiamondOwnershipFacet.json rename to deployments/arbitrum/_DefaultDiamondOwnershipFacet.json index 6770098..690ff62 100644 --- a/deployments/baseGoerli/_DefaultDiamondOwnershipFacet.json +++ b/deployments/arbitrum/_DefaultDiamondOwnershipFacet.json @@ -47,22 +47,6 @@ "type": "function" } ], - "transactionHash": "0x6ba3657da479696ea0fb11c3b54129211833f66d7d62942c4775ce8cce6045a0", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "209732", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x657d515e1d0a1e66efb91ad1ca62c56d8f937da1b12472b9effe84c0f7f7ee00", - "transactionHash": "0x6ba3657da479696ea0fb11c3b54129211833f66d7d62942c4775ce8cce6045a0", - "logs": [], - "blockNumber": 9669983, - "cumulativeGasUsed": "256573", - "status": 1, - "byzantium": true - }, "args": [], "numDeployments": 1, "solcInputHash": "3fe12e823553336a8d0f950a5a792ac9", diff --git a/deployments/baseGoerli/solcInputs/3fe12e823553336a8d0f950a5a792ac9.json b/deployments/arbitrum/solcInputs/3fe12e823553336a8d0f950a5a792ac9.json similarity index 100% rename from deployments/baseGoerli/solcInputs/3fe12e823553336a8d0f950a5a792ac9.json rename to deployments/arbitrum/solcInputs/3fe12e823553336a8d0f950a5a792ac9.json diff --git a/deployments/arbitrum/solcInputs/69b6ccc89b7eaa4e346529a9a529edba.json b/deployments/arbitrum/solcInputs/69b6ccc89b7eaa4e346529a9a529edba.json new file mode 100644 index 0000000..766851f --- /dev/null +++ b/deployments/arbitrum/solcInputs/69b6ccc89b7eaa4e346529a9a529edba.json @@ -0,0 +1,95 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@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/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/facets/AdminFacet.sol": { + "content": "// SPDX-License-Identifier: Unlicense\n\npragma solidity 0.8.18;\n\nimport \"../storage/LibAppStorage.sol\";\n\nimport {LibDiamond} from \"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\";\n\n/// @notice Caller of any function in this facet must be the admin address\ncontract AdminFacet {\n event SetProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage);\n event SetCursedBondPercentage(uint256 cursedBondPercentage);\n event WithdrawProtocolFees(uint256 totalProtocolFees, address withdrawalAddress);\n event SetGracePeriod(uint256 gracePeriod);\n event SetEmbalmerClaimWindow(uint256 embalmerClaimWindow);\n event SetExpirationThreshold(uint256 expirationThreshold);\n event AdminTransferred(address indexed previousAdmin, address indexed newAdmin);\n\n /// @notice Admin has attempted to set a zero value\n error CannotSetZeroValue();\n\n /// @notice Caller must be the admin address\n error CallerIsNotAdminOrOwner();\n\n /// @notice Provided address cannot be zero address\n error ZeroAddress();\n\n /// @notice Modifier to enforce caller is admin or contract owner\n modifier onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n if (msg.sender != s.admin && msg.sender != LibDiamond.contractOwner()) {\n revert CallerIsNotAdminOrOwner();\n }\n _;\n }\n\n /// @notice Withdraws the total protocol fee amount from the contract to the specified address\n /// @param withdrawalAddress - the address to withdraw funds to\n function withdrawProtocolFees(address withdrawalAddress) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n // Get the total protocol fees from storage\n uint256 totalProtocolFees = s.totalProtocolFees;\n // Set the total protocol fees to 0 before the transfer to avoid reentrancy\n s.totalProtocolFees = 0;\n // Transfer the protocol fee amount to the sender after setting state\n s.sarcoToken.transfer(withdrawalAddress, totalProtocolFees);\n emit WithdrawProtocolFees(totalProtocolFees, withdrawalAddress);\n }\n\n /// @notice Sets the protocol fee base percentage, used to calculate protocol fees\n /// @notice The denominator is 10000\n /// @param protocolFeeBasePercentage percentage to set\n function setProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\n emit SetProtocolFeeBasePercentage(protocolFeeBasePercentage);\n }\n\n /// @notice Sets the digging fee / cursed bond ratio\n /// @notice The denominator is 10000\n /// used to calculate how much bond archaeologists must lock per curse.\n /// @param cursedBondPercentage ratio to set.\n function setCursedBondPercentage(uint256 cursedBondPercentage) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n if (cursedBondPercentage == 0) {\n revert CannotSetZeroValue();\n }\n s.cursedBondPercentage = cursedBondPercentage;\n emit SetCursedBondPercentage(cursedBondPercentage);\n }\n\n /// @notice Updates the resurrection grace period\n /// @notice Denominated in seconds\n /// @param gracePeriod to set\n function setGracePeriod(uint256 gracePeriod) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n s.gracePeriod = gracePeriod;\n emit SetGracePeriod(gracePeriod);\n }\n\n /// @notice Updates the embalmerClaimWindow\n /// @notice Denominated in seconds\n /// @param embalmerClaimWindow to set\n function setEmbalmerClaimWindow(uint256 embalmerClaimWindow) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n s.embalmerClaimWindow = embalmerClaimWindow;\n emit SetEmbalmerClaimWindow(embalmerClaimWindow);\n }\n\n /// @notice Updates the expirationThreshold used during sarcophagus creation\n /// @notice Denominated in seconds\n /// @param expirationThreshold to set\n function setExpirationThreshold(uint256 expirationThreshold) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n s.expirationThreshold = expirationThreshold;\n emit SetExpirationThreshold(expirationThreshold);\n }\n\n /// @notice Transfers admin address to newAdmin.\n /// @param newAdmin to set\n function transferAdmin(address newAdmin) external onlyAdmin {\n AppStorage storage s = LibAppStorage.getAppStorage();\n if (newAdmin == address(0)) {\n revert ZeroAddress();\n }\n s.admin = newAdmin;\n emit AdminTransferred(msg.sender, newAdmin);\n }\n\n /// @notice Transfers diamond owner to new owner.\n /// @param newOwner to set\n function transferDiamondOwner(address newOwner) external {\n LibDiamond.enforceIsContractOwner();\n LibDiamond.setContractOwner(newOwner);\n }\n\n /// @notice Returns current owner of Diamond contract.\n function getDiamondOwner() external view returns (address) {\n return LibDiamond.contractOwner();\n }\n}\n" + }, + "contracts/facets/ArchaeologistFacet.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../libraries/LibTypes.sol\";\nimport \"../storage/LibAppStorage.sol\";\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\nimport {LibPrivateKeys} from \"../libraries/LibPrivateKeys.sol\";\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\nimport {LibBonds} from \"../libraries/LibBonds.sol\";\n\ncontract ArchaeologistFacet {\n /// @notice Emitted when an archaeologist successfully publishes their private key for a sarcophagus\n /// @param sarcoId ID of sarcophagus archaeologist has published the private key on\n /// @param privateKey private key that has been published\n event PublishPrivateKey(\n bytes32 indexed sarcoId,\n bytes32 privateKey,\n address indexed archaeologist\n );\n\n event DepositFreeBond(address indexed archaeologist, uint256 depositedBond);\n\n event RegisterArchaeologist(\n address indexed archaeologist,\n string peerId,\n uint256 minimumDiggingFee,\n uint256 maximumRewrapInterval,\n uint256 freeBond,\n uint256 maximumResurrectionTime,\n uint256 curseFee\n );\n\n event UpdateArchaeologist(\n address indexed archaeologist,\n string peerId,\n uint256 minimumDiggingFee,\n uint256 maximumRewrapInterval,\n uint256 freeBond,\n uint256 maximumResurrectionTime,\n uint256 curseFee\n );\n\n event WithdrawFreeBond(address indexed archaeologist, uint256 withdrawnBond);\n\n event WithdrawReward(address indexed archaeologist, uint256 withdrawnReward);\n\n /// @notice An archaeologist that has already been successfully accused has attempted to publish their private key\n /// @param archaeologistAddress Address of accused archaeologist who is attempting to publish their private key\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a key on\n error ArchaeologistHasBeenAccused(address archaeologistAddress, bytes32 sarcoId);\n\n /// @notice Archaeologist has attempted to publish a key before the resurrection time\n /// @param currentTime Timestamp of the failed publish attempt\n /// @param resurrectionTime Time after which the sarcophagus can be resurrected\n error TooEarlyForPublish(uint256 currentTime, uint256 resurrectionTime);\n\n /// @notice Archaeologist has attempted to publish a key after the end of the resurrection window\n /// @param currentTime Timestamp of the failed publish attempt\n /// @param publishDeadline Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)\n error TooLateForPublish(uint256 currentTime, uint256 publishDeadline);\n\n /// @notice Archaeologist has attempted to publish a key for a sarcophagus twice\n /// @param archaeologistAddress address of publishing archaeologist\n error ArchaeologistAlreadyPublishedPrivateKey(address archaeologistAddress);\n\n /// @notice Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval\n error CannotSetZeroProfileValue();\n\n /// @notice Archaeologist has attempted to publish the incorrect private key for a sarcophagus\n /// @param archaeologistAddress address of publishing archaeologist\n /// @param publicKey publicKey stored for archaeologist on the sarcophagus\n /// @param privateKey privateKey the archaeologist has attempted to publish\n error ArchaeologistPublishedIncorrectPrivateKey(\n address archaeologistAddress,\n bytes publicKey,\n bytes32 privateKey\n );\n\n /// @notice Registers the archaeologist profile\n /// @param peerId The libp2p identifier for the archaeologist\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\n /// for a resurrection\n /// @param freeBond How much bond the archaeologist wants to deposit during the register call (if any)\n /// @param maximumResurrectionTime The time beyond which the archaeologist is not willing to accept new curses or rewraps\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\n function registerArchaeologist(\n string memory peerId,\n uint256 minimumDiggingFeePerSecond,\n uint256 maximumRewrapInterval,\n uint256 freeBond,\n uint256 maximumResurrectionTime,\n uint256 curseFee\n ) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n // verify that the archaeologist does not already exist\n LibUtils.revertIfArchProfileExists(msg.sender);\n\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\n revert CannotSetZeroProfileValue();\n }\n\n // create a new archaeologist\n LibTypes.ArchaeologistProfile memory newArch = LibTypes.ArchaeologistProfile({\n peerId: peerId,\n minimumDiggingFeePerSecond: minimumDiggingFeePerSecond,\n maximumResurrectionTime: maximumResurrectionTime,\n maximumRewrapInterval: maximumRewrapInterval,\n freeBond: freeBond,\n cursedBond: 0,\n curseFee: curseFee\n });\n\n // transfer SARCO tokens from the archaeologist to this contract, to be\n // used as their free bond. can be 0.\n if (freeBond != 0) {\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\n }\n\n // save the new archaeologist into relevant data structures\n s.archaeologistProfiles[msg.sender] = newArch;\n s.archaeologistProfileAddresses.push(msg.sender);\n\n emit RegisterArchaeologist(\n msg.sender,\n newArch.peerId,\n newArch.minimumDiggingFeePerSecond,\n newArch.maximumRewrapInterval,\n newArch.freeBond,\n newArch.maximumResurrectionTime,\n newArch.curseFee\n );\n }\n\n /// @notice Updates the archaeologist profile\n /// @param peerId The libp2p identifier for the archaeologist\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\n /// @param freeBond How much bond the archaeologist wants to deposit during the update call (if any)\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\n /// for a resurrection\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\n function updateArchaeologist(\n string memory peerId,\n uint256 minimumDiggingFeePerSecond,\n uint256 maximumRewrapInterval,\n uint256 freeBond,\n uint256 maximumResurrectionTime,\n uint256 curseFee\n ) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n\n // verify that the archaeologist exists\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\n\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\n revert CannotSetZeroProfileValue();\n }\n\n LibTypes.ArchaeologistProfile storage existingArch = s.archaeologistProfiles[msg.sender];\n existingArch.peerId = peerId;\n existingArch.minimumDiggingFeePerSecond = minimumDiggingFeePerSecond;\n existingArch.maximumRewrapInterval = maximumRewrapInterval;\n existingArch.maximumResurrectionTime = maximumResurrectionTime;\n existingArch.curseFee = curseFee;\n\n // transfer SARCO tokens from the archaeologist to this contract, to be\n // used as their free bond. can be 0.\n if (freeBond != 0) {\n s.archaeologistProfiles[msg.sender].freeBond += freeBond;\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\n }\n\n emit UpdateArchaeologist(\n msg.sender,\n existingArch.peerId,\n existingArch.minimumDiggingFeePerSecond,\n existingArch.maximumRewrapInterval,\n freeBond,\n existingArch.maximumResurrectionTime,\n existingArch.curseFee\n );\n }\n\n /// @notice Deposits an archaeologist's free bond to the contract.\n /// @param amount The amount to deposit\n function depositFreeBond(uint256 amount) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\n\n // Increase the archaeologist's free bond in app storage\n s.archaeologistProfiles[msg.sender].freeBond += amount;\n\n // Transfer the amount of sarcoToken from the archaeologist to the contract\n s.sarcoToken.transferFrom(msg.sender, address(this), amount);\n // Emit an event\n emit DepositFreeBond(msg.sender, amount);\n }\n\n /// @notice Withdraws an archaeologist's free bond from the contract.\n /// @param amount The amount to withdraw\n function withdrawFreeBond(uint256 amount) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\n // Decrease the archaeologist's free bond amount.\n // Reverts if there is not enough free bond on the contract.\n s.archaeologistProfiles[msg.sender].freeBond -= amount;\n\n // Transfer the amount of sarcoToken to the archaeologist\n s.sarcoToken.transfer(msg.sender, amount);\n\n emit WithdrawFreeBond(msg.sender, amount);\n }\n\n /// @notice Withdraws all rewards from an archaeologist's reward pool\n function withdrawReward() external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n uint256 amountToWithdraw = s.archaeologistRewards[msg.sender];\n s.archaeologistRewards[msg.sender] = 0;\n\n // Transfer the amount of sarcoToken to the archaeologist\n s.sarcoToken.transfer(msg.sender, amountToWithdraw);\n\n emit WithdrawReward(msg.sender, amountToWithdraw);\n }\n\n /// @notice Publishes the private key for which the archaeologist is responsible during the\n /// sarcophagus resurrection window.\n /// Pays digging fees to the archaeologist and releases their locked bond.\n /// Cannot be called on a compromised or buried sarcophagus.\n /// @param sarcoId The identifier of the sarcophagus for which the archaeologist is responsible\n /// @param privateKey The private key the archaeologist is publishing\n function publishPrivateKey(bytes32 sarcoId, bytes32 privateKey) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // Confirm sarcophagus exists\n if (sarcophagus.resurrectionTime == 0) {\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\n }\n\n // Confirm sarcophagus has not been compromised\n if (sarcophagus.isCompromised) {\n revert LibErrors.SarcophagusCompromised(sarcoId);\n }\n\n // Confirm sarcophagus is not buried\n if (sarcophagus.resurrectionTime == type(uint256).max) {\n revert LibErrors.SarcophagusInactive(sarcoId);\n }\n\n // Confirm current time is after resurrectionTime\n if (block.timestamp < sarcophagus.resurrectionTime) {\n revert TooEarlyForPublish(block.timestamp, sarcophagus.resurrectionTime);\n }\n\n // Confirm current time is within gracePeriod\n if (block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod) {\n revert TooLateForPublish(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\n }\n\n // Confirm tx sender is an archaeologist on the sarcophagus\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\n .sarcophagi[sarcoId]\n .cursedArchaeologists[msg.sender];\n if (cursedArchaeologist.publicKey.length == 0) {\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\n }\n\n // Confirm archaeologist has not already leaked their private key\n if (cursedArchaeologist.isAccused) {\n revert ArchaeologistHasBeenAccused(msg.sender, sarcoId);\n }\n\n // Confirm archaeologist has not already published their private key\n if (cursedArchaeologist.privateKey != 0) {\n revert ArchaeologistAlreadyPublishedPrivateKey(msg.sender);\n }\n\n // Confirm that the private key being submitted matches the public key stored on the\n // sarcophagus for this archaeologist\n if (!LibPrivateKeys.isPublicKeyOfPrivateKey(privateKey, cursedArchaeologist.publicKey)) {\n revert ArchaeologistPublishedIncorrectPrivateKey(\n msg.sender,\n cursedArchaeologist.publicKey,\n privateKey\n );\n }\n\n // Store the private key on cursed archaeologist\n cursedArchaeologist.privateKey = privateKey;\n\n // Free archaeologist locked bond and transfer digging fees\n LibBonds.freeArchaeologist(sarcoId, msg.sender);\n\n emit PublishPrivateKey(sarcoId, privateKey, msg.sender);\n }\n}\n" + }, + "contracts/facets/EmbalmerFacet.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\nimport \"../libraries/LibTypes.sol\";\nimport \"../storage/LibAppStorage.sol\";\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\nimport {LibBonds} from \"../libraries/LibBonds.sol\";\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\n\ncontract EmbalmerFacet {\n /// @notice Emitted when a sarcophagus is created\n /// @param sarcoId Id of the new sarcophagus\n /// @param name Name of the new sarcophagus\n /// @param resurrectionTime Resurrection time of the new sarcophagus\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\n /// @param embalmer Address of embalmer\n /// @param recipient Address of recipient\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\n /// @param arweaveTxId arweave tx id for the sarcophagus\n event CreateSarcophagus(\n bytes32 indexed sarcoId,\n string name,\n uint256 resurrectionTime,\n uint256 creationTime,\n address indexed embalmer,\n address indexed recipient,\n address[] cursedArchaeologists,\n uint256 totalDiggingFees,\n string arweaveTxId\n );\n\n /// @notice Emitted when a sarcophagus is rewrapped\n /// @param sarcoId Id of sarcophagus that was rewrapped\n /// @param resurrectionTime New resurrection time for the sarcophagus\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\n event RewrapSarcophagus(\n bytes32 indexed sarcoId,\n uint256 resurrectionTime,\n uint256 totalDiggingFees,\n uint256 rewrapSarcophagusProtocolFees\n );\n\n /// @notice Emitted when a sarcophagus is buried\n /// @param sarcoId Id of sarcophagus that was buried\n event BurySarcophagus(bytes32 indexed sarcoId);\n\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\n struct SarcophagusParams {\n string name;\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\n uint256 maximumRewrapInterval;\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\n uint256 maximumResurrectionTime;\n address recipientAddress;\n uint256 resurrectionTime;\n uint8 threshold;\n uint256 creationTime;\n }\n\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\n struct CurseParams {\n bytes publicKey;\n address archAddress;\n uint256 diggingFeePerSecond;\n uint256 curseFee;\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\n /// @param sarcoId Id that is already in use\n error SarcophagusAlreadyExists(bytes32 sarcoId);\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\n /// @param currentTime Timestamp of the failed create attempt\n /// @param creationTime Time when the sarcophagus parameters were created\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\n error SarcophagusParametersExpired(\n uint256 currentTime,\n uint256 creationTime,\n uint256 creationDeadline\n );\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\n error NoArchaeologistsProvided();\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\n error ThresholdCannotBeZero();\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\n uint8 threshold,\n uint256 totalNumberOfArchaeologists\n );\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\n\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\n /// @param currentTime Timestamp of the failed rewrap attempt\n /// @param resurrectionTime Resurrection timestamp which has already passed\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\n\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\n /// @param publicKey the duplicated public key\n error DuplicatePublicKey(bytes publicKey);\n\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\n error ResurrectionTimeTooFarInFuture(\n uint256 resurrectionTime,\n uint256 sarcophagusMaximumRewrapInterval,\n uint256 maximumPermissibleResurrectionTime\n );\n\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\n /// @param maxResurrectionTime The maximum allowed resurrection time\n error ResurrectionTimePastMaxResurrectionTime(\n uint256 resurrectionTime,\n uint256 maxResurrectionTime\n );\n\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\n\n error NewResurrectionTimeIsZero();\n\n error NewResurrectionTimeTooFarInFuture(\n uint256 resurrectionTime,\n uint256 sarcophagusMaximumRewrapInterval,\n uint256 maximumPermissibleResurrectionTime\n );\n\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\n uint256 resurrectionTime,\n uint256 previousResurrectionTime\n );\n\n /// @notice Creates a sarcophagus with the supplied parameters and locks\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\n /// of the sarcophagus until its resurrection time.\n ///\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\n /// - `publicKey` that matches the private key the archaeologist is responsible for\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\n /// - `creationTime` of sarcophagus\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\n ///\n /// @param sarcoId the identifier of the sarcophagus\n /// @param sarcophagusParams params to set on sarcophagus being created\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\n function createSarcophagus(\n bytes32 sarcoId,\n SarcophagusParams calldata sarcophagusParams,\n CurseParams[] calldata selectedArchaeologists,\n string calldata arweaveTxId\n ) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n\n // Confirm that sarcophagus with supplied id doesn't already exist\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\n revert SarcophagusAlreadyExists(sarcoId);\n }\n\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\n // off by its cursed archaeologists.\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\n revert SarcophagusParametersExpired(\n block.timestamp,\n sarcophagusParams.creationTime,\n sarcophagusParams.creationTime + s.expirationThreshold\n );\n }\n\n // Confirm that resurrection time is in the future\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\n }\n\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\n if (\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\n sarcophagusParams.resurrectionTime\n ) {\n revert ResurrectionTimeTooFarInFuture(\n sarcophagusParams.resurrectionTime,\n sarcophagusParams.maximumRewrapInterval,\n block.timestamp + sarcophagusParams.maximumRewrapInterval\n );\n }\n\n // Confirm that the resurrection time is less than the max resurrection time\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\n revert ResurrectionTimePastMaxResurrectionTime(\n sarcophagusParams.resurrectionTime,\n sarcophagusParams.maximumResurrectionTime\n );\n }\n\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // track total digging fees due upon creation of sarcophagus\n uint256 totalDiggingFees;\n\n {\n uint256 nSelectedArchs = selectedArchaeologists.length;\n // Validate archaeologist and threshold lengths\n if (nSelectedArchs == 0) {\n revert NoArchaeologistsProvided();\n }\n\n if (sarcophagusParams.threshold == 0) {\n revert ThresholdCannotBeZero();\n }\n\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\n // used to distribute keyshares among archaeologists\n if (sarcophagusParams.threshold > nSelectedArchs) {\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\n sarcophagusParams.threshold,\n nSelectedArchs\n );\n }\n\n // create the sarcophagus\n sarcophagus.name = sarcophagusParams.name;\n sarcophagus.threshold = sarcophagusParams.threshold;\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\n sarcophagus.arweaveTxId = arweaveTxId;\n sarcophagus.embalmerAddress = msg.sender;\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\n\n for (uint256 i; i < nSelectedArchs; ) {\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\n\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\n if (\n sarcophagus\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\n .publicKey\n .length != 0\n ) {\n revert ArchaeologistListContainsDuplicate(\n selectedArchaeologists[i].archAddress\n );\n }\n\n // Confirm archaeologist is not re-using a key pair\n if (\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\n address(0)\n ) {\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\n }\n\n LibUtils.verifyArchaeologistSignature(\n sarcophagusParams.maximumRewrapInterval,\n sarcophagusParams.maximumResurrectionTime,\n sarcophagusParams.creationTime,\n selectedArchaeologists[i]\n );\n\n // Curse the archaeologist on this sarcophagus\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\n sarcoId,\n selectedArchaeologists[i],\n i\n );\n\n totalDiggingFees += diggingFeesDue;\n\n // \"Consume\" this public key so it cannot be reused in the future\n s.publicKeyToArchaeologistAddress[\n selectedArchaeologists[i].publicKey\n ] = selectedArchaeologists[i].archAddress;\n unchecked {\n ++i;\n }\n }\n\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\n s.totalProtocolFees += protocolFees;\n s.sarcoToken.transferFrom(\n msg.sender,\n address(this),\n totalDiggingFees + protocolFees\n );\n }\n emit CreateSarcophagus(\n sarcoId,\n sarcophagusParams.name,\n sarcophagusParams.resurrectionTime,\n sarcophagusParams.creationTime,\n msg.sender,\n sarcophagusParams.recipientAddress,\n sarcophagus.cursedArchaeologistAddresses,\n totalDiggingFees,\n arweaveTxId\n );\n }\n\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\n /// @param sarcoId the identifier of the sarcophagus\n /// @param resurrectionTime the new resurrection time\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // Confirm the sarcophagus exists\n if (sarcophagus.resurrectionTime == 0) {\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\n }\n\n // Confirm the sarcophagus has not been compromised\n if (sarcophagus.isCompromised) {\n revert LibErrors.SarcophagusCompromised(sarcoId);\n }\n\n // Confirm the sarcophagus is not buried\n if (sarcophagus.resurrectionTime == type(uint256).max) {\n revert LibErrors.SarcophagusInactive(sarcoId);\n }\n\n // Confirm tx sender is embalmer\n if (sarcophagus.embalmerAddress != msg.sender) {\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\n }\n\n // Confirm resurrection time has not yet passed\n if (block.timestamp >= sarcophagus.resurrectionTime) {\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\n }\n\n // Confirm that new resurrection time is in future\n if (block.timestamp >= resurrectionTime) {\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\n }\n\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\n revert NewResurrectionTimeTooFarInFuture(\n resurrectionTime,\n sarcophagus.maximumRewrapInterval,\n block.timestamp + sarcophagus.maximumRewrapInterval\n );\n }\n\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\n revert ResurrectionTimePastMaxResurrectionTime(\n resurrectionTime,\n sarcophagus.maximumResurrectionTime\n );\n }\n\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\n uint256 totalDiggingFees;\n\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\n\n uint256 nArchAddresses = archaeologistAddresses.length;\n for (uint256 i; i < nArchAddresses; ) {\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\n .cursedArchaeologists[archaeologistAddresses[i]];\n\n if (!cursedArchaeologist.isAccused) {\n // Previous digging fees calculation ignores curseFee\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\n\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\n (resurrectionTime - block.timestamp);\n\n // If the new digging fees are greater than the previous digging fees, we need to\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\n if (newDiggingFees > prevDiggingFees) {\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\n cursedBondPercentage) / 10000;\n\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\n if (cursedBondIncrease > prevDiggingFees) {\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\n resurrectionTime,\n sarcophagus.resurrectionTime\n );\n }\n\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\n s.archaeologistProfiles[archaeologistAddresses[i]]\n .cursedBond += cursedBondIncrease;\n\n // Rewards are now previous digging fees - difference\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\n } else if (newDiggingFees < prevDiggingFees) {\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\n cursedBondPercentage) / 10000;\n\n // Decrease archaeologist's cursed bond by the difference\n s\n .archaeologistProfiles[archaeologistAddresses[i]]\n .cursedBond -= cursedBondDecrease;\n\n // Increase archaeologist's free bond by the difference\n s\n .archaeologistProfiles[archaeologistAddresses[i]]\n .freeBond += cursedBondDecrease;\n\n // Rewards are equal to the previous digging fees\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\n } else {\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\n }\n\n // Add digging fees due for the new interval\n totalDiggingFees += newDiggingFees;\n\n // If sarcophagus has not been rewrapped yet, pay out the curseFee\n if (!sarcophagus.isRewrapped) {\n // Pay archaeologists the curse fee to their rewards\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\n }\n }\n unchecked {\n ++i;\n }\n }\n\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\n\n // Add the protocol fee to the total protocol fees in storage\n s.totalProtocolFees += protocolFees;\n\n // Update the sarcophagus resurrectionTime and previousRewrapTime\n sarcophagus.resurrectionTime = resurrectionTime;\n sarcophagus.previousRewrapTime = block.timestamp;\n\n if (!sarcophagus.isRewrapped) {\n sarcophagus.isRewrapped = true;\n }\n\n // Transfer the new digging fees and protocol fees from embalmer to contract\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\n\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\n }\n\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\n /// @param sarcoId the identifier of the sarcophagus\n function burySarcophagus(bytes32 sarcoId) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // Confirm the sarcophagus exists\n if (sarcophagus.resurrectionTime == 0) {\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\n }\n\n // Confirm the sarcophagus has not been compromised\n if (sarcophagus.isCompromised) {\n revert LibErrors.SarcophagusCompromised(sarcoId);\n }\n\n // Confirm the sarcophagus is not buried\n if (sarcophagus.resurrectionTime == type(uint256).max) {\n revert LibErrors.SarcophagusInactive(sarcoId);\n }\n\n // Confirm tx sender is embalmer\n if (sarcophagus.embalmerAddress != msg.sender) {\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\n }\n // Confirm that the current resurrection time is in the future\n if (block.timestamp >= sarcophagus.resurrectionTime) {\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\n }\n\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\n uint256 nArchAddresses = archaeologistAddresses.length;\n for (uint256 i; i < nArchAddresses; ) {\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\n .cursedArchaeologists[archaeologistAddresses[i]];\n\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\n if (!cursedArchaeologist.isAccused) {\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\n }\n unchecked {\n ++i;\n }\n }\n\n // Set resurrection time to infinity\n sarcophagus.resurrectionTime = type(uint256).max;\n\n emit BurySarcophagus(sarcoId);\n }\n}\n" + }, + "contracts/facets/ThirdPartyFacet.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport {LibDiamond} from \"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\";\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"../libraries/LibTypes.sol\";\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\nimport {LibBonds} from \"../libraries/LibBonds.sol\";\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\nimport \"../storage/LibAppStorage.sol\";\nimport \"../libraries/LibTypes.sol\";\n\ncontract ThirdPartyFacet {\n event AccuseArchaeologist(\n bytes32 indexed sarcoId,\n address indexed accuser,\n uint256 totalSlashedBondDistributed,\n uint256 totalDiggingFeesDistributed,\n address[] accusedArchAddresses\n );\n\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\n\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\n\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\n /// @param currentTime Timestamp of the failed clean attempt\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\n\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\n /// @param senderAddress Address of sender\n error SenderNotEmbalmerOrAdmin(address senderAddress);\n\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\n /// @param currentTime Timestamp of the failed clean attempt\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\n\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\n /// @param currentTime Timestamp of the failed clean attempt\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\n\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\n /// @param currentTime Timestamp of the failed accuse attempt\n /// @param resurrectionTime Resurrection timestamp which has already passed\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\n\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\n /// @param signatures the number of signatures passed into the accuse call\n /// @param publicKeys the number of public keys passed into the accuse call\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\n\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\n /// @param sarcoId that should have been signed\n /// @param paymentAddress payment address that should have been signed\n /// @param publicKey publicKey that should be derived from signing key\n /// @param signature invalid signature\n error InvalidAccusalSignature(\n bytes32 sarcoId,\n address paymentAddress,\n bytes publicKey,\n LibTypes.Signature signature\n );\n\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\n /// be able to claim remaining locked bond and diggingFees\n /// @param sarcoId The identifier of the sarcophagus to clean\n function clean(bytes32 sarcoId) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // Confirm the sarcophagus exists\n if (sarcophagus.resurrectionTime == 0) {\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\n }\n\n // Confirm tx sender is embalmer or admin\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\n revert SenderNotEmbalmerOrAdmin(msg.sender);\n }\n\n // Confirm the sarcophagus has not been compromised\n if (sarcophagus.isCompromised) {\n revert LibErrors.SarcophagusCompromised(sarcoId);\n }\n\n // Confirm the sarcophagus is not buried\n if (sarcophagus.resurrectionTime == type(uint256).max) {\n revert LibErrors.SarcophagusInactive(sarcoId);\n }\n\n // Confirm the sarcophagus has not already been cleaned\n if (sarcophagus.isCleaned) {\n revert SarcophagusAlreadyCleaned(sarcoId);\n }\n\n // Confirm that the resurrectionTime + gracePeriod have passed\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\n }\n\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\n if (\n msg.sender == sarcophagus.embalmerAddress &&\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\n ) {\n revert EmbalmerClaimWindowPassed(\n block.timestamp,\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\n );\n }\n\n // if sender is admin, confirm embalmerClaimWindow has passed\n if (\n msg.sender == LibDiamond.contractOwner() &&\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\n ) {\n revert TooEarlyForAdminClean(\n block.timestamp,\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\n );\n }\n\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\n uint256 totalDiggingFeesAndLockedBonds;\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\n\n for (uint256 i; i < nCursedArchs; ) {\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\n\n // Punish archaeologists that failed to publish their private key in time\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\n\n if (!sarcophagus.isRewrapped) {\n diggingFeesDue += cursedArchaeologist.curseFee;\n }\n\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\n\n // slash the archaeologist's locked bond for the sarcophagus\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\n }\n unchecked {\n ++i;\n }\n }\n\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\n // this to the contract's protocol fees\n if (msg.sender == sarcophagus.embalmerAddress) {\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\n } else {\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\n }\n\n sarcophagus.isCleaned = true;\n emit Clean(sarcoId, msg.sender);\n }\n\n /**\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\n * and payment address generated with the leaked private keys\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\n *\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\n * returned\n *\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\n * @param paymentAddress the address to which rewards should be sent if successful\n */\n function accuse(\n bytes32 sarcoId,\n bytes[] calldata publicKeys,\n LibTypes.Signature[] calldata signatures,\n address paymentAddress\n ) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // Confirm sarcophagus exists\n if (sarcophagus.resurrectionTime == 0) {\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\n }\n\n // verify that current time is not past resurrection time\n if (block.timestamp > sarcophagus.resurrectionTime) {\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\n }\n\n // Confirm the sarcophagus has not been compromised\n if (sarcophagus.isCompromised) {\n revert LibErrors.SarcophagusCompromised(sarcoId);\n }\n\n // Confirm the sarcophagus is not buried\n if (sarcophagus.resurrectionTime == type(uint256).max) {\n revert LibErrors.SarcophagusInactive(sarcoId);\n }\n\n uint256 nSigs = signatures.length;\n\n if (nSigs != publicKeys.length) {\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\n }\n\n address[] memory accusedArchAddresses = new address[](nSigs);\n\n // track the combined locked bond across all archaeologists being accused in this call\n uint256 totalCursedBond;\n uint256 accusalCount;\n for (uint256 i; i < nSigs; ) {\n if (\n !LibUtils.verifyAccusalSignature(\n sarcoId,\n paymentAddress,\n publicKeys[i],\n signatures[i]\n )\n ) {\n revert InvalidAccusalSignature(\n sarcoId,\n paymentAddress,\n publicKeys[i],\n signatures[i]\n );\n }\n\n // look up the archaeologist responsible for the publicKey\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\n .cursedArchaeologists[accusedArchaeologistAddress];\n\n // verify the accused archaeologist is cursed on the sarcophagus\n if (accusedArchaeologist.publicKey.length == 0) {\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\n }\n\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\n if (accusedArchaeologist.isAccused) {\n unchecked {\n ++i;\n }\n continue;\n }\n\n // mark the archaeologist on the sarcophagus as having been accused\n accusedArchaeologist.isAccused = true;\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\n\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\n sarcophagus.cursedBondPercentage) / 10000;\n\n // If the sarcophagus has not been rewrapped, also slash the curse fee\n if (!sarcophagus.isRewrapped) {\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\n }\n\n totalCursedBond += cursedBondDue;\n\n // Slash the offending archaeologists bond\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\n unchecked {\n ++i;\n }\n }\n\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\n if (accusalCount == 0) {\n return;\n }\n\n {\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\n\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\n if (accusalCount >= sarcophagus.threshold) {\n sarcophagus.isCompromised = true;\n } else {\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\n // check if total number of historical accusals on sarcophagus is greater than threshold\n uint256 totalAccusals;\n\n for (uint256 i; i < nCursedArchs; ) {\n if (\n sarcophagus\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\n .isAccused\n ) {\n ++totalAccusals;\n }\n unchecked {\n ++i;\n }\n }\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\n if (totalAccusals >= sarcophagus.threshold) {\n sarcophagus.isCompromised = true;\n }\n }\n\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\n // be returned to the remaining well behaved archaeologists\n if (sarcophagus.isCompromised) {\n // iterate through all archaeologist addresses on the sarcophagus\n for (uint256 i; i < nCursedArchs; ) {\n // if the archaeologist has never been accused, release their locked bond back to them\n if (\n !sarcophagus\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\n .isAccused\n ) {\n LibBonds.freeArchaeologist(\n sarcoId,\n sarcophagus.cursedArchaeologistAddresses[i]\n );\n }\n unchecked {\n ++i;\n }\n }\n }\n }\n\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\n // transfer the cursed half, plus the current digging fees, to the embalmer\n s.sarcoToken.transfer(\n sarcophagus.embalmerAddress,\n totalDiggingFees + halfTotalCursedBond\n );\n\n // transfer the other half of the cursed bond to the transaction caller\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\n\n emit AccuseArchaeologist(\n sarcoId,\n msg.sender,\n totalCursedBond,\n totalDiggingFees,\n accusedArchAddresses\n );\n }\n}\n" + }, + "contracts/facets/ViewStateFacet.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"../libraries/LibTypes.sol\";\nimport \"../libraries/LibUtils.sol\";\nimport \"../storage/LibAppStorage.sol\";\n\ncontract ViewStateFacet {\n /// @notice Get the admin address from diamond storage\n /// @return The admin address\n function getAdmin() external view returns (address) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.admin;\n }\n\n /// @notice Gets the total protocol fees from diamond storage\n /// @return The total protocol fees\n function getTotalProtocolFees() external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.totalProtocolFees;\n }\n\n /// @notice Get the protocol fee base percentage from diamond storage\n /// @return The protocol fee base percentage - protocolFeeBasePercentage\n function getProtocolFeeBasePercentage() external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.protocolFeeBasePercentage;\n }\n\n /// @notice Get the cursed bond percentage from diamond storage\n /// @return The cursed bond percentage - cursedBondPercentage\n function getCursedBondPercentage() external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.cursedBondPercentage;\n }\n\n /// @notice Gets archaeologist profiles given a list of archaeologist addresses.\n /// If an invalid address is included, simply leaves it out of the list.\n /// @param addresses The list of archaeologist addresses\n /// @return The list of archaeologist profiles\n function getArchaeologistProfiles(\n address[] memory addresses\n ) external view returns (LibTypes.ArchaeologistProfile[] memory) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n uint256 nAddresses = addresses.length;\n LibTypes.ArchaeologistProfile[] memory profiles = new LibTypes.ArchaeologistProfile[](\n nAddresses\n );\n\n for (uint256 i; i < nAddresses; ) {\n // Skip unregistered archaeologists\n if (s.archaeologistProfiles[addresses[i]].maximumRewrapInterval == 0) {\n continue;\n }\n profiles[i] = s.archaeologistProfiles[addresses[i]];\n unchecked {\n ++i;\n }\n }\n\n return profiles;\n }\n\n /// @notice Gets the grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time passes\n /// @return The resurrection grace period\n function getGracePeriod() external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.gracePeriod;\n }\n\n /// @notice Gets the window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys\n /// @return The embalmer claim window\n function getEmbalmerClaimWindow() external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.embalmerClaimWindow;\n }\n\n /// @notice Gets the expiration threshold after which a sarcophagus must be renegotiated\n /// @return The expiration threshold\n function getExpirationThreshold() external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.expirationThreshold;\n }\n\n /// @notice Given an archaeologist address, return that archaeologist's\n /// profile\n /// @param archaeologist The archaeologist account's address\n /// @return the Archaeologist object\n function getArchaeologistProfile(\n address archaeologist\n ) external view returns (LibTypes.ArchaeologistProfile memory) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibUtils.revertIfArchProfileDoesNotExist(archaeologist);\n return s.archaeologistProfiles[archaeologist];\n }\n\n /// @notice Return the list of registereed archaeologist addresses.\n /// @return addresses of registered archaeologists\n function getArchaeologistProfileAddresses() external view returns (address[] memory) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.archaeologistProfileAddresses;\n }\n\n /// @notice Given an index (of the full archaeologist array), return the\n /// archaeologist address at that index\n /// @param index The index of the registered archaeologist\n /// @return address of the archaeologist\n function getArchaeologistProfileAddressAtIndex(uint256 index) external view returns (address) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.archaeologistProfileAddresses[index];\n }\n\n /// @notice Returns the amount of free bond stored in the contract for an\n /// archaeologist.\n /// @param archaeologist The address of the archaeologist whose\n /// free bond is being returned\n function getFreeBond(address archaeologist) external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.archaeologistProfiles[archaeologist].freeBond;\n }\n\n /// @notice Returns the amount of rewards stored in the contract for an\n /// archaeologist.\n /// @param archaeologist The address of the archaeologist whose\n /// reward is being returned\n function getRewards(address archaeologist) external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.archaeologistRewards[archaeologist];\n }\n\n /// @notice Returns the amount of cursed bond stored in the contract for an\n /// archaeologist.\n /// @param archaeologist The address of the archaeologist whose\n /// cursed bond is being returned\n function getCursedBond(address archaeologist) external view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.archaeologistProfiles[archaeologist].cursedBond;\n }\n\n struct SarcophagusResponse {\n uint256 resurrectionTime;\n uint256 previousRewrapTime;\n bool isCompromised;\n bool isCleaned;\n string name;\n uint8 threshold;\n uint256 maximumRewrapInterval;\n uint256 maximumResurrectionTime;\n uint256 cursedBondPercentage;\n string arweaveTxId;\n address embalmerAddress;\n address recipientAddress;\n address[] archaeologistAddresses;\n uint8 publishedPrivateKeyCount;\n bool hasLockedBond;\n }\n\n /// @notice Returns data on the sarcophagus with the supplied id\n /// includes aggregate data on cursed archaeologists associated with the sarcophagus\n /// - publishedPrivateKeyCount - the total number of private keys published by archaeologists on the sarcophagus\n /// - hasLockedBond - true if archaeologists still have bond locked in the contract for this sarcophagus\n /// @param sarcoId The identifier of the sarcophagus being returned\n function getSarcophagus(bytes32 sarcoId) external view returns (SarcophagusResponse memory) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n // Confirm sarcophagus exists\n if (sarcophagus.resurrectionTime == 0) {\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\n }\n\n uint8 publishedPrivateKeyCount;\n bool hasLockedBond;\n uint256 archsLength = sarcophagus.cursedArchaeologistAddresses.length;\n for (uint256 i; i < archsLength; ) {\n // archaeologist has published a private key\n if (\n sarcophagus\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\n .privateKey != 0\n ) {\n ++publishedPrivateKeyCount;\n } else if (\n !sarcophagus\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\n .isAccused &&\n !sarcophagus.isCompromised &&\n !sarcophagus.isCleaned &&\n sarcophagus.resurrectionTime != type(uint256).max\n ) {\n // if the sarcophagus is not compromised, buried, or cleaned and\n // one or more unaccused archaeologists hasn't published a private key there is locked bond on the sarcophagus\n hasLockedBond = true;\n }\n unchecked {\n ++i;\n }\n }\n\n return\n SarcophagusResponse({\n resurrectionTime: sarcophagus.resurrectionTime,\n previousRewrapTime: sarcophagus.previousRewrapTime,\n isCompromised: sarcophagus.isCompromised,\n isCleaned: sarcophagus.isCleaned,\n name: sarcophagus.name,\n threshold: sarcophagus.threshold,\n maximumRewrapInterval: sarcophagus.maximumRewrapInterval,\n maximumResurrectionTime: sarcophagus.maximumResurrectionTime,\n cursedBondPercentage: sarcophagus.cursedBondPercentage,\n arweaveTxId: sarcophagus.arweaveTxId,\n embalmerAddress: sarcophagus.embalmerAddress,\n recipientAddress: sarcophagus.recipientAddress,\n archaeologistAddresses: sarcophagus.cursedArchaeologistAddresses,\n publishedPrivateKeyCount: publishedPrivateKeyCount,\n hasLockedBond: hasLockedBond\n });\n }\n\n /// @notice Returns the data stored on a sarcophagus for an archaeologist.\n /// @param sarcoId The identifier of the sarcophagus whose data is being\n /// returned\n /// @param archaeologist The address of the archaeologist whose data is\n /// being returned\n function getSarcophagusArchaeologist(\n bytes32 sarcoId,\n address archaeologist\n ) external view returns (LibTypes.CursedArchaeologist memory) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n return s.sarcophagi[sarcoId].cursedArchaeologists[archaeologist];\n }\n}\n" + }, + "contracts/libraries/LibBonds.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"../storage/LibAppStorage.sol\";\nimport \"../libraries/LibTypes.sol\";\nimport {LibErrors} from \"./LibErrors.sol\";\n\nimport \"../facets/EmbalmerFacet.sol\";\n\nlibrary LibBonds {\n /// @notice Bonds the archaeologist to a sarcophagus.\n /// This does the following:\n /// - adds the archaeologist's curse params and address to the sarcophagus\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\n ///\n /// @return the amount of digging fees due the embalmer for this curse\n function curseArchaeologist(\n bytes32 sarcoId,\n EmbalmerFacet.CurseParams calldata archaeologist,\n uint256 index\n ) internal returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\n publicKey: archaeologist.publicKey,\n privateKey: 0,\n isAccused: false,\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\n curseFee: archaeologist.curseFee\n });\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\n\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\n + archaeologist.curseFee;\n\n // Use cursed bond percentage to determine how much bond to lock up\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\n\n // Transfer bond to curse from free bond to cursed bond\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\n\n return diggingFeesDue;\n }\n\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\n /// @param archaeologistAddress the address of the archaeologist to free\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\n AppStorage storage s = LibAppStorage.getAppStorage();\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\n\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\n .sarcophagi[sarcoId]\n .cursedArchaeologists[archaeologistAddress];\n\n // Calculate the digging fees to be paid since the last rewrap (or creation)\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\n\n // Include curse fee in bond amount being released\n uint256 cursedBondAmount = ((diggingFeeAmount + cursedArchaeologist.curseFee) * sarcophagus.cursedBondPercentage) / 10000;\n\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\n\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\n if (!sarcophagus.isRewrapped) {\n diggingFeeAmount += cursedArchaeologist.curseFee;\n }\n\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\n }\n}\n" + }, + "contracts/libraries/LibErrors.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\n/**\n * @title A collection of Errors\n * @notice This library defines all of the Errors that the Sarcophagus system\n * uses.\n */\nlibrary LibErrors {\n error ArchaeologistNotOnSarcophagus(address archaeologist);\n\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\n\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\n\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\n\n error SarcophagusDoesNotExist(bytes32 sarcoId);\n\n error SarcophagusInactive(bytes32 sarcoId);\n\n error SarcophagusCompromised(bytes32 sarcoId);\n\n error SenderNotEmbalmer(address sender, address embalmer);\n\n error InvalidSignature(\n // address recovered from signature via ecrecover\n address recoveredAddress,\n // address we expected to have signed the data\n address expectedAddress\n );\n}\n" + }, + "contracts/libraries/LibPrivateKeys.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.18;\n\n/**\n * @title Private key verification\n * @notice Implements a private key -> public key checking function\n * @dev modified from https://github.com/1Address/ecsol, removes extra code\n * which isn't necessary for our Sarcophagus implementation\n */\nlibrary LibPrivateKeys {\n /**\n * @notice Given a private key and a public key, determines if that public\n * key was derived from the private key\n * @dev based on https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9\n * @param privKey an secp256k1 private key\n * @param pubKey an uncompressed 65 byte secp256k1 public key\n * @return bool indicating whether the public key is derived from the\n * private key\n */\n function isPublicKeyOfPrivateKey(\n bytes32 privKey,\n bytes storage pubKey\n ) internal view returns (bool) {\n // removes the 0x04 prefix from an uncompressed public key\n uint256 pubKeyLength = pubKey.length;\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\n for (uint256 i = 1; i < pubKeyLength; ) {\n truncatedPublicKey[i - 1] = pubKey[i];\n unchecked {\n ++i;\n }\n }\n\n // generator point coordinates and order of secp256k1\n uint256 gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;\n uint256 gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;\n uint256 m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;\n\n address signer = ecrecover(\n 0,\n gy % 2 != 0 ? 28 : 27,\n bytes32(gx),\n bytes32(mulmod(uint256(privKey), gx, m))\n );\n\n address xyAddress = address(\n uint160(\n uint256(keccak256(truncatedPublicKey)) &\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n )\n );\n return xyAddress == signer;\n }\n}\n" + }, + "contracts/libraries/LibTypes.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\n/**\n * @title Types shared across facets for the Sarcophagus diamond\n */\nlibrary LibTypes {\n struct Sarcophagus {\n // Also used for existence checks -- does not exist if 0\n uint256 resurrectionTime;\n uint256 previousRewrapTime;\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\n bool isCompromised;\n bool isCleaned;\n bool isRewrapped;\n uint8 threshold;\n string name;\n uint256 maximumRewrapInterval;\n uint256 maximumResurrectionTime;\n string arweaveTxId;\n address embalmerAddress;\n address recipientAddress;\n address[] cursedArchaeologistAddresses;\n mapping(address => CursedArchaeologist) cursedArchaeologists;\n uint256 cursedBondPercentage;\n }\n\n struct CursedArchaeologist {\n uint256 diggingFeePerSecond;\n // Also used for publish checks -- has not published if 0\n bytes32 privateKey;\n // Also used for curse checks -- is not bonded if length is 0\n bytes publicKey;\n bool isAccused;\n uint256 curseFee;\n }\n\n struct Signature {\n uint8 v;\n bytes32 r;\n bytes32 s;\n }\n\n struct ArchaeologistProfile {\n // Also used for existence checks -- does not exist if 0\n uint256 maximumRewrapInterval;\n uint256 maximumResurrectionTime;\n string peerId;\n uint256 minimumDiggingFeePerSecond;\n uint256 freeBond;\n uint256 cursedBond;\n uint256 curseFee;\n }\n}\n" + }, + "contracts/libraries/LibUtils.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"../storage/LibAppStorage.sol\";\nimport \"../libraries/LibTypes.sol\";\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\nimport \"../facets/ThirdPartyFacet.sol\";\nimport \"./LibTypes.sol\";\nimport \"../facets/EmbalmerFacet.sol\";\n\n/**\n * @title Utility functions used within the Sarcophagus system\n * @notice This library implements various functions that are used throughout\n * Sarcophagus, mainly to DRY up the codebase\n * @dev these functions are all stateless, public, pure/view\n */\nlibrary LibUtils {\n /**\n * @notice The archaeologist needs to sign off on two pieces of data\n * to guarantee their unrwap will be successful\n *\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\n * @param curseParams parameters of curse signed by archaeologist\n */\n function verifyArchaeologistSignature(\n uint256 agreedMaximumRewrapInterval,\n uint256 maximumResurrectionTime,\n uint256 timestamp,\n EmbalmerFacet.CurseParams calldata curseParams\n ) internal pure {\n // Hash the hash of the data payload\n bytes32 messageHash = keccak256(\n abi.encodePacked(\n \"\\x19Ethereum Signed Message:\\n32\",\n keccak256(\n abi.encode(\n curseParams.publicKey,\n agreedMaximumRewrapInterval,\n maximumResurrectionTime,\n curseParams.diggingFeePerSecond,\n timestamp,\n curseParams.curseFee\n )\n )\n )\n );\n\n // Generate the address from the signature.\n // ecrecover should always return a valid address.\n address recoveredAddress = ecrecover(\n messageHash,\n curseParams.v,\n curseParams.r,\n curseParams.s\n );\n\n if (recoveredAddress != curseParams.archAddress) {\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\n }\n }\n\n /// @notice Verifies that a signature and public key were created from the same private key\n /// @param sarcoId the sarcoId that was signed\n /// @param paymentAddress the payment address that was signed\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\n /// @param signature signature on the sarco id and payment address\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\n function verifyAccusalSignature(\n bytes32 sarcoId,\n address paymentAddress,\n bytes calldata publicKey,\n LibTypes.Signature calldata signature\n ) internal pure returns (bool) {\n // removes the 0x04 prefix from an uncompressed public key\n uint256 pubKeyLength = publicKey.length;\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\n for (uint256 i = 1; i < pubKeyLength; ) {\n truncatedPublicKey[i - 1] = publicKey[i];\n unchecked {\n ++i;\n }\n }\n bytes32 messageHash = keccak256(\n abi.encodePacked(\n \"\\x19Ethereum Signed Message:\\n32\",\n keccak256(abi.encode(sarcoId, paymentAddress))\n )\n );\n // Use ecrecover to get the address that signed the message\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\n\n address publicKeyAddress = address(\n uint160(\n uint256(keccak256(truncatedPublicKey)) &\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n )\n );\n\n return signingAddress == publicKeyAddress;\n }\n\n /// @notice Checks if an archaeologist profile exists and\n /// reverts if so\n ///\n /// @param archaeologist the archaeologist address to check existence of\n function revertIfArchProfileExists(address archaeologist) internal view {\n AppStorage storage s = LibAppStorage.getAppStorage();\n\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\n }\n }\n\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\n ///\n /// @param archaeologist the archaeologist address to check lack of existence of\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\n AppStorage storage s = LibAppStorage.getAppStorage();\n\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\n }\n }\n\n /// @notice Calculates the protocol fees to be taken from the embalmer.\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\n /// @return The protocol fees amount\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\n AppStorage storage s = LibAppStorage.getAppStorage();\n\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\n }\n}\n" + }, + "contracts/proxy/LibUtilsProxy.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\nimport {LibTypes} from \"../libraries/LibTypes.sol\";\n\ncontract LibUtilsTest {\n function verifySignature(\n bytes32 sarcoId,\n address paymentAddress,\n bytes calldata publicKey,\n LibTypes.Signature calldata signature\n ) external pure returns (bool) {\n return LibUtils.verifyAccusalSignature(sarcoId, paymentAddress, publicKey, signature);\n }\n}\n" + }, + "contracts/storage/AppStorageInit.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"./LibAppStorage.sol\";\n\ncontract AppStorageInit {\n /// @notice Initializes the app with default state values\n /// @dev Add any AppStorage struct properties here to initialize values\n function init(\n IERC20 sarcoToken,\n address admin,\n uint256 protocolFeeBasePercentage,\n uint256 cursedBondPercentage,\n uint256 gracePeriod,\n uint256 embalmerClaimWindow,\n uint256 expirationThreshold\n ) external {\n AppStorage storage s = LibAppStorage.getAppStorage();\n\n s.sarcoToken = sarcoToken;\n s.admin = admin;\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\n s.cursedBondPercentage = cursedBondPercentage;\n s.gracePeriod = gracePeriod;\n s.embalmerClaimWindow = embalmerClaimWindow;\n s.expirationThreshold = expirationThreshold;\n }\n}\n" + }, + "contracts/storage/LibAppStorage.sol": { + "content": "// SPDX-License-Identifier: Unlicense\npragma solidity 0.8.18;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"../libraries/LibTypes.sol\";\n\n/**\n * Global diamond storage struct to be shared across facets\n */\nstruct AppStorage {\n // SARCO token contract\n IERC20 sarcoToken;\n // The Admin address allowed to call Admin Facet functions\n address admin;\n // total protocol fees available to be withdrawn by the admin\n uint256 totalProtocolFees;\n /**\n * Protocol level admin configurations\n */\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\n uint256 protocolFeeBasePercentage;\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\n uint256 cursedBondPercentage;\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\n uint256 gracePeriod;\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\n uint256 expirationThreshold;\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\n uint256 embalmerClaimWindow;\n // registered archaeologist addresses\n address[] archaeologistProfileAddresses;\n // public key => archaeologist address\n mapping(bytes => address) publicKeyToArchaeologistAddress;\n // sarcophagus id => sarcophagus object\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\n // archaeologist address => profile\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\n // current balance of rewards available for the archaeologist to withdraw\n mapping(address => uint256) archaeologistRewards;\n}\n\nlibrary LibAppStorage {\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\"sarcophagus.storage.1\");\n\n function getAppStorage() internal pure returns (AppStorage storage s) {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n s.slot := position\n }\n }\n}\n" + }, + "hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\ninterface IDiamondCut {\n enum FacetCutAction {Add, Replace, Remove}\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" + }, + "hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\nimport { IDiamondCut } from \"../interfaces/IDiamondCut.sol\";\n\nlibrary LibDiamond {\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\"diamond.standard.diamond.storage\");\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n require(msg.sender == diamondStorage().contractOwner, \"LibDiamond: Must be contract owner\");\n }\n\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n require(_functionSelectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n DiamondStorage storage ds = diamondStorage(); \n require(_facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress); \n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(ds, selector, selectorPosition, _facetAddress);\n selectorPosition++;\n }\n }\n\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n require(_functionSelectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n DiamondStorage storage ds = diamondStorage();\n require(_facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != _facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n selectorPosition++;\n }\n }\n\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n require(_functionSelectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n require(_facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n }\n }\n\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\n enforceHasContractCode(_facetAddress, \"LibDiamondCut: New facet has no code\");\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\n ds.facetAddresses.push(_facetAddress);\n } \n\n\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \n require(_facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n // an immutable function is a function defined directly in a diamond\n require(_facetAddress != address(this), \"LibDiamondCut: Can't remove immutable function\");\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\n if (_init == address(0)) {\n require(_calldata.length == 0, \"LibDiamondCut: _init is address(0) but_calldata is not empty\");\n } else {\n require(_calldata.length > 0, \"LibDiamondCut: _calldata is empty but _init is not address(0)\");\n if (_init != address(this)) {\n enforceHasContractCode(_init, \"LibDiamondCut: _init address has no code\");\n }\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert(\"LibDiamondCut: _init function reverted\");\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize > 0, _errorMessage);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": false, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file diff --git a/deployments/baseGoerli/.chainId b/deployments/baseGoerli/.chainId deleted file mode 100644 index 9b24bf0..0000000 --- a/deployments/baseGoerli/.chainId +++ /dev/null @@ -1 +0,0 @@ -84531 \ No newline at end of file diff --git a/deployments/baseGoerli/AdminFacet.json b/deployments/baseGoerli/AdminFacet.json deleted file mode 100644 index 5498dfa..0000000 --- a/deployments/baseGoerli/AdminFacet.json +++ /dev/null @@ -1,326 +0,0 @@ -{ - "address": "0xdd76D7b1720b8Ee74218a28Eb6D54A52502d637b", - "abi": [ - { - "inputs": [], - "name": "CallerIsNotAdmin", - "type": "error" - }, - { - "inputs": [], - "name": "CannotSetZeroValue", - "type": "error" - }, - { - "inputs": [], - "name": "ZeroAddress", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousAdmin", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "AdminTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "cursedBondPercentage", - "type": "uint256" - } - ], - "name": "SetCursedBondPercentage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "embalmerClaimWindow", - "type": "uint256" - } - ], - "name": "SetEmbalmerClaimWindow", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "expirationThreshold", - "type": "uint256" - } - ], - "name": "SetExpirationThreshold", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "gracePeriod", - "type": "uint256" - } - ], - "name": "SetGracePeriod", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "protocolFeeBasePercentage", - "type": "uint256" - } - ], - "name": "SetProtocolFeeBasePercentage", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "uint256", - "name": "totalProtocolFees", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address", - "name": "withdrawalAddress", - "type": "address" - } - ], - "name": "WithdrawProtocolFees", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "cursedBondPercentage", - "type": "uint256" - } - ], - "name": "setCursedBondPercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "embalmerClaimWindow", - "type": "uint256" - } - ], - "name": "setEmbalmerClaimWindow", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "expirationThreshold", - "type": "uint256" - } - ], - "name": "setExpirationThreshold", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "gracePeriod", - "type": "uint256" - } - ], - "name": "setGracePeriod", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "protocolFeeBasePercentage", - "type": "uint256" - } - ], - "name": "setProtocolFeeBasePercentage", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newAdmin", - "type": "address" - } - ], - "name": "transferAdmin", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "withdrawalAddress", - "type": "address" - } - ], - "name": "withdrawProtocolFees", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xeebc5a176227498c78b1903b8a104ae95d7f1048ece7ac13b050d5e64ea59a15", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 2, - "gasUsed": "687807", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x1f2fc2c8aa7710d66770822770741a2ff3fdd15193a6463b57ba2fe5d4a97533", - "transactionHash": "0xeebc5a176227498c78b1903b8a104ae95d7f1048ece7ac13b050d5e64ea59a15", - "logs": [], - "blockNumber": 9669978, - "cumulativeGasUsed": "4788716", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "b7fcd450a9977c08df561a1e7df764e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[],\"name\":\"CallerIsNotAdmin\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSetZeroValue\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousAdmin\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"AdminTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"}],\"name\":\"SetCursedBondPercentage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindow\",\"type\":\"uint256\"}],\"name\":\"SetEmbalmerClaimWindow\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"expirationThreshold\",\"type\":\"uint256\"}],\"name\":\"SetExpirationThreshold\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"gracePeriod\",\"type\":\"uint256\"}],\"name\":\"SetGracePeriod\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"protocolFeeBasePercentage\",\"type\":\"uint256\"}],\"name\":\"SetProtocolFeeBasePercentage\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalProtocolFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"withdrawalAddress\",\"type\":\"address\"}],\"name\":\"WithdrawProtocolFees\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"cursedBondPercentage\",\"type\":\"uint256\"}],\"name\":\"setCursedBondPercentage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindow\",\"type\":\"uint256\"}],\"name\":\"setEmbalmerClaimWindow\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"expirationThreshold\",\"type\":\"uint256\"}],\"name\":\"setExpirationThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"gracePeriod\",\"type\":\"uint256\"}],\"name\":\"setGracePeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"protocolFeeBasePercentage\",\"type\":\"uint256\"}],\"name\":\"setProtocolFeeBasePercentage\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newAdmin\",\"type\":\"address\"}],\"name\":\"transferAdmin\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"withdrawalAddress\",\"type\":\"address\"}],\"name\":\"withdrawProtocolFees\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"setCursedBondPercentage(uint256)\":{\"params\":{\"cursedBondPercentage\":\"ratio to set.\"}},\"setEmbalmerClaimWindow(uint256)\":{\"params\":{\"embalmerClaimWindow\":\"to set\"}},\"setExpirationThreshold(uint256)\":{\"params\":{\"expirationThreshold\":\"to set\"}},\"setGracePeriod(uint256)\":{\"params\":{\"gracePeriod\":\"to set\"}},\"setProtocolFeeBasePercentage(uint256)\":{\"params\":{\"protocolFeeBasePercentage\":\"percentage to set\"}},\"transferAdmin(address)\":{\"params\":{\"newAdmin\":\"to set\"}},\"withdrawProtocolFees(address)\":{\"params\":{\"withdrawalAddress\":\"- the address to withdraw funds to\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"CallerIsNotAdmin()\":[{\"notice\":\"Caller must be the admin address\"}],\"CannotSetZeroValue()\":[{\"notice\":\"Admin has attempted to set a zero value\"}],\"ZeroAddress()\":[{\"notice\":\"Provided address cannot be zero address\"}]},\"kind\":\"user\",\"methods\":{\"setCursedBondPercentage(uint256)\":{\"notice\":\"Sets the digging fee / cursed bond ratioThe denominator is 10000 used to calculate how much bond archaeologists must lock per curse.\"},\"setEmbalmerClaimWindow(uint256)\":{\"notice\":\"Updates the embalmerClaimWindowDenominated in seconds\"},\"setExpirationThreshold(uint256)\":{\"notice\":\"Updates the expirationThreshold used during sarcophagus creationDenominated in seconds\"},\"setGracePeriod(uint256)\":{\"notice\":\"Updates the resurrection grace periodDenominated in seconds\"},\"setProtocolFeeBasePercentage(uint256)\":{\"notice\":\"Sets the protocol fee base percentage, used to calculate protocol feesThe denominator is 10000\"},\"transferAdmin(address)\":{\"notice\":\"Transfers admin address to newAdmin.\"},\"withdrawProtocolFees(address)\":{\"notice\":\"Withdraws the total protocol fee amount from the contract to the specified address\"}},\"notice\":\"Caller of any function in this facet must be the admin address\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/AdminFacet.sol\":\"AdminFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"contracts/facets/AdminFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\n\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\n\\r\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\r\\n\\r\\n/// @notice Caller of any function in this facet must be the admin address\\r\\ncontract AdminFacet {\\r\\n event SetProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage);\\r\\n event SetCursedBondPercentage(uint256 cursedBondPercentage);\\r\\n event WithdrawProtocolFees(uint256 totalProtocolFees, address withdrawalAddress);\\r\\n event SetGracePeriod(uint256 gracePeriod);\\r\\n event SetEmbalmerClaimWindow(uint256 embalmerClaimWindow);\\r\\n event SetExpirationThreshold(uint256 expirationThreshold);\\r\\n event AdminTransferred(address indexed previousAdmin, address indexed newAdmin);\\r\\n\\r\\n /// @notice Admin has attempted to set a zero value\\r\\n error CannotSetZeroValue();\\r\\n\\r\\n /// @notice Caller must be the admin address\\r\\n error CallerIsNotAdmin();\\r\\n\\r\\n /// @notice Provided address cannot be zero address\\r\\n error ZeroAddress();\\r\\n\\r\\n modifier onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n if (msg.sender != s.admin) {\\r\\n revert CallerIsNotAdmin();\\r\\n }\\r\\n _;\\r\\n }\\r\\n\\r\\n /// @notice Withdraws the total protocol fee amount from the contract to the specified address\\r\\n /// @param withdrawalAddress - the address to withdraw funds to\\r\\n function withdrawProtocolFees(address withdrawalAddress) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n // Get the total protocol fees from storage\\r\\n uint256 totalProtocolFees = s.totalProtocolFees;\\r\\n // Set the total protocol fees to 0 before the transfer to avoid reentrancy\\r\\n s.totalProtocolFees = 0;\\r\\n // Transfer the protocol fee amount to the sender after setting state\\r\\n s.sarcoToken.transfer(withdrawalAddress, totalProtocolFees);\\r\\n emit WithdrawProtocolFees(totalProtocolFees, withdrawalAddress);\\r\\n }\\r\\n\\r\\n /// @notice Sets the protocol fee base percentage, used to calculate protocol fees\\r\\n /// @notice The denominator is 10000\\r\\n /// @param protocolFeeBasePercentage percentage to set\\r\\n function setProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\\r\\n emit SetProtocolFeeBasePercentage(protocolFeeBasePercentage);\\r\\n }\\r\\n\\r\\n /// @notice Sets the digging fee / cursed bond ratio\\r\\n /// @notice The denominator is 10000\\r\\n /// used to calculate how much bond archaeologists must lock per curse.\\r\\n /// @param cursedBondPercentage ratio to set.\\r\\n function setCursedBondPercentage(uint256 cursedBondPercentage) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n if (cursedBondPercentage == 0) {\\r\\n revert CannotSetZeroValue();\\r\\n }\\r\\n s.cursedBondPercentage = cursedBondPercentage;\\r\\n emit SetCursedBondPercentage(cursedBondPercentage);\\r\\n }\\r\\n\\r\\n /// @notice Updates the resurrection grace period\\r\\n /// @notice Denominated in seconds\\r\\n /// @param gracePeriod to set\\r\\n function setGracePeriod(uint256 gracePeriod) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n s.gracePeriod = gracePeriod;\\r\\n emit SetGracePeriod(gracePeriod);\\r\\n }\\r\\n\\r\\n /// @notice Updates the embalmerClaimWindow\\r\\n /// @notice Denominated in seconds\\r\\n /// @param embalmerClaimWindow to set\\r\\n function setEmbalmerClaimWindow(uint256 embalmerClaimWindow) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n s.embalmerClaimWindow = embalmerClaimWindow;\\r\\n emit SetEmbalmerClaimWindow(embalmerClaimWindow);\\r\\n }\\r\\n\\r\\n /// @notice Updates the expirationThreshold used during sarcophagus creation\\r\\n /// @notice Denominated in seconds\\r\\n /// @param expirationThreshold to set\\r\\n function setExpirationThreshold(uint256 expirationThreshold) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n s.expirationThreshold = expirationThreshold;\\r\\n emit SetExpirationThreshold(expirationThreshold);\\r\\n }\\r\\n\\r\\n /// @notice Transfers admin address to newAdmin.\\r\\n /// @param newAdmin to set\\r\\n function transferAdmin(address newAdmin) external onlyAdmin {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n if (newAdmin == address(0)) {\\r\\n revert ZeroAddress();\\r\\n }\\r\\n s.admin = newAdmin;\\r\\n emit AdminTransferred(msg.sender, newAdmin);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x73025f904f1e1ec022d4660b4420cc12a4712cac0f2d1dde85e424004b9f0a57\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Types shared across facets for the Sarcophagus diamond\\r\\n */\\r\\nlibrary LibTypes {\\r\\n struct Sarcophagus {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n bool isRewrapped;\\r\\n uint8 threshold;\\r\\n string name;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] cursedArchaeologistAddresses;\\r\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\r\\n uint256 cursedBondPercentage;\\r\\n }\\r\\n\\r\\n struct CursedArchaeologist {\\r\\n uint256 diggingFeePerSecond;\\r\\n // Also used for publish checks -- has not published if 0\\r\\n bytes32 privateKey;\\r\\n // Also used for curse checks -- is not bonded if length is 0\\r\\n bytes publicKey;\\r\\n bool isAccused;\\r\\n uint256 curseFee;\\r\\n }\\r\\n\\r\\n struct Signature {\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n struct ArchaeologistProfile {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string peerId;\\r\\n uint256 minimumDiggingFeePerSecond;\\r\\n uint256 freeBond;\\r\\n uint256 cursedBond;\\r\\n uint256 curseFee;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x096d9660852c5179b16d71abe3a818282db9e980fdc431efa77bd92577d60fb8\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\n/**\\r\\n * Global diamond storage struct to be shared across facets\\r\\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\\r\\n */\\r\\nstruct AppStorage {\\r\\n // SARCO token contract\\r\\n IERC20 sarcoToken;\\r\\n // The Admin address allowed to call Admin Facet functions\\r\\n address admin;\\r\\n // total protocol fees available to be withdrawn by the admin\\r\\n uint256 totalProtocolFees;\\r\\n /**\\r\\n * Protocol level admin configurations\\r\\n */\\r\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\r\\n uint256 protocolFeeBasePercentage;\\r\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\r\\n uint256 cursedBondPercentage;\\r\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\r\\n uint256 gracePeriod;\\r\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\r\\n uint256 expirationThreshold;\\r\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\r\\n uint256 embalmerClaimWindow;\\r\\n // registered archaeologist addresses\\r\\n address[] archaeologistProfileAddresses;\\r\\n // public key => archaeologist address\\r\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\r\\n // sarcophagus id => sarcophagus object\\r\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\r\\n // archaeologist address => profile\\r\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\r\\n // current balance of rewards available for the archaeologist to withdraw\\r\\n mapping(address => uint256) archaeologistRewards;\\r\\n}\\r\\n\\r\\nlibrary LibAppStorage {\\r\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\r\\n\\r\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n assembly {\\r\\n s.slot := position\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x66f7100a037fcc417379e68914a8831d867f3701c39419f8f04a3af27008438c\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50610b83806100206000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c806375829def1161005b57806375829def146100d65780638a5b5690146100f2578063a828c4791461010e578063f2f659601461012a5761007d565b8063274f255e146100825780632d80caa51461009e5780636430ae6a146100ba575b600080fd5b61009c600480360381019061009791906109a5565b610146565b005b6100b860048036038101906100b39190610a30565b61022c565b005b6100d460048036038101906100cf91906109a5565b6103c2565b005b6100f060048036038101906100eb9190610a30565b6104e2565b005b61010c600480360381019061010791906109a5565b61068b565b005b610128600480360381019061012391906109a5565b610771565b005b610144600480360381019061013f91906109a5565b610857565b005b600061015061093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101db576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006101e561093d565b90508281600701819055507f3d58bff47ca074037a5dcd57740255670d45843115cca9c9bc442eb6d3f0ad788360405161021f9190610a6c565b60405180910390a1505050565b600061023661093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102c1576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006102cb61093d565b9050600081600201549050600082600201819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836040518363ffffffff1660e01b815260040161033f929190610a96565b6020604051808303816000875af115801561035e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103829190610af7565b507f7baf2b6a1777e2a34a2dcddad43c098eb5ab5b5c7a1f3c8ec4872863265244f481856040516103b4929190610b24565b60405180910390a150505050565b60006103cc61093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610457576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046161093d565b90506000830361049d576040517f4a8fadb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8281600401819055507f4aeca9f26d25b33ee1b2c061ab4a849de97bfb592e7dfb276c9ded12d0ad56a2836040516104d59190610a6c565b60405180910390a1505050565b60006104ec61093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610577576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061058161093d565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105e9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec660405160405180910390a3505050565b600061069561093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610720576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061072a61093d565b90508281600301819055507f4768bb3a79cb8de7ec3c4c950f9f76fbe4588407c214998efbf648001c858e9b836040516107649190610a6c565b60405180910390a1505050565b600061077b61093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610806576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061081061093d565b90508281600601819055507f047ca17cdae34ccbd8db62138d05e11962458ffd86009620909ba6ad606282ad8360405161084a9190610a6c565b60405180910390a1505050565b600061086161093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108ec576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108f661093d565b90508281600501819055507f848ba7852320e491d84ddc22f1f12fe48672aa22757fc4452703c9046d9982d7836040516109309190610a6c565b60405180910390a1505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b600080fd5b6000819050919050565b6109828161096f565b811461098d57600080fd5b50565b60008135905061099f81610979565b92915050565b6000602082840312156109bb576109ba61096a565b5b60006109c984828501610990565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006109fd826109d2565b9050919050565b610a0d816109f2565b8114610a1857600080fd5b50565b600081359050610a2a81610a04565b92915050565b600060208284031215610a4657610a4561096a565b5b6000610a5484828501610a1b565b91505092915050565b610a668161096f565b82525050565b6000602082019050610a816000830184610a5d565b92915050565b610a90816109f2565b82525050565b6000604082019050610aab6000830185610a87565b610ab86020830184610a5d565b9392505050565b60008115159050919050565b610ad481610abf565b8114610adf57600080fd5b50565b600081519050610af181610acb565b92915050565b600060208284031215610b0d57610b0c61096a565b5b6000610b1b84828501610ae2565b91505092915050565b6000604082019050610b396000830185610a5d565b610b466020830184610a87565b939250505056fea26469706673582212202b99df4126e7262fe4189b447cf266da561a651ce3160af63019994b2c9565ac64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b506004361061007d5760003560e01c806375829def1161005b57806375829def146100d65780638a5b5690146100f2578063a828c4791461010e578063f2f659601461012a5761007d565b8063274f255e146100825780632d80caa51461009e5780636430ae6a146100ba575b600080fd5b61009c600480360381019061009791906109a5565b610146565b005b6100b860048036038101906100b39190610a30565b61022c565b005b6100d460048036038101906100cf91906109a5565b6103c2565b005b6100f060048036038101906100eb9190610a30565b6104e2565b005b61010c600480360381019061010791906109a5565b61068b565b005b610128600480360381019061012391906109a5565b610771565b005b610144600480360381019061013f91906109a5565b610857565b005b600061015061093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146101db576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006101e561093d565b90508281600701819055507f3d58bff47ca074037a5dcd57740255670d45843115cca9c9bc442eb6d3f0ad788360405161021f9190610a6c565b60405180910390a1505050565b600061023661093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146102c1576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006102cb61093d565b9050600081600201549050600082600201819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb85836040518363ffffffff1660e01b815260040161033f929190610a96565b6020604051808303816000875af115801561035e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103829190610af7565b507f7baf2b6a1777e2a34a2dcddad43c098eb5ab5b5c7a1f3c8ec4872863265244f481856040516103b4929190610b24565b60405180910390a150505050565b60006103cc61093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610457576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061046161093d565b90506000830361049d576040517f4a8fadb900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b8281600401819055507f4aeca9f26d25b33ee1b2c061ab4a849de97bfb592e7dfb276c9ded12d0ad56a2836040516104d59190610a6c565b60405180910390a1505050565b60006104ec61093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610577576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061058161093d565b9050600073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105e9576040517fd92e233d00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b828160010160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167ff8ccb027dfcd135e000e9d45e6cc2d662578a8825d4c45b5e32e0adf67e79ec660405160405180910390a3505050565b600061069561093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610720576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061072a61093d565b90508281600301819055507f4768bb3a79cb8de7ec3c4c950f9f76fbe4588407c214998efbf648001c858e9b836040516107649190610a6c565b60405180910390a1505050565b600061077b61093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610806576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600061081061093d565b90508281600601819055507f047ca17cdae34ccbd8db62138d05e11962458ffd86009620909ba6ad606282ad8360405161084a9190610a6c565b60405180910390a1505050565b600061086161093d565b90508060010160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff16146108ec576040517f8dfa73db00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006108f661093d565b90508281600501819055507f848ba7852320e491d84ddc22f1f12fe48672aa22757fc4452703c9046d9982d7836040516109309190610a6c565b60405180910390a1505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b600080fd5b6000819050919050565b6109828161096f565b811461098d57600080fd5b50565b60008135905061099f81610979565b92915050565b6000602082840312156109bb576109ba61096a565b5b60006109c984828501610990565b91505092915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006109fd826109d2565b9050919050565b610a0d816109f2565b8114610a1857600080fd5b50565b600081359050610a2a81610a04565b92915050565b600060208284031215610a4657610a4561096a565b5b6000610a5484828501610a1b565b91505092915050565b610a668161096f565b82525050565b6000602082019050610a816000830184610a5d565b92915050565b610a90816109f2565b82525050565b6000604082019050610aab6000830185610a87565b610ab86020830184610a5d565b9392505050565b60008115159050919050565b610ad481610abf565b8114610adf57600080fd5b50565b600081519050610af181610acb565b92915050565b600060208284031215610b0d57610b0c61096a565b5b6000610b1b84828501610ae2565b91505092915050565b6000604082019050610b396000830185610a5d565b610b466020830184610a87565b939250505056fea26469706673582212202b99df4126e7262fe4189b447cf266da561a651ce3160af63019994b2c9565ac64736f6c63430008120033", - "devdoc": { - "kind": "dev", - "methods": { - "setCursedBondPercentage(uint256)": { - "params": { - "cursedBondPercentage": "ratio to set." - } - }, - "setEmbalmerClaimWindow(uint256)": { - "params": { - "embalmerClaimWindow": "to set" - } - }, - "setExpirationThreshold(uint256)": { - "params": { - "expirationThreshold": "to set" - } - }, - "setGracePeriod(uint256)": { - "params": { - "gracePeriod": "to set" - } - }, - "setProtocolFeeBasePercentage(uint256)": { - "params": { - "protocolFeeBasePercentage": "percentage to set" - } - }, - "transferAdmin(address)": { - "params": { - "newAdmin": "to set" - } - }, - "withdrawProtocolFees(address)": { - "params": { - "withdrawalAddress": "- the address to withdraw funds to" - } - } - }, - "version": 1 - }, - "userdoc": { - "errors": { - "CallerIsNotAdmin()": [ - { - "notice": "Caller must be the admin address" - } - ], - "CannotSetZeroValue()": [ - { - "notice": "Admin has attempted to set a zero value" - } - ], - "ZeroAddress()": [ - { - "notice": "Provided address cannot be zero address" - } - ] - }, - "kind": "user", - "methods": { - "setCursedBondPercentage(uint256)": { - "notice": "Sets the digging fee / cursed bond ratioThe denominator is 10000 used to calculate how much bond archaeologists must lock per curse." - }, - "setEmbalmerClaimWindow(uint256)": { - "notice": "Updates the embalmerClaimWindowDenominated in seconds" - }, - "setExpirationThreshold(uint256)": { - "notice": "Updates the expirationThreshold used during sarcophagus creationDenominated in seconds" - }, - "setGracePeriod(uint256)": { - "notice": "Updates the resurrection grace periodDenominated in seconds" - }, - "setProtocolFeeBasePercentage(uint256)": { - "notice": "Sets the protocol fee base percentage, used to calculate protocol feesThe denominator is 10000" - }, - "transferAdmin(address)": { - "notice": "Transfers admin address to newAdmin." - }, - "withdrawProtocolFees(address)": { - "notice": "Withdraws the total protocol fee amount from the contract to the specified address" - } - }, - "notice": "Caller of any function in this facet must be the admin address", - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/deployments/baseGoerli/ArchaeologistFacet.json b/deployments/baseGoerli/ArchaeologistFacet.json deleted file mode 100644 index c3e16dd..0000000 --- a/deployments/baseGoerli/ArchaeologistFacet.json +++ /dev/null @@ -1,635 +0,0 @@ -{ - "address": "0xa5D2340a71B0b10b82CB879B9F9a31d4C4595102", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "archaeologistAddress", - "type": "address" - } - ], - "name": "ArchaeologistAlreadyPublishedPrivateKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "archaeologistAddress", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "ArchaeologistHasBeenAccused", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "archaeologist", - "type": "address" - } - ], - "name": "ArchaeologistNotOnSarcophagus", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "address", - "name": "archaeologist", - "type": "address" - } - ], - "name": "ArchaeologistProfileExistsShouldBe", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "archaeologistAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - }, - { - "internalType": "bytes32", - "name": "privateKey", - "type": "bytes32" - } - ], - "name": "ArchaeologistPublishedIncorrectPrivateKey", - "type": "error" - }, - { - "inputs": [], - "name": "CannotSetZeroProfileValue", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusCompromised", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusInactive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - } - ], - "name": "TooEarlyForPublish", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "publishDeadline", - "type": "uint256" - } - ], - "name": "TooLateForPublish", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "archaeologist", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "depositedBond", - "type": "uint256" - } - ], - "name": "DepositFreeBond", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "bytes32", - "name": "privateKey", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "archaeologist", - "type": "address" - } - ], - "name": "PublishPrivateKey", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "archaeologist", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "peerId", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "minimumDiggingFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maximumRewrapInterval", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "freeBond", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maximumResurrectionTime", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "curseFee", - "type": "uint256" - } - ], - "name": "RegisterArchaeologist", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "archaeologist", - "type": "address" - }, - { - "indexed": false, - "internalType": "string", - "name": "peerId", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "minimumDiggingFee", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maximumRewrapInterval", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "freeBond", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "maximumResurrectionTime", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "curseFee", - "type": "uint256" - } - ], - "name": "UpdateArchaeologist", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "archaeologist", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "withdrawnBond", - "type": "uint256" - } - ], - "name": "WithdrawFreeBond", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "archaeologist", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "withdrawnReward", - "type": "uint256" - } - ], - "name": "WithdrawReward", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "depositFreeBond", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "privateKey", - "type": "bytes32" - } - ], - "name": "publishPrivateKey", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "peerId", - "type": "string" - }, - { - "internalType": "uint256", - "name": "minimumDiggingFeePerSecond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumRewrapInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "freeBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumResurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "curseFee", - "type": "uint256" - } - ], - "name": "registerArchaeologist", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "string", - "name": "peerId", - "type": "string" - }, - { - "internalType": "uint256", - "name": "minimumDiggingFeePerSecond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumRewrapInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "freeBond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumResurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "curseFee", - "type": "uint256" - } - ], - "name": "updateArchaeologist", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "amount", - "type": "uint256" - } - ], - "name": "withdrawFreeBond", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "withdrawReward", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xb68f698fd072f989201a9ab53e0b18e9a9d35c1bda13e76823244fa99ab02311", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "1887909", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x547f0deadb9a4239b2b2ea6db351dc1c53d7c4145b074afb586f91bb498c0a24", - "transactionHash": "0xb68f698fd072f989201a9ab53e0b18e9a9d35c1bda13e76823244fa99ab02311", - "logs": [], - "blockNumber": 9669969, - "cumulativeGasUsed": "1938338", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "b7fcd450a9977c08df561a1e7df764e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"}],\"name\":\"ArchaeologistAlreadyPublishedPrivateKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"ArchaeologistHasBeenAccused\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistNotOnSarcophagus\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistProfileExistsShouldBe\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"}],\"name\":\"ArchaeologistPublishedIncorrectPrivateKey\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"CannotSetZeroProfileValue\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusCompromised\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"TooEarlyForPublish\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"publishDeadline\",\"type\":\"uint256\"}],\"name\":\"TooLateForPublish\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"depositedBond\",\"type\":\"uint256\"}],\"name\":\"DepositFreeBond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"PublishPrivateKey\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minimumDiggingFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"RegisterArchaeologist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"minimumDiggingFee\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"UpdateArchaeologist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawnBond\",\"type\":\"uint256\"}],\"name\":\"WithdrawFreeBond\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"withdrawnReward\",\"type\":\"uint256\"}],\"name\":\"WithdrawReward\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"depositFreeBond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"privateKey\",\"type\":\"bytes32\"}],\"name\":\"publishPrivateKey\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"registerArchaeologist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"string\",\"name\":\"peerId\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"minimumDiggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"freeBond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"}],\"name\":\"updateArchaeologist\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"withdrawFreeBond\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdrawReward\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"ArchaeologistAlreadyPublishedPrivateKey(address)\":[{\"params\":{\"archaeologistAddress\":\"address of publishing archaeologist\"}}],\"ArchaeologistHasBeenAccused(address,bytes32)\":[{\"params\":{\"archaeologistAddress\":\"Address of accused archaeologist who is attempting to publish their private key\",\"sarcoId\":\"ID of sarcophagus archaeologist has attempted to publish a key on\"}}],\"ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)\":[{\"params\":{\"archaeologistAddress\":\"address of publishing archaeologist\",\"privateKey\":\"privateKey the archaeologist has attempted to publish\",\"publicKey\":\"publicKey stored for archaeologist on the sarcophagus\"}}],\"TooEarlyForPublish(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed publish attempt\",\"resurrectionTime\":\"Time after which the sarcophagus can be resurrected\"}}],\"TooLateForPublish(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed publish attempt\",\"publishDeadline\":\"Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)\"}}]},\"events\":{\"PublishPrivateKey(bytes32,bytes32,address)\":{\"params\":{\"privateKey\":\"private key that has been published\",\"sarcoId\":\"ID of sarcophagus archaeologist has published the private key on\"}}},\"kind\":\"dev\",\"methods\":{\"depositFreeBond(uint256)\":{\"params\":{\"amount\":\"The amount to deposit\"}},\"publishPrivateKey(bytes32,bytes32)\":{\"params\":{\"privateKey\":\"The private key the archaeologist is publishing\",\"sarcoId\":\"The identifier of the sarcophagus for which the archaeologist is responsible\"}},\"registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"curseFee\":\"The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\",\"freeBond\":\"How much bond the archaeologist wants to deposit during the register call (if any)\",\"maximumResurrectionTime\":\"The time beyond which the archaeologist is not willing to accept new curses or rewraps\",\"maximumRewrapInterval\":\"The longest interval of time from a rewrap time the arch will accept for a resurrection\",\"minimumDiggingFeePerSecond\":\"The archaeologist's minimum amount to earn per second for being cursed\",\"peerId\":\"The libp2p identifier for the archaeologist\"}},\"updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"params\":{\"curseFee\":\"The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\",\"freeBond\":\"How much bond the archaeologist wants to deposit during the update call (if any)\",\"maximumRewrapInterval\":\"The longest interval of time from a rewrap time the arch will accept for a resurrection\",\"minimumDiggingFeePerSecond\":\"The archaeologist's minimum amount to earn per second for being cursed\",\"peerId\":\"The libp2p identifier for the archaeologist\"}},\"withdrawFreeBond(uint256)\":{\"params\":{\"amount\":\"The amount to withdraw\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ArchaeologistAlreadyPublishedPrivateKey(address)\":[{\"notice\":\"Archaeologist has attempted to publish a key for a sarcophagus twice\"}],\"ArchaeologistHasBeenAccused(address,bytes32)\":[{\"notice\":\"An archaeologist that has already been successfully accused has attempted to publish their private key\"}],\"ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)\":[{\"notice\":\"Archaeologist has attempted to publish the incorrect private key for a sarcophagus\"}],\"CannotSetZeroProfileValue()\":[{\"notice\":\"Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval\"}],\"TooEarlyForPublish(uint256,uint256)\":[{\"notice\":\"Archaeologist has attempted to publish a key before the resurrection time\"}],\"TooLateForPublish(uint256,uint256)\":[{\"notice\":\"Archaeologist has attempted to publish a key after the end of the resurrection window\"}]},\"events\":{\"PublishPrivateKey(bytes32,bytes32,address)\":{\"notice\":\"Emitted when an archaeologist successfully publishes their private key for a sarcophagus\"}},\"kind\":\"user\",\"methods\":{\"depositFreeBond(uint256)\":{\"notice\":\"Deposits an archaeologist's free bond to the contract.\"},\"publishPrivateKey(bytes32,bytes32)\":{\"notice\":\"Publishes the private key for which the archaeologist is responsible during the sarcophagus resurrection window. Pays digging fees to the archaeologist and releases their locked bond. Cannot be called on a compromised or buried sarcophagus.\"},\"registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Registers the archaeologist profile\"},\"updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)\":{\"notice\":\"Updates the archaeologist profile\"},\"withdrawFreeBond(uint256)\":{\"notice\":\"Withdraws an archaeologist's free bond from the contract.\"},\"withdrawReward()\":{\"notice\":\"Withdraws all rewards from an archaeologist's reward pool\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ArchaeologistFacet.sol\":\"ArchaeologistFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/ArchaeologistFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\nimport {LibPrivateKeys} from \\\"../libraries/LibPrivateKeys.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\n\\r\\ncontract ArchaeologistFacet {\\r\\n /// @notice Emitted when an archaeologist successfully publishes their private key for a sarcophagus\\r\\n /// @param sarcoId ID of sarcophagus archaeologist has published the private key on\\r\\n /// @param privateKey private key that has been published\\r\\n event PublishPrivateKey(\\r\\n bytes32 indexed sarcoId,\\r\\n bytes32 privateKey,\\r\\n address indexed archaeologist\\r\\n );\\r\\n\\r\\n event DepositFreeBond(address indexed archaeologist, uint256 depositedBond);\\r\\n\\r\\n event RegisterArchaeologist(\\r\\n address indexed archaeologist,\\r\\n string peerId,\\r\\n uint256 minimumDiggingFee,\\r\\n uint256 maximumRewrapInterval,\\r\\n uint256 freeBond,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 curseFee\\r\\n );\\r\\n\\r\\n event UpdateArchaeologist(\\r\\n address indexed archaeologist,\\r\\n string peerId,\\r\\n uint256 minimumDiggingFee,\\r\\n uint256 maximumRewrapInterval,\\r\\n uint256 freeBond,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 curseFee\\r\\n );\\r\\n\\r\\n event WithdrawFreeBond(address indexed archaeologist, uint256 withdrawnBond);\\r\\n\\r\\n event WithdrawReward(address indexed archaeologist, uint256 withdrawnReward);\\r\\n\\r\\n /// @notice An archaeologist that has already been successfully accused has attempted to publish their private key\\r\\n /// @param archaeologistAddress Address of accused archaeologist who is attempting to publish their private key\\r\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a key on\\r\\n error ArchaeologistHasBeenAccused(address archaeologistAddress, bytes32 sarcoId);\\r\\n\\r\\n /// @notice Archaeologist has attempted to publish a key before the resurrection time\\r\\n /// @param currentTime Timestamp of the failed publish attempt\\r\\n /// @param resurrectionTime Time after which the sarcophagus can be resurrected\\r\\n error TooEarlyForPublish(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Archaeologist has attempted to publish a key after the end of the resurrection window\\r\\n /// @param currentTime Timestamp of the failed publish attempt\\r\\n /// @param publishDeadline Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)\\r\\n error TooLateForPublish(uint256 currentTime, uint256 publishDeadline);\\r\\n\\r\\n /// @notice Archaeologist has attempted to publish a key for a sarcophagus twice\\r\\n /// @param archaeologistAddress address of publishing archaeologist\\r\\n error ArchaeologistAlreadyPublishedPrivateKey(address archaeologistAddress);\\r\\n\\r\\n /// @notice Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval\\r\\n error CannotSetZeroProfileValue();\\r\\n\\r\\n /// @notice Archaeologist has attempted to publish the incorrect private key for a sarcophagus\\r\\n /// @param archaeologistAddress address of publishing archaeologist\\r\\n /// @param publicKey publicKey stored for archaeologist on the sarcophagus\\r\\n /// @param privateKey privateKey the archaeologist has attempted to publish\\r\\n error ArchaeologistPublishedIncorrectPrivateKey(\\r\\n address archaeologistAddress,\\r\\n bytes publicKey,\\r\\n bytes32 privateKey\\r\\n );\\r\\n\\r\\n /// @notice Registers the archaeologist profile\\r\\n /// @param peerId The libp2p identifier for the archaeologist\\r\\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\\r\\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\\r\\n /// for a resurrection\\r\\n /// @param freeBond How much bond the archaeologist wants to deposit during the register call (if any)\\r\\n /// @param maximumResurrectionTime The time beyond which the archaeologist is not willing to accept new curses or rewraps\\r\\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\\r\\n function registerArchaeologist(\\r\\n string memory peerId,\\r\\n uint256 minimumDiggingFeePerSecond,\\r\\n uint256 maximumRewrapInterval,\\r\\n uint256 freeBond,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 curseFee\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n // verify that the archaeologist does not already exist\\r\\n LibUtils.revertIfArchProfileExists(msg.sender);\\r\\n\\r\\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\\r\\n revert CannotSetZeroProfileValue();\\r\\n }\\r\\n\\r\\n // create a new archaeologist\\r\\n LibTypes.ArchaeologistProfile memory newArch = LibTypes.ArchaeologistProfile({\\r\\n peerId: peerId,\\r\\n minimumDiggingFeePerSecond: minimumDiggingFeePerSecond,\\r\\n maximumResurrectionTime: maximumResurrectionTime,\\r\\n maximumRewrapInterval: maximumRewrapInterval,\\r\\n freeBond: freeBond,\\r\\n cursedBond: 0,\\r\\n curseFee: curseFee\\r\\n });\\r\\n\\r\\n // transfer SARCO tokens from the archaeologist to this contract, to be\\r\\n // used as their free bond. can be 0.\\r\\n if (freeBond != 0) {\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\\r\\n }\\r\\n\\r\\n // save the new archaeologist into relevant data structures\\r\\n s.archaeologistProfiles[msg.sender] = newArch;\\r\\n s.archaeologistProfileAddresses.push(msg.sender);\\r\\n\\r\\n emit RegisterArchaeologist(\\r\\n msg.sender,\\r\\n newArch.peerId,\\r\\n newArch.minimumDiggingFeePerSecond,\\r\\n newArch.maximumRewrapInterval,\\r\\n newArch.freeBond,\\r\\n newArch.maximumResurrectionTime,\\r\\n newArch.curseFee\\r\\n );\\r\\n }\\r\\n\\r\\n /// @notice Updates the archaeologist profile\\r\\n /// @param peerId The libp2p identifier for the archaeologist\\r\\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\\r\\n /// @param freeBond How much bond the archaeologist wants to deposit during the update call (if any)\\r\\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\\r\\n /// for a resurrection\\r\\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\\r\\n function updateArchaeologist(\\r\\n string memory peerId,\\r\\n uint256 minimumDiggingFeePerSecond,\\r\\n uint256 maximumRewrapInterval,\\r\\n uint256 freeBond,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 curseFee\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n // verify that the archaeologist exists\\r\\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\\r\\n\\r\\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\\r\\n revert CannotSetZeroProfileValue();\\r\\n }\\r\\n\\r\\n LibTypes.ArchaeologistProfile storage existingArch = s.archaeologistProfiles[msg.sender];\\r\\n existingArch.peerId = peerId;\\r\\n existingArch.minimumDiggingFeePerSecond = minimumDiggingFeePerSecond;\\r\\n existingArch.maximumRewrapInterval = maximumRewrapInterval;\\r\\n existingArch.maximumResurrectionTime = maximumResurrectionTime;\\r\\n existingArch.curseFee = curseFee;\\r\\n\\r\\n // transfer SARCO tokens from the archaeologist to this contract, to be\\r\\n // used as their free bond. can be 0.\\r\\n if (freeBond != 0) {\\r\\n s.archaeologistProfiles[msg.sender].freeBond += freeBond;\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\\r\\n }\\r\\n\\r\\n emit UpdateArchaeologist(\\r\\n msg.sender,\\r\\n existingArch.peerId,\\r\\n existingArch.minimumDiggingFeePerSecond,\\r\\n existingArch.maximumRewrapInterval,\\r\\n freeBond,\\r\\n existingArch.maximumResurrectionTime,\\r\\n existingArch.curseFee\\r\\n );\\r\\n }\\r\\n\\r\\n /// @notice Deposits an archaeologist's free bond to the contract.\\r\\n /// @param amount The amount to deposit\\r\\n function depositFreeBond(uint256 amount) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\\r\\n\\r\\n // Increase the archaeologist's free bond in app storage\\r\\n s.archaeologistProfiles[msg.sender].freeBond += amount;\\r\\n\\r\\n // Transfer the amount of sarcoToken from the archaeologist to the contract\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), amount);\\r\\n // Emit an event\\r\\n emit DepositFreeBond(msg.sender, amount);\\r\\n }\\r\\n\\r\\n /// @notice Withdraws an archaeologist's free bond from the contract.\\r\\n /// @param amount The amount to withdraw\\r\\n function withdrawFreeBond(uint256 amount) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\\r\\n // Decrease the archaeologist's free bond amount.\\r\\n // Reverts if there is not enough free bond on the contract.\\r\\n s.archaeologistProfiles[msg.sender].freeBond -= amount;\\r\\n\\r\\n // Transfer the amount of sarcoToken to the archaeologist\\r\\n s.sarcoToken.transfer(msg.sender, amount);\\r\\n\\r\\n emit WithdrawFreeBond(msg.sender, amount);\\r\\n }\\r\\n\\r\\n /// @notice Withdraws all rewards from an archaeologist's reward pool\\r\\n function withdrawReward() external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n uint256 amountToWithdraw = s.archaeologistRewards[msg.sender];\\r\\n s.archaeologistRewards[msg.sender] = 0;\\r\\n\\r\\n // Transfer the amount of sarcoToken to the archaeologist\\r\\n s.sarcoToken.transfer(msg.sender, amountToWithdraw);\\r\\n\\r\\n emit WithdrawReward(msg.sender, amountToWithdraw);\\r\\n }\\r\\n\\r\\n /// @notice Publishes the private key for which the archaeologist is responsible during the\\r\\n /// sarcophagus resurrection window.\\r\\n /// Pays digging fees to the archaeologist and releases their locked bond.\\r\\n /// Cannot be called on a compromised or buried sarcophagus.\\r\\n /// @param sarcoId The identifier of the sarcophagus for which the archaeologist is responsible\\r\\n /// @param privateKey The private key the archaeologist is publishing\\r\\n function publishPrivateKey(bytes32 sarcoId, bytes32 privateKey) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm current time is after resurrectionTime\\r\\n if (block.timestamp < sarcophagus.resurrectionTime) {\\r\\n revert TooEarlyForPublish(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm current time is within gracePeriod\\r\\n if (block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod) {\\r\\n revert TooLateForPublish(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is an archaeologist on the sarcophagus\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\r\\n .sarcophagi[sarcoId]\\r\\n .cursedArchaeologists[msg.sender];\\r\\n if (cursedArchaeologist.publicKey.length == 0) {\\r\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\r\\n }\\r\\n\\r\\n // Confirm archaeologist has not already leaked their private key\\r\\n if (cursedArchaeologist.isAccused) {\\r\\n revert ArchaeologistHasBeenAccused(msg.sender, sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm archaeologist has not already published their private key\\r\\n if (cursedArchaeologist.privateKey != 0) {\\r\\n revert ArchaeologistAlreadyPublishedPrivateKey(msg.sender);\\r\\n }\\r\\n\\r\\n // Confirm that the private key being submitted matches the public key stored on the\\r\\n // sarcophagus for this archaeologist\\r\\n if (!LibPrivateKeys.isPublicKeyOfPrivateKey(privateKey, cursedArchaeologist.publicKey)) {\\r\\n revert ArchaeologistPublishedIncorrectPrivateKey(\\r\\n msg.sender,\\r\\n cursedArchaeologist.publicKey,\\r\\n privateKey\\r\\n );\\r\\n }\\r\\n\\r\\n // Store the private key on cursed archaeologist\\r\\n cursedArchaeologist.privateKey = privateKey;\\r\\n\\r\\n // Free archaeologist locked bond and transfer digging fees\\r\\n LibBonds.freeArchaeologist(sarcoId, msg.sender);\\r\\n\\r\\n emit PublishPrivateKey(sarcoId, privateKey, msg.sender);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x3fb82b7dbc8a0e25afedfed53aec35c591fedfc57fcf5dcc4bc01c9b8e6a43b7\",\"license\":\"Unlicense\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\n\\r\\ncontract EmbalmerFacet {\\r\\n /// @notice Emitted when a sarcophagus is created\\r\\n /// @param sarcoId Id of the new sarcophagus\\r\\n /// @param name Name of the new sarcophagus\\r\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\r\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\r\\n /// @param embalmer Address of embalmer\\r\\n /// @param recipient Address of recipient\\r\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\r\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\r\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\r\\n event CreateSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n string name,\\r\\n uint256 resurrectionTime,\\r\\n uint256 creationTime,\\r\\n address indexed embalmer,\\r\\n address indexed recipient,\\r\\n address[] cursedArchaeologists,\\r\\n uint256 totalDiggingFees,\\r\\n string arweaveTxId\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is rewrapped\\r\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\r\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\r\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\r\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\r\\n event RewrapSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n uint256 resurrectionTime,\\r\\n uint256 totalDiggingFees,\\r\\n uint256 rewrapSarcophagusProtocolFees\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is buried\\r\\n /// @param sarcoId Id of sarcophagus that was buried\\r\\n event BurySarcophagus(bytes32 indexed sarcoId);\\r\\n\\r\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\r\\n struct SarcophagusParams {\\r\\n string name;\\r\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\r\\n uint256 maximumRewrapInterval;\\r\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\r\\n uint256 maximumResurrectionTime;\\r\\n address recipientAddress;\\r\\n uint256 resurrectionTime;\\r\\n uint8 threshold;\\r\\n uint256 creationTime;\\r\\n }\\r\\n\\r\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\r\\n struct CurseParams {\\r\\n bytes publicKey;\\r\\n address archAddress;\\r\\n uint256 diggingFeePerSecond;\\r\\n uint256 curseFee;\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\r\\n /// @param sarcoId Id that is already in use\\r\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\r\\n /// @param currentTime Timestamp of the failed create attempt\\r\\n /// @param creationTime Time when the sarcophagus parameters were created\\r\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\r\\n error SarcophagusParametersExpired(\\r\\n uint256 currentTime,\\r\\n uint256 creationTime,\\r\\n uint256 creationDeadline\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\r\\n error NoArchaeologistsProvided();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\r\\n error ThresholdCannotBeZero();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\r\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n uint8 threshold,\\r\\n uint256 totalNumberOfArchaeologists\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\r\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\r\\n /// @param currentTime Timestamp of the failed rewrap attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\r\\n /// @param publicKey the duplicated public key\\r\\n error DuplicatePublicKey(bytes publicKey);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\r\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\r\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\r\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\r\\n error ResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\r\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\r\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\r\\n error ResurrectionTimePastMaxResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 maxResurrectionTime\\r\\n );\\r\\n\\r\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\r\\n\\r\\n error NewResurrectionTimeIsZero();\\r\\n\\r\\n error NewResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 previousResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\r\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\r\\n /// of the sarcophagus until its resurrection time.\\r\\n ///\\r\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\r\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\r\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\r\\n /// - `creationTime` of sarcophagus\\r\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\r\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\r\\n ///\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param sarcophagusParams params to set on sarcophagus being created\\r\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\r\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\r\\n function createSarcophagus(\\r\\n bytes32 sarcoId,\\r\\n SarcophagusParams calldata sarcophagusParams,\\r\\n CurseParams[] calldata selectedArchaeologists,\\r\\n string calldata arweaveTxId\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n // Confirm that sarcophagus with supplied id doesn't already exist\\r\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\r\\n revert SarcophagusAlreadyExists(sarcoId);\\r\\n }\\r\\n\\r\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\r\\n // off by its cursed archaeologists.\\r\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\r\\n revert SarcophagusParametersExpired(\\r\\n block.timestamp,\\r\\n sarcophagusParams.creationTime,\\r\\n sarcophagusParams.creationTime + s.expirationThreshold\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\r\\n if (\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\r\\n sarcophagusParams.resurrectionTime\\r\\n ) {\\r\\n revert ResurrectionTimeTooFarInFuture(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the resurrection time is less than the max resurrection time\\r\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // track total digging fees due upon creation of sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n {\\r\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\r\\n // Validate archaeologist and threshold lengths\\r\\n if (nSelectedArchs == 0) {\\r\\n revert NoArchaeologistsProvided();\\r\\n }\\r\\n\\r\\n if (sarcophagusParams.threshold == 0) {\\r\\n revert ThresholdCannotBeZero();\\r\\n }\\r\\n\\r\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\r\\n // used to distribute keyshares among archaeologists\\r\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\r\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n sarcophagusParams.threshold,\\r\\n nSelectedArchs\\r\\n );\\r\\n }\\r\\n\\r\\n // create the sarcophagus\\r\\n sarcophagus.name = sarcophagusParams.name;\\r\\n sarcophagus.threshold = sarcophagusParams.threshold;\\r\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\r\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\r\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\r\\n sarcophagus.arweaveTxId = arweaveTxId;\\r\\n sarcophagus.embalmerAddress = msg.sender;\\r\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\r\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\r\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\r\\n\\r\\n for (uint256 i; i < nSelectedArchs; ) {\\r\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\r\\n\\r\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\r\\n .publicKey\\r\\n .length != 0\\r\\n ) {\\r\\n revert ArchaeologistListContainsDuplicate(\\r\\n selectedArchaeologists[i].archAddress\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm archaeologist is not re-using a key pair\\r\\n if (\\r\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\r\\n address(0)\\r\\n ) {\\r\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\r\\n }\\r\\n\\r\\n LibUtils.verifyArchaeologistSignature(\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n sarcophagusParams.maximumResurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n selectedArchaeologists[i]\\r\\n );\\r\\n\\r\\n // Curse the archaeologist on this sarcophagus\\r\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\r\\n sarcoId,\\r\\n selectedArchaeologists[i],\\r\\n i\\r\\n );\\r\\n\\r\\n totalDiggingFees += diggingFeesDue;\\r\\n\\r\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\r\\n s.publicKeyToArchaeologistAddress[\\r\\n selectedArchaeologists[i].publicKey\\r\\n ] = selectedArchaeologists[i].archAddress;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n s.totalProtocolFees += protocolFees;\\r\\n s.sarcoToken.transferFrom(\\r\\n msg.sender,\\r\\n address(this),\\r\\n totalDiggingFees + protocolFees\\r\\n );\\r\\n }\\r\\n emit CreateSarcophagus(\\r\\n sarcoId,\\r\\n sarcophagusParams.name,\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n msg.sender,\\r\\n sarcophagusParams.recipientAddress,\\r\\n sarcophagus.cursedArchaeologistAddresses,\\r\\n totalDiggingFees,\\r\\n arweaveTxId\\r\\n );\\r\\n }\\r\\n\\r\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param resurrectionTime the new resurrection time\\r\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n\\r\\n // Confirm resurrection time has not yet passed\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time is in future\\r\\n if (block.timestamp >= resurrectionTime) {\\r\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\r\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\r\\n revert NewResurrectionTimeTooFarInFuture(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagus.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\r\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\r\\n\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n // Previous digging fees calculation ignores curseFee\\r\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\r\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (resurrectionTime - block.timestamp);\\r\\n\\r\\n // If the new digging fees are greater than the previous digging fees, we need to\\r\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\r\\n if (newDiggingFees > prevDiggingFees) {\\r\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\r\\n if (cursedBondIncrease > prevDiggingFees) {\\r\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.resurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond += cursedBondIncrease;\\r\\n\\r\\n // Rewards are now previous digging fees - difference\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\r\\n } else if (newDiggingFees < prevDiggingFees) {\\r\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\r\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // Decrease archaeologist's cursed bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond -= cursedBondDecrease;\\r\\n\\r\\n // Increase archaeologist's free bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .freeBond += cursedBondDecrease;\\r\\n\\r\\n // Rewards are equal to the previous digging fees\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n } else {\\r\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n }\\r\\n\\r\\n // Add digging fees due for the new interval\\r\\n totalDiggingFees += newDiggingFees;\\r\\n\\r\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee and unlock the curseFee bond\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n // Pay archaeologists the curse fee to their rewards\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\r\\n\\r\\n // Unlock the curseFee cursed bond by debiting the cursed bond and crediting free bond\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].cursedBond -= ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].freeBond += ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n }\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n\\r\\n // Add the protocol fee to the total protocol fees in storage\\r\\n s.totalProtocolFees += protocolFees;\\r\\n\\r\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\r\\n sarcophagus.resurrectionTime = resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = block.timestamp;\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n sarcophagus.isRewrapped = true;\\r\\n }\\r\\n\\r\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\r\\n\\r\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\r\\n }\\r\\n\\r\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\r\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n function burySarcophagus(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n // Confirm that the current resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Set resurrection time to infinity\\r\\n sarcophagus.resurrectionTime = type(uint256).max;\\r\\n\\r\\n emit BurySarcophagus(sarcoId);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x9b019288bbff9433124bcccab5f8099b19e9f3bf1a9588221c30b4c5da1106dc\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\ncontract ThirdPartyFacet {\\r\\n event AccuseArchaeologist(\\r\\n bytes32 indexed sarcoId,\\r\\n address indexed accuser,\\r\\n uint256 totalSlashedBondDistributed,\\r\\n uint256 totalDiggingFeesDistributed,\\r\\n address[] accusedArchAddresses\\r\\n );\\r\\n\\r\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\r\\n\\r\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\r\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\r\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\r\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\r\\n\\r\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\r\\n /// @param senderAddress Address of sender\\r\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\r\\n\\r\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\r\\n /// @param currentTime Timestamp of the failed accuse attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\r\\n /// @param signatures the number of signatures passed into the accuse call\\r\\n /// @param publicKeys the number of public keys passed into the accuse call\\r\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\r\\n /// @param sarcoId that should have been signed\\r\\n /// @param paymentAddress payment address that should have been signed\\r\\n /// @param publicKey publicKey that should be derived from signing key\\r\\n /// @param signature invalid signature\\r\\n error InvalidAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes publicKey,\\r\\n LibTypes.Signature signature\\r\\n );\\r\\n\\r\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\r\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\r\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\r\\n /// be able to claim remaining locked bond and diggingFees\\r\\n /// @param sarcoId The identifier of the sarcophagus to clean\\r\\n function clean(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer or admin\\r\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\r\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not already been cleaned\\r\\n if (sarcophagus.isCleaned) {\\r\\n revert SarcophagusAlreadyCleaned(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm that the resurrectionTime + gracePeriod have passed\\r\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\r\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\r\\n }\\r\\n\\r\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\r\\n if (\\r\\n msg.sender == sarcophagus.embalmerAddress &&\\r\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert EmbalmerClaimWindowPassed(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // if sender is admin, confirm embalmerClaimWindow has passed\\r\\n if (\\r\\n msg.sender == LibDiamond.contractOwner() &&\\r\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert TooEarlyForAdminClean(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\r\\n uint256 totalDiggingFeesAndLockedBonds;\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\r\\n\\r\\n // Punish archaeologists that failed to publish their private key in time\\r\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\r\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeesDue += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\r\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\r\\n\\r\\n // slash the archaeologist's locked bond for the sarcophagus\\r\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\r\\n // this to the contract's protocol fees\\r\\n if (msg.sender == sarcophagus.embalmerAddress) {\\r\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\r\\n } else {\\r\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\r\\n }\\r\\n\\r\\n sarcophagus.isCleaned = true;\\r\\n emit Clean(sarcoId, msg.sender);\\r\\n }\\r\\n\\r\\n /**\\r\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\r\\n * and payment address generated with the leaked private keys\\r\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\r\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\r\\n *\\r\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\r\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\r\\n * returned\\r\\n *\\r\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\r\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\r\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\r\\n * @param paymentAddress the address to which rewards should be sent if successful\\r\\n */\\r\\n function accuse(\\r\\n bytes32 sarcoId,\\r\\n bytes[] calldata publicKeys,\\r\\n LibTypes.Signature[] calldata signatures,\\r\\n address paymentAddress\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // verify that current time is not past resurrection time\\r\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n uint256 nSigs = signatures.length;\\r\\n\\r\\n if (nSigs != publicKeys.length) {\\r\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\r\\n }\\r\\n\\r\\n address[] memory accusedArchAddresses = new address[](nSigs);\\r\\n\\r\\n // track the combined locked bond across all archaeologists being accused in this call\\r\\n uint256 totalCursedBond;\\r\\n uint256 accusalCount;\\r\\n for (uint256 i; i < nSigs; ) {\\r\\n if (\\r\\n !LibUtils.verifyAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n )\\r\\n ) {\\r\\n revert InvalidAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n );\\r\\n }\\r\\n\\r\\n // look up the archaeologist responsible for the publicKey\\r\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\r\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[accusedArchaeologistAddress];\\r\\n\\r\\n // verify the accused archaeologist is cursed on the sarcophagus\\r\\n if (accusedArchaeologist.publicKey.length == 0) {\\r\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\r\\n }\\r\\n\\r\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\r\\n if (accusedArchaeologist.isAccused) {\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n continue;\\r\\n }\\r\\n\\r\\n // mark the archaeologist on the sarcophagus as having been accused\\r\\n accusedArchaeologist.isAccused = true;\\r\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\r\\n\\r\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\r\\n sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\r\\n }\\r\\n\\r\\n totalCursedBond += cursedBondDue;\\r\\n\\r\\n // Slash the offending archaeologists bond\\r\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\r\\n if (accusalCount == 0) {\\r\\n return;\\r\\n }\\r\\n\\r\\n {\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\r\\n if (accusalCount >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n } else {\\r\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\r\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\r\\n uint256 totalAccusals;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n ++totalAccusals;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\r\\n if (totalAccusals >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n }\\r\\n }\\r\\n\\r\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\r\\n // be returned to the remaining well behaved archaeologists\\r\\n if (sarcophagus.isCompromised) {\\r\\n // iterate through all archaeologist addresses on the sarcophagus\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n // if the archaeologist has never been accused, release their locked bond back to them\\r\\n if (\\r\\n !sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n LibBonds.freeArchaeologist(\\r\\n sarcoId,\\r\\n sarcophagus.cursedArchaeologistAddresses[i]\\r\\n );\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\r\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\r\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\r\\n s.sarcoToken.transfer(\\r\\n sarcophagus.embalmerAddress,\\r\\n totalDiggingFees + halfTotalCursedBond\\r\\n );\\r\\n\\r\\n // transfer the other half of the cursed bond to the transaction caller\\r\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\r\\n\\r\\n emit AccuseArchaeologist(\\r\\n sarcoId,\\r\\n msg.sender,\\r\\n totalCursedBond,\\r\\n totalDiggingFees,\\r\\n accusedArchAddresses\\r\\n );\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xc4a28de898fe399da500fae3d4cd8ff0a300f3dedbc2548d8c54940fd76a7ea1\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\r\\n\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\nlibrary LibBonds {\\r\\n /// @notice Bonds the archaeologist to a sarcophagus.\\r\\n /// This does the following:\\r\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\r\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\r\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\r\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\r\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\r\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\r\\n ///\\r\\n /// @return the amount of digging fees due the embalmer for this curse\\r\\n function curseArchaeologist(\\r\\n bytes32 sarcoId,\\r\\n EmbalmerFacet.CurseParams calldata archaeologist,\\r\\n uint256 index\\r\\n ) internal returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\r\\n publicKey: archaeologist.publicKey,\\r\\n privateKey: 0,\\r\\n isAccused: false,\\r\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\r\\n curseFee: archaeologist.curseFee\\r\\n });\\r\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\r\\n\\r\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\r\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\r\\n + archaeologist.curseFee;\\r\\n\\r\\n // Use cursed bond percentage to determine how much bond to lock up\\r\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\r\\n\\r\\n // Transfer bond to curse from free bond to cursed bond\\r\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\r\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\r\\n\\r\\n return diggingFeesDue;\\r\\n }\\r\\n\\r\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\r\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\r\\n /// @param archaeologistAddress the address of the archaeologist to free\\r\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\r\\n .sarcophagi[sarcoId]\\r\\n .cursedArchaeologists[archaeologistAddress];\\r\\n\\r\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\r\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondAmount = (diggingFeeAmount * sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\r\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\r\\n\\r\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x8c0a7c621ffa042eee7a312fb919102bf8af87daf434bfc07819acb5b3c06dd9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title A collection of Errors\\r\\n * @notice This library defines all of the Errors that the Sarcophagus system\\r\\n * uses.\\r\\n */\\r\\nlibrary LibErrors {\\r\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\r\\n\\r\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\r\\n\\r\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\r\\n\\r\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\r\\n\\r\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusInactive(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusCompromised(bytes32 sarcoId);\\r\\n\\r\\n error SenderNotEmbalmer(address sender, address embalmer);\\r\\n\\r\\n error InvalidSignature(\\r\\n // address recovered from signature via ecrecover\\r\\n address recoveredAddress,\\r\\n // address we expected to have signed the data\\r\\n address expectedAddress\\r\\n );\\r\\n}\\r\\n\",\"keccak256\":\"0xa0a8e8a9d339d070e5bf21d4b0462e5eb947a60acec58d0cb1013006b6d73cac\",\"license\":\"Unlicense\"},\"contracts/libraries/LibPrivateKeys.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Private key verification\\r\\n * @notice Implements a private key -> public key checking function\\r\\n * @dev modified from https://github.com/1Address/ecsol, removes extra code\\r\\n * which isn't necessary for our Sarcophagus implementation\\r\\n */\\r\\nlibrary LibPrivateKeys {\\r\\n /**\\r\\n * @notice Given a private key and a public key, determines if that public\\r\\n * key was derived from the private key\\r\\n * @dev based on https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9\\r\\n * @param privKey an secp256k1 private key\\r\\n * @param pubKey an uncompressed 65 byte secp256k1 public key\\r\\n * @return bool indicating whether the public key is derived from the\\r\\n * private key\\r\\n */\\r\\n function isPublicKeyOfPrivateKey(\\r\\n bytes32 privKey,\\r\\n bytes storage pubKey\\r\\n ) internal view returns (bool) {\\r\\n // removes the 0x04 prefix from an uncompressed public key\\r\\n uint256 pubKeyLength = pubKey.length;\\r\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\r\\n for (uint256 i = 1; i < pubKeyLength; ) {\\r\\n truncatedPublicKey[i - 1] = pubKey[i];\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // generator point coordinates and order of secp256k1\\r\\n uint256 gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;\\r\\n uint256 gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;\\r\\n uint256 m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;\\r\\n\\r\\n address signer = ecrecover(\\r\\n 0,\\r\\n gy % 2 != 0 ? 28 : 27,\\r\\n bytes32(gx),\\r\\n bytes32(mulmod(uint256(privKey), gx, m))\\r\\n );\\r\\n\\r\\n address xyAddress = address(\\r\\n uint160(\\r\\n uint256(keccak256(truncatedPublicKey)) &\\r\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\r\\n )\\r\\n );\\r\\n return xyAddress == signer;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x5d1d2c10d7ab0c943dfe1e1dbc49f944a1b246bba51b626c686f1b54b1dc2fb2\",\"license\":\"MIT\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Types shared across facets for the Sarcophagus diamond\\r\\n */\\r\\nlibrary LibTypes {\\r\\n struct Sarcophagus {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n bool isRewrapped;\\r\\n uint8 threshold;\\r\\n string name;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] cursedArchaeologistAddresses;\\r\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\r\\n uint256 cursedBondPercentage;\\r\\n }\\r\\n\\r\\n struct CursedArchaeologist {\\r\\n uint256 diggingFeePerSecond;\\r\\n // Also used for publish checks -- has not published if 0\\r\\n bytes32 privateKey;\\r\\n // Also used for curse checks -- is not bonded if length is 0\\r\\n bytes publicKey;\\r\\n bool isAccused;\\r\\n uint256 curseFee;\\r\\n }\\r\\n\\r\\n struct Signature {\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n struct ArchaeologistProfile {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string peerId;\\r\\n uint256 minimumDiggingFeePerSecond;\\r\\n uint256 freeBond;\\r\\n uint256 cursedBond;\\r\\n uint256 curseFee;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x096d9660852c5179b16d71abe3a818282db9e980fdc431efa77bd92577d60fb8\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\r\\nimport \\\"./LibTypes.sol\\\";\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\n/**\\r\\n * @title Utility functions used within the Sarcophagus system\\r\\n * @notice This library implements various functions that are used throughout\\r\\n * Sarcophagus, mainly to DRY up the codebase\\r\\n * @dev these functions are all stateless, public, pure/view\\r\\n */\\r\\nlibrary LibUtils {\\r\\n /**\\r\\n * @notice The archaeologist needs to sign off on two pieces of data\\r\\n * to guarantee their unrwap will be successful\\r\\n *\\r\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\r\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\r\\n * @param curseParams parameters of curse signed by archaeologist\\r\\n */\\r\\n function verifyArchaeologistSignature(\\r\\n uint256 agreedMaximumRewrapInterval,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 timestamp,\\r\\n EmbalmerFacet.CurseParams calldata curseParams\\r\\n ) internal pure {\\r\\n // Hash the hash of the data payload\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(\\r\\n abi.encode(\\r\\n curseParams.publicKey,\\r\\n agreedMaximumRewrapInterval,\\r\\n maximumResurrectionTime,\\r\\n curseParams.diggingFeePerSecond,\\r\\n timestamp,\\r\\n curseParams.curseFee\\r\\n )\\r\\n )\\r\\n )\\r\\n );\\r\\n\\r\\n // Generate the address from the signature.\\r\\n // ecrecover should always return a valid address.\\r\\n address recoveredAddress = ecrecover(\\r\\n messageHash,\\r\\n curseParams.v,\\r\\n curseParams.r,\\r\\n curseParams.s\\r\\n );\\r\\n\\r\\n if (recoveredAddress != curseParams.archAddress) {\\r\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Verifies that a signature and public key were created from the same private key\\r\\n /// @param sarcoId the sarcoId that was signed\\r\\n /// @param paymentAddress the payment address that was signed\\r\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\r\\n /// @param signature signature on the sarco id and payment address\\r\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\r\\n function verifyAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes calldata publicKey,\\r\\n LibTypes.Signature calldata signature\\r\\n ) internal pure returns (bool) {\\r\\n // removes the 0x04 prefix from an uncompressed public key\\r\\n uint256 pubKeyLength = publicKey.length;\\r\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\r\\n for (uint256 i = 1; i < pubKeyLength; ) {\\r\\n truncatedPublicKey[i - 1] = publicKey[i];\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(abi.encode(sarcoId, paymentAddress))\\r\\n )\\r\\n );\\r\\n // Use ecrecover to get the address that signed the message\\r\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\r\\n\\r\\n address publicKeyAddress = address(\\r\\n uint160(\\r\\n uint256(keccak256(truncatedPublicKey)) &\\r\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\r\\n )\\r\\n );\\r\\n\\r\\n return signingAddress == publicKeyAddress;\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile exists and\\r\\n /// reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check existence of\\r\\n function revertIfArchProfileExists(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check lack of existence of\\r\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\r\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\r\\n /// @return The protocol fees amount\\r\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x4e6fa08e9f931ba0ef0c2c5b0938be70124d00b94c86a3a4ae303472cd5c8fb8\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\n/**\\r\\n * Global diamond storage struct to be shared across facets\\r\\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\\r\\n */\\r\\nstruct AppStorage {\\r\\n // SARCO token contract\\r\\n IERC20 sarcoToken;\\r\\n // The Admin address allowed to call Admin Facet functions\\r\\n address admin;\\r\\n // total protocol fees available to be withdrawn by the admin\\r\\n uint256 totalProtocolFees;\\r\\n /**\\r\\n * Protocol level admin configurations\\r\\n */\\r\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\r\\n uint256 protocolFeeBasePercentage;\\r\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\r\\n uint256 cursedBondPercentage;\\r\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\r\\n uint256 gracePeriod;\\r\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\r\\n uint256 expirationThreshold;\\r\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\r\\n uint256 embalmerClaimWindow;\\r\\n // registered archaeologist addresses\\r\\n address[] archaeologistProfileAddresses;\\r\\n // public key => archaeologist address\\r\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\r\\n // sarcophagus id => sarcophagus object\\r\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\r\\n // archaeologist address => profile\\r\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\r\\n // current balance of rewards available for the archaeologist to withdraw\\r\\n mapping(address => uint256) archaeologistRewards;\\r\\n}\\r\\n\\r\\nlibrary LibAppStorage {\\r\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\r\\n\\r\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n assembly {\\r\\n s.slot := position\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x66f7100a037fcc417379e68914a8831d867f3701c39419f8f04a3af27008438c\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50612142806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c8063364e0801146100675780636a5ac74c1461008357806395b22c721461009f578063a4110dbe146100bb578063a4d9eb43146100d7578063c885bc58146100f3575b600080fd5b610081600480360381019061007c91906114a0565b6100fd565b005b61009d600480360381019061009891906114a0565b610262565b005b6100b960048036038101906100b49190611613565b6103c9565b005b6100d560048036038101906100d091906116f2565b61061d565b005b6100f160048036038101906100ec9190611613565b610a10565b005b6100fb610cc7565b005b6000610107610e55565b905061011233610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546101669190611761565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b81526004016101cc9291906117e5565b6020604051808303816000875af11580156101eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020f9190611846565b503373ffffffffffffffffffffffffffffffffffffffff167fd91b1e491a880123721b161dbbf8249668b0c546077d7ba4d0016441ca9d8f45836040516102569190611873565b60405180910390a25050565b600061026c610e55565b905061027733610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546102cb919061188e565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401610333939291906118c2565b6020604051808303816000875af1158015610352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103769190611846565b503373ffffffffffffffffffffffffffffffffffffffff167ff882a0847c57aefe6f6c7df2098dd0afd122eb0e886199e223651b8e45fda823836040516103bd9190611873565b60405180910390a25050565b60006103d3610e55565b90506103de33610e82565b60008514806103ed5750600086145b15610424576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508781600201908161047a9190611b10565b50868160030181905550858160000181905550838160010181905550828160060181905550600085146105a8578482600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546104fb919061188e565b925050819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610563939291906118c2565b6020604051808303816000875af1158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190611846565b505b3373ffffffffffffffffffffffffffffffffffffffff167f8497b060a6072f95dc9b98911879fc0378644d084b03c80f8acdb6385609deb88260020183600301548460000154898660010154876006015460405161060b96959493929190611c77565b60405180910390a25050505050505050565b6000610627610e55565b9050600081600a0160008581526020019081526020016000209050600081600001540361068b57836040517f018da6880000000000000000000000000000000000000000000000000000000081526004016106829190611cee565b60405180910390fd5b8060020160009054906101000a900460ff16156106df57836040517f9af72b860000000000000000000000000000000000000000000000000000000081526004016106d69190611cee565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361074757836040517f7c6a6d7000000000000000000000000000000000000000000000000000000000815260040161073e9190611cee565b60405180910390fd5b8060000154421015610796574281600001546040517f4827680900000000000000000000000000000000000000000000000000000000815260040161078d929190611d09565b60405180910390fd5b816005015481600001546107aa919061188e565b4211156108035742826005015482600001546107c6919061188e565b6040517f4ccffab10000000000000000000000000000000000000000000000000000000081526004016107fa929190611d09565b60405180910390fd5b600082600a016000868152602001908152602001600020600a0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201805461086d90611933565b9050036108b157336040517f82881f030000000000000000000000000000000000000000000000000000000081526004016108a89190611d32565b60405180910390fd5b8060030160009054906101000a900460ff16156109075733856040517fa40b44230000000000000000000000000000000000000000000000000000000081526004016108fe929190611d4d565b60405180910390fd5b6000801b81600101541461095257336040517f7b06b1770000000000000000000000000000000000000000000000000000000081526004016109499190611d32565b60405180910390fd5b61095f8482600201610f1e565b6109a7573381600201856040517f5a95e91c00000000000000000000000000000000000000000000000000000000815260040161099e93929190611e20565b60405180910390fd5b8381600101819055506109ba85336111b4565b3373ffffffffffffffffffffffffffffffffffffffff16857f110eca32dd0b1dbdeaa29671186ba025abb2a6d9c193469a7214ee3244ef740486604051610a019190611cee565b60405180910390a35050505050565b6000610a1a610e55565b9050610a25336113ba565b6000851480610a345750600086145b15610a6b576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060e001604052808781526020018581526020018981526020018881526020018681526020016000815260200184815250905060008514610b51578160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610b0c939291906118c2565b6020604051808303816000875af1158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190611846565b505b8082600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081610bbc9190611b10565b50606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505081600801339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f6b3162bc849214e57423b31909892ac678c2245d7ee3c2642c173f7036452394826040015183606001518460000151856080015186602001518760c00151604051610cb596959493929190611ec1565b60405180910390a25050505050505050565b6000610cd1610e55565b9050600081600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600082600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401610dbf9291906117e5565b6020604051808303816000875af1158015610dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e029190611846565b503373ffffffffffffffffffffffffffffffffffffffff167fbc84835063c693975166f00cffb19f01a94c2db55b1bf259238c5da3594e506682604051610e499190611873565b60405180910390a25050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000610e8c610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403610f1a576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401610f11929190611f38565b60405180910390fd5b5050565b600080828054610f2d90611933565b905090506000600182610f409190611761565b67ffffffffffffffff811115610f5957610f586114e8565b5b6040519080825280601f01601f191660200182016040528015610f8b5781602001600182028036833780820191505090505b5090506000600190505b828110156110575784818154610faa90611933565b8110610fb957610fb8611f61565b5b815460011615610fd85790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000028260018361100c9190611761565b8151811061101d5761101c611f61565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806001019050610f95565b5060007f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798905060007f483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419050600060016000806002866110db9190611fbf565b036110e757601b6110ea565b601c5b8660001b85806110fd576110fc611f90565b5b888e60001c0960001b604051600081526020016040526040516111239493929190612054565b6020604051602081039080840390855afa158015611145573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff868051906020012060001c1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161497505050505050505092915050565b60006111be610e55565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546112489190611761565b82600001546112579190612099565b90508260020160029054906101000a900460ff166112825781600401548161127f919061188e565b90505b600061271084600b0154836112979190612099565b6112a191906120db565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546112f79190611761565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611352919061188e565b925050819055508185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113aa919061188e565b9250508190555050505050505050565b60006113c4610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414611452576000826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611449929190611f38565b60405180910390fd5b5050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61147d8161146a565b811461148857600080fd5b50565b60008135905061149a81611474565b92915050565b6000602082840312156114b6576114b5611460565b5b60006114c48482850161148b565b91505092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611520826114d7565b810181811067ffffffffffffffff8211171561153f5761153e6114e8565b5b80604052505050565b6000611552611456565b905061155e8282611517565b919050565b600067ffffffffffffffff82111561157e5761157d6114e8565b5b611587826114d7565b9050602081019050919050565b82818337600083830152505050565b60006115b66115b184611563565b611548565b9050828152602081018484840111156115d2576115d16114d2565b5b6115dd848285611594565b509392505050565b600082601f8301126115fa576115f96114cd565b5b813561160a8482602086016115a3565b91505092915050565b60008060008060008060c087890312156116305761162f611460565b5b600087013567ffffffffffffffff81111561164e5761164d611465565b5b61165a89828a016115e5565b965050602061166b89828a0161148b565b955050604061167c89828a0161148b565b945050606061168d89828a0161148b565b935050608061169e89828a0161148b565b92505060a06116af89828a0161148b565b9150509295509295509295565b6000819050919050565b6116cf816116bc565b81146116da57600080fd5b50565b6000813590506116ec816116c6565b92915050565b6000806040838503121561170957611708611460565b5b6000611717858286016116dd565b9250506020611728858286016116dd565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061176c8261146a565b91506117778361146a565b925082820390508181111561178f5761178e611732565b5b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006117c082611795565b9050919050565b6117d0816117b5565b82525050565b6117df8161146a565b82525050565b60006040820190506117fa60008301856117c7565b61180760208301846117d6565b9392505050565b60008115159050919050565b6118238161180e565b811461182e57600080fd5b50565b6000815190506118408161181a565b92915050565b60006020828403121561185c5761185b611460565b5b600061186a84828501611831565b91505092915050565b600060208201905061188860008301846117d6565b92915050565b60006118998261146a565b91506118a48361146a565b92508282019050808211156118bc576118bb611732565b5b92915050565b60006060820190506118d760008301866117c7565b6118e460208301856117c7565b6118f160408301846117d6565b949350505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061194b57607f821691505b60208210810361195e5761195d611904565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026119c67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611989565b6119d08683611989565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611a0d611a08611a038461146a565b6119e8565b61146a565b9050919050565b6000819050919050565b611a27836119f2565b611a3b611a3382611a14565b848454611996565b825550505050565b600090565b611a50611a43565b611a5b818484611a1e565b505050565b5b81811015611a7f57611a74600082611a48565b600181019050611a61565b5050565b601f821115611ac457611a9581611964565b611a9e84611979565b81016020851015611aad578190505b611ac1611ab985611979565b830182611a60565b50505b505050565b600082821c905092915050565b6000611ae760001984600802611ac9565b1980831691505092915050565b6000611b008383611ad6565b9150826002028217905092915050565b611b19826118f9565b67ffffffffffffffff811115611b3257611b316114e8565b5b611b3c8254611933565b611b47828285611a83565b600060209050601f831160018114611b7a5760008415611b68578287015190505b611b728582611af4565b865550611bda565b601f198416611b8886611964565b60005b82811015611bb057848901518255600182019150602085019450602081019050611b8b565b86831015611bcd5784890151611bc9601f891682611ad6565b8355505b6001600288020188555050505b505050505050565b600082825260208201905092915050565b60008154611c0081611933565b611c0a8186611be2565b94506001821660008114611c255760018114611c3b57611c6e565b60ff198316865281151560200286019350611c6e565b611c4485611964565b60005b83811015611c6657815481890152600182019150602081019050611c47565b808801955050505b50505092915050565b600060c0820190508181036000830152611c918189611bf3565b9050611ca060208301886117d6565b611cad60408301876117d6565b611cba60608301866117d6565b611cc760808301856117d6565b611cd460a08301846117d6565b979650505050505050565b611ce8816116bc565b82525050565b6000602082019050611d036000830184611cdf565b92915050565b6000604082019050611d1e60008301856117d6565b611d2b60208301846117d6565b9392505050565b6000602082019050611d4760008301846117c7565b92915050565b6000604082019050611d6260008301856117c7565b611d6f6020830184611cdf565b9392505050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b60008154611da981611933565b611db38186611d76565b94506001821660008114611dce5760018114611de457611e17565b60ff198316865281151560200286019350611e17565b611ded85611d87565b60005b83811015611e0f57815481890152600182019150602081019050611df0565b808801955050505b50505092915050565b6000606082019050611e3560008301866117c7565b8181036020830152611e478185611d9c565b9050611e566040830184611cdf565b949350505050565b60005b83811015611e7c578082015181840152602081019050611e61565b60008484015250505050565b6000611e93826118f9565b611e9d8185611be2565b9350611ead818560208601611e5e565b611eb6816114d7565b840191505092915050565b600060c0820190508181036000830152611edb8189611e88565b9050611eea60208301886117d6565b611ef760408301876117d6565b611f0460608301866117d6565b611f1160808301856117d6565b611f1e60a08301846117d6565b979650505050505050565b611f328161180e565b82525050565b6000604082019050611f4d6000830185611f29565b611f5a60208301846117c7565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611fca8261146a565b9150611fd58361146a565b925082611fe557611fe4611f90565b5b828206905092915050565b6000819050919050565b60008160001b9050919050565b600061202261201d61201884611ff0565b611ffa565b6116bc565b9050919050565b61203281612007565b82525050565b600060ff82169050919050565b61204e81612038565b82525050565b60006080820190506120696000830187612029565b6120766020830186612045565b6120836040830185611cdf565b6120906060830184611cdf565b95945050505050565b60006120a48261146a565b91506120af8361146a565b92508282026120bd8161146a565b915082820484148315176120d4576120d3611732565b5b5092915050565b60006120e68261146a565b91506120f18361146a565b92508261210157612100611f90565b5b82820490509291505056fea264697066735822122014cca9a6dd40c22a7c7026391e09a704e5f5b809f86910859101955c0929a67a64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100625760003560e01c8063364e0801146100675780636a5ac74c1461008357806395b22c721461009f578063a4110dbe146100bb578063a4d9eb43146100d7578063c885bc58146100f3575b600080fd5b610081600480360381019061007c91906114a0565b6100fd565b005b61009d600480360381019061009891906114a0565b610262565b005b6100b960048036038101906100b49190611613565b6103c9565b005b6100d560048036038101906100d091906116f2565b61061d565b005b6100f160048036038101906100ec9190611613565b610a10565b005b6100fb610cc7565b005b6000610107610e55565b905061011233610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546101669190611761565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33846040518363ffffffff1660e01b81526004016101cc9291906117e5565b6020604051808303816000875af11580156101eb573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061020f9190611846565b503373ffffffffffffffffffffffffffffffffffffffff167fd91b1e491a880123721b161dbbf8249668b0c546077d7ba4d0016441ca9d8f45836040516102569190611873565b60405180910390a25050565b600061026c610e55565b905061027733610e82565b8181600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546102cb919061188e565b925050819055508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330856040518463ffffffff1660e01b8152600401610333939291906118c2565b6020604051808303816000875af1158015610352573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906103769190611846565b503373ffffffffffffffffffffffffffffffffffffffff167ff882a0847c57aefe6f6c7df2098dd0afd122eb0e886199e223651b8e45fda823836040516103bd9190611873565b60405180910390a25050565b60006103d3610e55565b90506103de33610e82565b60008514806103ed5750600086145b15610424576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600081600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508781600201908161047a9190611b10565b50868160030181905550858160000181905550838160010181905550828160060181905550600085146105a8578482600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546104fb919061188e565b925050819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610563939291906118c2565b6020604051808303816000875af1158015610582573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105a69190611846565b505b3373ffffffffffffffffffffffffffffffffffffffff167f8497b060a6072f95dc9b98911879fc0378644d084b03c80f8acdb6385609deb88260020183600301548460000154898660010154876006015460405161060b96959493929190611c77565b60405180910390a25050505050505050565b6000610627610e55565b9050600081600a0160008581526020019081526020016000209050600081600001540361068b57836040517f018da6880000000000000000000000000000000000000000000000000000000081526004016106829190611cee565b60405180910390fd5b8060020160009054906101000a900460ff16156106df57836040517f9af72b860000000000000000000000000000000000000000000000000000000081526004016106d69190611cee565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361074757836040517f7c6a6d7000000000000000000000000000000000000000000000000000000000815260040161073e9190611cee565b60405180910390fd5b8060000154421015610796574281600001546040517f4827680900000000000000000000000000000000000000000000000000000000815260040161078d929190611d09565b60405180910390fd5b816005015481600001546107aa919061188e565b4211156108035742826005015482600001546107c6919061188e565b6040517f4ccffab10000000000000000000000000000000000000000000000000000000081526004016107fa929190611d09565b60405180910390fd5b600082600a016000868152602001908152602001600020600a0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600081600201805461086d90611933565b9050036108b157336040517f82881f030000000000000000000000000000000000000000000000000000000081526004016108a89190611d32565b60405180910390fd5b8060030160009054906101000a900460ff16156109075733856040517fa40b44230000000000000000000000000000000000000000000000000000000081526004016108fe929190611d4d565b60405180910390fd5b6000801b81600101541461095257336040517f7b06b1770000000000000000000000000000000000000000000000000000000081526004016109499190611d32565b60405180910390fd5b61095f8482600201610f1e565b6109a7573381600201856040517f5a95e91c00000000000000000000000000000000000000000000000000000000815260040161099e93929190611e20565b60405180910390fd5b8381600101819055506109ba85336111b4565b3373ffffffffffffffffffffffffffffffffffffffff16857f110eca32dd0b1dbdeaa29671186ba025abb2a6d9c193469a7214ee3244ef740486604051610a019190611cee565b60405180910390a35050505050565b6000610a1a610e55565b9050610a25336113ba565b6000851480610a345750600086145b15610a6b576040517fdec9919f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60006040518060e001604052808781526020018581526020018981526020018881526020018681526020016000815260200184815250905060008514610b51578160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330886040518463ffffffff1660e01b8152600401610b0c939291906118c2565b6020604051808303816000875af1158015610b2b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4f9190611846565b505b8082600b0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081610bbc9190611b10565b50606082015181600301556080820151816004015560a0820151816005015560c0820151816006015590505081600801339080600181540180825580915050600190039060005260206000200160009091909190916101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055503373ffffffffffffffffffffffffffffffffffffffff167f6b3162bc849214e57423b31909892ac678c2245d7ee3c2642c173f7036452394826040015183606001518460000151856080015186602001518760c00151604051610cb596959493929190611ec1565b60405180910390a25050505050505050565b6000610cd1610e55565b9050600081600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020549050600082600c0160003373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055508160000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb33836040518363ffffffff1660e01b8152600401610dbf9291906117e5565b6020604051808303816000875af1158015610dde573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e029190611846565b503373ffffffffffffffffffffffffffffffffffffffff167fbc84835063c693975166f00cffb19f01a94c2db55b1bf259238c5da3594e506682604051610e499190611873565b60405180910390a25050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000610e8c610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403610f1a576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401610f11929190611f38565b60405180910390fd5b5050565b600080828054610f2d90611933565b905090506000600182610f409190611761565b67ffffffffffffffff811115610f5957610f586114e8565b5b6040519080825280601f01601f191660200182016040528015610f8b5781602001600182028036833780820191505090505b5090506000600190505b828110156110575784818154610faa90611933565b8110610fb957610fb8611f61565b5b815460011615610fd85790600052602060002090602091828204019190065b9054901a7f0100000000000000000000000000000000000000000000000000000000000000028260018361100c9190611761565b8151811061101d5761101c611f61565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806001019050610f95565b5060007f79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798905060007f483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8905060007ffffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd03641419050600060016000806002866110db9190611fbf565b036110e757601b6110ea565b601c5b8660001b85806110fd576110fc611f90565b5b888e60001c0960001b604051600081526020016040526040516111239493929190612054565b6020604051602081039080840390855afa158015611145573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff868051906020012060001c1690508173ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff161497505050505050505092915050565b60006111be610e55565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546112489190611761565b82600001546112579190612099565b90508260020160029054906101000a900460ff166112825781600401548161127f919061188e565b90505b600061271084600b0154836112979190612099565b6112a191906120db565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546112f79190611761565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611352919061188e565b925050819055508185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113aa919061188e565b9250508190555050505050505050565b60006113c4610e55565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015414611452576000826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611449929190611f38565b60405180910390fd5b5050565b6000604051905090565b600080fd5b600080fd5b6000819050919050565b61147d8161146a565b811461148857600080fd5b50565b60008135905061149a81611474565b92915050565b6000602082840312156114b6576114b5611460565b5b60006114c48482850161148b565b91505092915050565b600080fd5b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b611520826114d7565b810181811067ffffffffffffffff8211171561153f5761153e6114e8565b5b80604052505050565b6000611552611456565b905061155e8282611517565b919050565b600067ffffffffffffffff82111561157e5761157d6114e8565b5b611587826114d7565b9050602081019050919050565b82818337600083830152505050565b60006115b66115b184611563565b611548565b9050828152602081018484840111156115d2576115d16114d2565b5b6115dd848285611594565b509392505050565b600082601f8301126115fa576115f96114cd565b5b813561160a8482602086016115a3565b91505092915050565b60008060008060008060c087890312156116305761162f611460565b5b600087013567ffffffffffffffff81111561164e5761164d611465565b5b61165a89828a016115e5565b965050602061166b89828a0161148b565b955050604061167c89828a0161148b565b945050606061168d89828a0161148b565b935050608061169e89828a0161148b565b92505060a06116af89828a0161148b565b9150509295509295509295565b6000819050919050565b6116cf816116bc565b81146116da57600080fd5b50565b6000813590506116ec816116c6565b92915050565b6000806040838503121561170957611708611460565b5b6000611717858286016116dd565b9250506020611728858286016116dd565b9150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061176c8261146a565b91506117778361146a565b925082820390508181111561178f5761178e611732565b5b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006117c082611795565b9050919050565b6117d0816117b5565b82525050565b6117df8161146a565b82525050565b60006040820190506117fa60008301856117c7565b61180760208301846117d6565b9392505050565b60008115159050919050565b6118238161180e565b811461182e57600080fd5b50565b6000815190506118408161181a565b92915050565b60006020828403121561185c5761185b611460565b5b600061186a84828501611831565b91505092915050565b600060208201905061188860008301846117d6565b92915050565b60006118998261146a565b91506118a48361146a565b92508282019050808211156118bc576118bb611732565b5b92915050565b60006060820190506118d760008301866117c7565b6118e460208301856117c7565b6118f160408301846117d6565b949350505050565b600081519050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061194b57607f821691505b60208210810361195e5761195d611904565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026119c67fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611989565b6119d08683611989565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611a0d611a08611a038461146a565b6119e8565b61146a565b9050919050565b6000819050919050565b611a27836119f2565b611a3b611a3382611a14565b848454611996565b825550505050565b600090565b611a50611a43565b611a5b818484611a1e565b505050565b5b81811015611a7f57611a74600082611a48565b600181019050611a61565b5050565b601f821115611ac457611a9581611964565b611a9e84611979565b81016020851015611aad578190505b611ac1611ab985611979565b830182611a60565b50505b505050565b600082821c905092915050565b6000611ae760001984600802611ac9565b1980831691505092915050565b6000611b008383611ad6565b9150826002028217905092915050565b611b19826118f9565b67ffffffffffffffff811115611b3257611b316114e8565b5b611b3c8254611933565b611b47828285611a83565b600060209050601f831160018114611b7a5760008415611b68578287015190505b611b728582611af4565b865550611bda565b601f198416611b8886611964565b60005b82811015611bb057848901518255600182019150602085019450602081019050611b8b565b86831015611bcd5784890151611bc9601f891682611ad6565b8355505b6001600288020188555050505b505050505050565b600082825260208201905092915050565b60008154611c0081611933565b611c0a8186611be2565b94506001821660008114611c255760018114611c3b57611c6e565b60ff198316865281151560200286019350611c6e565b611c4485611964565b60005b83811015611c6657815481890152600182019150602081019050611c47565b808801955050505b50505092915050565b600060c0820190508181036000830152611c918189611bf3565b9050611ca060208301886117d6565b611cad60408301876117d6565b611cba60608301866117d6565b611cc760808301856117d6565b611cd460a08301846117d6565b979650505050505050565b611ce8816116bc565b82525050565b6000602082019050611d036000830184611cdf565b92915050565b6000604082019050611d1e60008301856117d6565b611d2b60208301846117d6565b9392505050565b6000602082019050611d4760008301846117c7565b92915050565b6000604082019050611d6260008301856117c7565b611d6f6020830184611cdf565b9392505050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b60008154611da981611933565b611db38186611d76565b94506001821660008114611dce5760018114611de457611e17565b60ff198316865281151560200286019350611e17565b611ded85611d87565b60005b83811015611e0f57815481890152600182019150602081019050611df0565b808801955050505b50505092915050565b6000606082019050611e3560008301866117c7565b8181036020830152611e478185611d9c565b9050611e566040830184611cdf565b949350505050565b60005b83811015611e7c578082015181840152602081019050611e61565b60008484015250505050565b6000611e93826118f9565b611e9d8185611be2565b9350611ead818560208601611e5e565b611eb6816114d7565b840191505092915050565b600060c0820190508181036000830152611edb8189611e88565b9050611eea60208301886117d6565b611ef760408301876117d6565b611f0460608301866117d6565b611f1160808301856117d6565b611f1e60a08301846117d6565b979650505050505050565b611f328161180e565b82525050565b6000604082019050611f4d6000830185611f29565b611f5a60208301846117c7565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611fca8261146a565b9150611fd58361146a565b925082611fe557611fe4611f90565b5b828206905092915050565b6000819050919050565b60008160001b9050919050565b600061202261201d61201884611ff0565b611ffa565b6116bc565b9050919050565b61203281612007565b82525050565b600060ff82169050919050565b61204e81612038565b82525050565b60006080820190506120696000830187612029565b6120766020830186612045565b6120836040830185611cdf565b6120906060830184611cdf565b95945050505050565b60006120a48261146a565b91506120af8361146a565b92508282026120bd8161146a565b915082820484148315176120d4576120d3611732565b5b5092915050565b60006120e68261146a565b91506120f18361146a565b92508261210157612100611f90565b5b82820490509291505056fea264697066735822122014cca9a6dd40c22a7c7026391e09a704e5f5b809f86910859101955c0929a67a64736f6c63430008120033", - "devdoc": { - "errors": { - "ArchaeologistAlreadyPublishedPrivateKey(address)": [ - { - "params": { - "archaeologistAddress": "address of publishing archaeologist" - } - } - ], - "ArchaeologistHasBeenAccused(address,bytes32)": [ - { - "params": { - "archaeologistAddress": "Address of accused archaeologist who is attempting to publish their private key", - "sarcoId": "ID of sarcophagus archaeologist has attempted to publish a key on" - } - } - ], - "ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)": [ - { - "params": { - "archaeologistAddress": "address of publishing archaeologist", - "privateKey": "privateKey the archaeologist has attempted to publish", - "publicKey": "publicKey stored for archaeologist on the sarcophagus" - } - } - ], - "TooEarlyForPublish(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed publish attempt", - "resurrectionTime": "Time after which the sarcophagus can be resurrected" - } - } - ], - "TooLateForPublish(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed publish attempt", - "publishDeadline": "Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)" - } - } - ] - }, - "events": { - "PublishPrivateKey(bytes32,bytes32,address)": { - "params": { - "privateKey": "private key that has been published", - "sarcoId": "ID of sarcophagus archaeologist has published the private key on" - } - } - }, - "kind": "dev", - "methods": { - "depositFreeBond(uint256)": { - "params": { - "amount": "The amount to deposit" - } - }, - "publishPrivateKey(bytes32,bytes32)": { - "params": { - "privateKey": "The private key the archaeologist is publishing", - "sarcoId": "The identifier of the sarcophagus for which the archaeologist is responsible" - } - }, - "registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { - "params": { - "curseFee": "The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction", - "freeBond": "How much bond the archaeologist wants to deposit during the register call (if any)", - "maximumResurrectionTime": "The time beyond which the archaeologist is not willing to accept new curses or rewraps", - "maximumRewrapInterval": "The longest interval of time from a rewrap time the arch will accept for a resurrection", - "minimumDiggingFeePerSecond": "The archaeologist's minimum amount to earn per second for being cursed", - "peerId": "The libp2p identifier for the archaeologist" - } - }, - "updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { - "params": { - "curseFee": "The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction", - "freeBond": "How much bond the archaeologist wants to deposit during the update call (if any)", - "maximumRewrapInterval": "The longest interval of time from a rewrap time the arch will accept for a resurrection", - "minimumDiggingFeePerSecond": "The archaeologist's minimum amount to earn per second for being cursed", - "peerId": "The libp2p identifier for the archaeologist" - } - }, - "withdrawFreeBond(uint256)": { - "params": { - "amount": "The amount to withdraw" - } - } - }, - "version": 1 - }, - "userdoc": { - "errors": { - "ArchaeologistAlreadyPublishedPrivateKey(address)": [ - { - "notice": "Archaeologist has attempted to publish a key for a sarcophagus twice" - } - ], - "ArchaeologistHasBeenAccused(address,bytes32)": [ - { - "notice": "An archaeologist that has already been successfully accused has attempted to publish their private key" - } - ], - "ArchaeologistPublishedIncorrectPrivateKey(address,bytes,bytes32)": [ - { - "notice": "Archaeologist has attempted to publish the incorrect private key for a sarcophagus" - } - ], - "CannotSetZeroProfileValue()": [ - { - "notice": "Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval" - } - ], - "TooEarlyForPublish(uint256,uint256)": [ - { - "notice": "Archaeologist has attempted to publish a key before the resurrection time" - } - ], - "TooLateForPublish(uint256,uint256)": [ - { - "notice": "Archaeologist has attempted to publish a key after the end of the resurrection window" - } - ] - }, - "events": { - "PublishPrivateKey(bytes32,bytes32,address)": { - "notice": "Emitted when an archaeologist successfully publishes their private key for a sarcophagus" - } - }, - "kind": "user", - "methods": { - "depositFreeBond(uint256)": { - "notice": "Deposits an archaeologist's free bond to the contract." - }, - "publishPrivateKey(bytes32,bytes32)": { - "notice": "Publishes the private key for which the archaeologist is responsible during the sarcophagus resurrection window. Pays digging fees to the archaeologist and releases their locked bond. Cannot be called on a compromised or buried sarcophagus." - }, - "registerArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { - "notice": "Registers the archaeologist profile" - }, - "updateArchaeologist(string,uint256,uint256,uint256,uint256,uint256)": { - "notice": "Updates the archaeologist profile" - }, - "withdrawFreeBond(uint256)": { - "notice": "Withdraws an archaeologist's free bond from the contract." - }, - "withdrawReward()": { - "notice": "Withdraws all rewards from an archaeologist's reward pool" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/deployments/baseGoerli/EmbalmerFacet.json b/deployments/baseGoerli/EmbalmerFacet.json deleted file mode 100644 index 2ea3433..0000000 --- a/deployments/baseGoerli/EmbalmerFacet.json +++ /dev/null @@ -1,722 +0,0 @@ -{ - "address": "0x5CA66f7E40F28e0905DD641E7bF4Ec6930656636", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "archaeologistAddress", - "type": "address" - } - ], - "name": "ArchaeologistListContainsDuplicate", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bool", - "name": "exists", - "type": "bool" - }, - { - "internalType": "address", - "name": "archaeologist", - "type": "address" - } - ], - "name": "ArchaeologistProfileExistsShouldBe", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - } - ], - "name": "DuplicatePublicKey", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "recoveredAddress", - "type": "address" - }, - { - "internalType": "address", - "name": "expectedAddress", - "type": "address" - } - ], - "name": "InvalidSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "newResurrectionTime", - "type": "uint256" - } - ], - "name": "NewResurrectionTimeInPast", - "type": "error" - }, - { - "inputs": [], - "name": "NewResurrectionTimeIsZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sarcophagusMaximumRewrapInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumPermissibleResurrectionTime", - "type": "uint256" - } - ], - "name": "NewResurrectionTimeTooFarInFuture", - "type": "error" - }, - { - "inputs": [], - "name": "NoArchaeologistsProvided", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - } - ], - "name": "ResurrectionTimeInPast", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maxResurrectionTime", - "type": "uint256" - } - ], - "name": "ResurrectionTimePastMaxResurrectionTime", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "sarcophagusMaximumRewrapInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumPermissibleResurrectionTime", - "type": "uint256" - } - ], - "name": "ResurrectionTimeTooFarInFuture", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "previousResurrectionTime", - "type": "uint256" - } - ], - "name": "ResurrectionTimeTooFarPastPreviousResurrectionTime", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusAlreadyExists", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusCompromised", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusInactive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "creationDeadline", - "type": "uint256" - } - ], - "name": "SarcophagusParametersExpired", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "sender", - "type": "address" - }, - { - "internalType": "address", - "name": "embalmer", - "type": "address" - } - ], - "name": "SenderNotEmbalmer", - "type": "error" - }, - { - "inputs": [], - "name": "ThresholdCannotBeZero", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "threshold", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "totalNumberOfArchaeologists", - "type": "uint256" - } - ], - "name": "ThresholdGreaterThanTotalNumberOfArchaeologists", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "BurySarcophagus", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "creationTime", - "type": "uint256" - }, - { - "indexed": true, - "internalType": "address", - "name": "embalmer", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "recipient", - "type": "address" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "cursedArchaeologists", - "type": "address[]" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiggingFees", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "string", - "name": "arweaveTxId", - "type": "string" - } - ], - "name": "CreateSarcophagus", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiggingFees", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "rewrapSarcophagusProtocolFees", - "type": "uint256" - } - ], - "name": "RewrapSarcophagus", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "burySarcophagus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "components": [ - { - "internalType": "string", - "name": "name", - "type": "string" - }, - { - "internalType": "uint256", - "name": "maximumRewrapInterval", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "maximumResurrectionTime", - "type": "uint256" - }, - { - "internalType": "address", - "name": "recipientAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "threshold", - "type": "uint8" - }, - { - "internalType": "uint256", - "name": "creationTime", - "type": "uint256" - } - ], - "internalType": "struct EmbalmerFacet.SarcophagusParams", - "name": "sarcophagusParams", - "type": "tuple" - }, - { - "components": [ - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - }, - { - "internalType": "address", - "name": "archAddress", - "type": "address" - }, - { - "internalType": "uint256", - "name": "diggingFeePerSecond", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "curseFee", - "type": "uint256" - }, - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct EmbalmerFacet.CurseParams[]", - "name": "selectedArchaeologists", - "type": "tuple[]" - }, - { - "internalType": "string", - "name": "arweaveTxId", - "type": "string" - } - ], - "name": "createSarcophagus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - } - ], - "name": "rewrapSarcophagus", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0x4f917ac2da2ea3cbb488cf40a12df2592c912892f169a224f67effc562d8e5da", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 1, - "gasUsed": "2848412", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x151b26fb6e4ae4c18e4fe296c7fffabb00227b5004895c60baeaa04295ccc9d7", - "transactionHash": "0x4f917ac2da2ea3cbb488cf40a12df2592c912892f169a224f67effc562d8e5da", - "logs": [], - "blockNumber": 9669966, - "cumulativeGasUsed": "2895241", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "b7fcd450a9977c08df561a1e7df764e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologistAddress\",\"type\":\"address\"}],\"name\":\"ArchaeologistListContainsDuplicate\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bool\",\"name\":\"exists\",\"type\":\"bool\"},{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistProfileExistsShouldBe\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"}],\"name\":\"DuplicatePublicKey\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recoveredAddress\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"expectedAddress\",\"type\":\"address\"}],\"name\":\"InvalidSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"newResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"NewResurrectionTimeInPast\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NewResurrectionTimeIsZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sarcophagusMaximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumPermissibleResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"NewResurrectionTimeTooFarInFuture\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NoArchaeologistsProvided\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeInPast\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maxResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimePastMaxResurrectionTime\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"sarcophagusMaximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumPermissibleResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeTooFarInFuture\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"previousResurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeTooFarPastPreviousResurrectionTime\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusAlreadyExists\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusCompromised\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"creationDeadline\",\"type\":\"uint256\"}],\"name\":\"SarcophagusParametersExpired\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"embalmer\",\"type\":\"address\"}],\"name\":\"SenderNotEmbalmer\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ThresholdCannotBeZero\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"threshold\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"totalNumberOfArchaeologists\",\"type\":\"uint256\"}],\"name\":\"ThresholdGreaterThanTotalNumberOfArchaeologists\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"BurySarcophagus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"creationTime\",\"type\":\"uint256\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"embalmer\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"cursedArchaeologists\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDiggingFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"arweaveTxId\",\"type\":\"string\"}],\"name\":\"CreateSarcophagus\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDiggingFees\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"rewrapSarcophagusProtocolFees\",\"type\":\"uint256\"}],\"name\":\"RewrapSarcophagus\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"burySarcophagus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"components\":[{\"internalType\":\"string\",\"name\":\"name\",\"type\":\"string\"},{\"internalType\":\"uint256\",\"name\":\"maximumRewrapInterval\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"maximumResurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"address\",\"name\":\"recipientAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"threshold\",\"type\":\"uint8\"},{\"internalType\":\"uint256\",\"name\":\"creationTime\",\"type\":\"uint256\"}],\"internalType\":\"struct EmbalmerFacet.SarcophagusParams\",\"name\":\"sarcophagusParams\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"internalType\":\"address\",\"name\":\"archAddress\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"diggingFeePerSecond\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"curseFee\",\"type\":\"uint256\"},{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct EmbalmerFacet.CurseParams[]\",\"name\":\"selectedArchaeologists\",\"type\":\"tuple[]\"},{\"internalType\":\"string\",\"name\":\"arweaveTxId\",\"type\":\"string\"}],\"name\":\"createSarcophagus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"rewrapSarcophagus\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DuplicatePublicKey(bytes)\":[{\"params\":{\"publicKey\":\"the duplicated public key\"}}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed rewrap attempt\",\"resurrectionTime\":\"Resurrection timestamp which has already passed\"}}],\"ResurrectionTimePastMaxResurrectionTime(uint256,uint256)\":[{\"params\":{\"maxResurrectionTime\":\"The maximum allowed resurrection time\",\"resurrectionTime\":\"The resurrection time defined during the sarcophagus creation or rewrap\"}}],\"ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)\":[{\"params\":{\"maximumPermissibleResurrectionTime\":\"Resurrection timestamp which is too far in the future\",\"resurrectionTime\":\"Resurrection timestamp which is too far in the future\",\"sarcophagusMaximumRewrapInterval\":\"Maximum rewrap interval set for the sarcophagus\"}}],\"SarcophagusAlreadyExists(bytes32)\":[{\"params\":{\"sarcoId\":\"Id that is already in use\"}}],\"SarcophagusParametersExpired(uint256,uint256,uint256)\":[{\"params\":{\"creationDeadline\":\"Deadline for creation of a sarcophagus with the supplied parameters\",\"creationTime\":\"Time when the sarcophagus parameters were created\",\"currentTime\":\"Timestamp of the failed create attempt\"}}]},\"events\":{\"BurySarcophagus(bytes32)\":{\"params\":{\"sarcoId\":\"Id of sarcophagus that was buried\"}},\"CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)\":{\"params\":{\"arweaveTxId\":\"arweave tx id for the sarcophagus\",\"creationTime\":\"Creation time as set during negotiation, not the same as blocktime at which event is emitted\",\"cursedArchaeologists\":\"Array of addresses of cursed archaeologists\",\"embalmer\":\"Address of embalmer\",\"name\":\"Name of the new sarcophagus\",\"recipient\":\"Address of recipient\",\"resurrectionTime\":\"Resurrection time of the new sarcophagus\",\"sarcoId\":\"Id of the new sarcophagus\",\"totalDiggingFees\":\"Total digging fees charged to embalmer to create the sarcophagus\"}},\"RewrapSarcophagus(bytes32,uint256,uint256,uint256)\":{\"params\":{\"resurrectionTime\":\"New resurrection time for the sarcophagus\",\"rewrapSarcophagusProtocolFees\":\"Total protocol fees charged to the embalmer for the rewrap\",\"sarcoId\":\"Id of sarcophagus that was rewrapped\",\"totalDiggingFees\":\"Total digging fees charged to the embalmer for the rewrap\"}}},\"kind\":\"dev\",\"methods\":{\"burySarcophagus(bytes32)\":{\"params\":{\"sarcoId\":\"the identifier of the sarcophagus\"}},\"createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)\":{\"params\":{\"arweaveTxId\":\"id of tx storing the sarcophagus payload on arweave\",\"sarcoId\":\"the identifier of the sarcophagus\",\"sarcophagusParams\":\"params to set on sarcophagus being created\",\"selectedArchaeologists\":\"the archaeologists the embalmer has selected to curse\"}},\"rewrapSarcophagus(bytes32,uint256)\":{\"params\":{\"resurrectionTime\":\"the new resurrection time\",\"sarcoId\":\"the identifier of the sarcophagus\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"ArchaeologistListContainsDuplicate(address)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\"}],\"DuplicatePublicKey(bytes)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\"}],\"NoArchaeologistsProvided()\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\"}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\"}],\"ResurrectionTimePastMaxResurrectionTime(uint256,uint256)\":[{\"notice\":\"Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\"}],\"ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\"}],\"SarcophagusAlreadyExists(bytes32)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\"}],\"SarcophagusParametersExpired(uint256,uint256,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with expired parameters\"}],\"ThresholdCannotBeZero()\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\"}],\"ThresholdGreaterThanTotalNumberOfArchaeologists(uint8,uint256)\":[{\"notice\":\"Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\"}]},\"events\":{\"BurySarcophagus(bytes32)\":{\"notice\":\"Emitted when a sarcophagus is buried\"},\"CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)\":{\"notice\":\"Emitted when a sarcophagus is created\"},\"RewrapSarcophagus(bytes32,uint256,uint256,uint256)\":{\"notice\":\"Emitted when a sarcophagus is rewrapped\"}},\"kind\":\"user\",\"methods\":{\"burySarcophagus(bytes32)\":{\"notice\":\"Terminates a sarcophagus by setting its resurrection time to infinity and returning locked bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\"},\"createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)\":{\"notice\":\"Creates a sarcophagus with the supplied parameters and locks a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration of the sarcophagus until its resurrection time. Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters: - `publicKey` that matches the private key the archaeologist is responsible for - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap. - `creationTime` of sarcophagus - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant. - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\"},\"rewrapSarcophagus(bytes32,uint256)\":{\"notice\":\"Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/EmbalmerFacet.sol\":\"EmbalmerFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\n\\r\\ncontract EmbalmerFacet {\\r\\n /// @notice Emitted when a sarcophagus is created\\r\\n /// @param sarcoId Id of the new sarcophagus\\r\\n /// @param name Name of the new sarcophagus\\r\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\r\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\r\\n /// @param embalmer Address of embalmer\\r\\n /// @param recipient Address of recipient\\r\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\r\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\r\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\r\\n event CreateSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n string name,\\r\\n uint256 resurrectionTime,\\r\\n uint256 creationTime,\\r\\n address indexed embalmer,\\r\\n address indexed recipient,\\r\\n address[] cursedArchaeologists,\\r\\n uint256 totalDiggingFees,\\r\\n string arweaveTxId\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is rewrapped\\r\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\r\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\r\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\r\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\r\\n event RewrapSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n uint256 resurrectionTime,\\r\\n uint256 totalDiggingFees,\\r\\n uint256 rewrapSarcophagusProtocolFees\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is buried\\r\\n /// @param sarcoId Id of sarcophagus that was buried\\r\\n event BurySarcophagus(bytes32 indexed sarcoId);\\r\\n\\r\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\r\\n struct SarcophagusParams {\\r\\n string name;\\r\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\r\\n uint256 maximumRewrapInterval;\\r\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\r\\n uint256 maximumResurrectionTime;\\r\\n address recipientAddress;\\r\\n uint256 resurrectionTime;\\r\\n uint8 threshold;\\r\\n uint256 creationTime;\\r\\n }\\r\\n\\r\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\r\\n struct CurseParams {\\r\\n bytes publicKey;\\r\\n address archAddress;\\r\\n uint256 diggingFeePerSecond;\\r\\n uint256 curseFee;\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\r\\n /// @param sarcoId Id that is already in use\\r\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\r\\n /// @param currentTime Timestamp of the failed create attempt\\r\\n /// @param creationTime Time when the sarcophagus parameters were created\\r\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\r\\n error SarcophagusParametersExpired(\\r\\n uint256 currentTime,\\r\\n uint256 creationTime,\\r\\n uint256 creationDeadline\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\r\\n error NoArchaeologistsProvided();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\r\\n error ThresholdCannotBeZero();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\r\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n uint8 threshold,\\r\\n uint256 totalNumberOfArchaeologists\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\r\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\r\\n /// @param currentTime Timestamp of the failed rewrap attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\r\\n /// @param publicKey the duplicated public key\\r\\n error DuplicatePublicKey(bytes publicKey);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\r\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\r\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\r\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\r\\n error ResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\r\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\r\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\r\\n error ResurrectionTimePastMaxResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 maxResurrectionTime\\r\\n );\\r\\n\\r\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\r\\n\\r\\n error NewResurrectionTimeIsZero();\\r\\n\\r\\n error NewResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 previousResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\r\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\r\\n /// of the sarcophagus until its resurrection time.\\r\\n ///\\r\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\r\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\r\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\r\\n /// - `creationTime` of sarcophagus\\r\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\r\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\r\\n ///\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param sarcophagusParams params to set on sarcophagus being created\\r\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\r\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\r\\n function createSarcophagus(\\r\\n bytes32 sarcoId,\\r\\n SarcophagusParams calldata sarcophagusParams,\\r\\n CurseParams[] calldata selectedArchaeologists,\\r\\n string calldata arweaveTxId\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n // Confirm that sarcophagus with supplied id doesn't already exist\\r\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\r\\n revert SarcophagusAlreadyExists(sarcoId);\\r\\n }\\r\\n\\r\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\r\\n // off by its cursed archaeologists.\\r\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\r\\n revert SarcophagusParametersExpired(\\r\\n block.timestamp,\\r\\n sarcophagusParams.creationTime,\\r\\n sarcophagusParams.creationTime + s.expirationThreshold\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\r\\n if (\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\r\\n sarcophagusParams.resurrectionTime\\r\\n ) {\\r\\n revert ResurrectionTimeTooFarInFuture(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the resurrection time is less than the max resurrection time\\r\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // track total digging fees due upon creation of sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n {\\r\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\r\\n // Validate archaeologist and threshold lengths\\r\\n if (nSelectedArchs == 0) {\\r\\n revert NoArchaeologistsProvided();\\r\\n }\\r\\n\\r\\n if (sarcophagusParams.threshold == 0) {\\r\\n revert ThresholdCannotBeZero();\\r\\n }\\r\\n\\r\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\r\\n // used to distribute keyshares among archaeologists\\r\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\r\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n sarcophagusParams.threshold,\\r\\n nSelectedArchs\\r\\n );\\r\\n }\\r\\n\\r\\n // create the sarcophagus\\r\\n sarcophagus.name = sarcophagusParams.name;\\r\\n sarcophagus.threshold = sarcophagusParams.threshold;\\r\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\r\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\r\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\r\\n sarcophagus.arweaveTxId = arweaveTxId;\\r\\n sarcophagus.embalmerAddress = msg.sender;\\r\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\r\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\r\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\r\\n\\r\\n for (uint256 i; i < nSelectedArchs; ) {\\r\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\r\\n\\r\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\r\\n .publicKey\\r\\n .length != 0\\r\\n ) {\\r\\n revert ArchaeologistListContainsDuplicate(\\r\\n selectedArchaeologists[i].archAddress\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm archaeologist is not re-using a key pair\\r\\n if (\\r\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\r\\n address(0)\\r\\n ) {\\r\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\r\\n }\\r\\n\\r\\n LibUtils.verifyArchaeologistSignature(\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n sarcophagusParams.maximumResurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n selectedArchaeologists[i]\\r\\n );\\r\\n\\r\\n // Curse the archaeologist on this sarcophagus\\r\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\r\\n sarcoId,\\r\\n selectedArchaeologists[i],\\r\\n i\\r\\n );\\r\\n\\r\\n totalDiggingFees += diggingFeesDue;\\r\\n\\r\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\r\\n s.publicKeyToArchaeologistAddress[\\r\\n selectedArchaeologists[i].publicKey\\r\\n ] = selectedArchaeologists[i].archAddress;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n s.totalProtocolFees += protocolFees;\\r\\n s.sarcoToken.transferFrom(\\r\\n msg.sender,\\r\\n address(this),\\r\\n totalDiggingFees + protocolFees\\r\\n );\\r\\n }\\r\\n emit CreateSarcophagus(\\r\\n sarcoId,\\r\\n sarcophagusParams.name,\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n msg.sender,\\r\\n sarcophagusParams.recipientAddress,\\r\\n sarcophagus.cursedArchaeologistAddresses,\\r\\n totalDiggingFees,\\r\\n arweaveTxId\\r\\n );\\r\\n }\\r\\n\\r\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param resurrectionTime the new resurrection time\\r\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n\\r\\n // Confirm resurrection time has not yet passed\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time is in future\\r\\n if (block.timestamp >= resurrectionTime) {\\r\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\r\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\r\\n revert NewResurrectionTimeTooFarInFuture(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagus.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\r\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\r\\n\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n // Previous digging fees calculation ignores curseFee\\r\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\r\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (resurrectionTime - block.timestamp);\\r\\n\\r\\n // If the new digging fees are greater than the previous digging fees, we need to\\r\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\r\\n if (newDiggingFees > prevDiggingFees) {\\r\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\r\\n if (cursedBondIncrease > prevDiggingFees) {\\r\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.resurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond += cursedBondIncrease;\\r\\n\\r\\n // Rewards are now previous digging fees - difference\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\r\\n } else if (newDiggingFees < prevDiggingFees) {\\r\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\r\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // Decrease archaeologist's cursed bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond -= cursedBondDecrease;\\r\\n\\r\\n // Increase archaeologist's free bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .freeBond += cursedBondDecrease;\\r\\n\\r\\n // Rewards are equal to the previous digging fees\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n } else {\\r\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n }\\r\\n\\r\\n // Add digging fees due for the new interval\\r\\n totalDiggingFees += newDiggingFees;\\r\\n\\r\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee and unlock the curseFee bond\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n // Pay archaeologists the curse fee to their rewards\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\r\\n\\r\\n // Unlock the curseFee cursed bond by debiting the cursed bond and crediting free bond\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].cursedBond -= ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].freeBond += ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n }\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n\\r\\n // Add the protocol fee to the total protocol fees in storage\\r\\n s.totalProtocolFees += protocolFees;\\r\\n\\r\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\r\\n sarcophagus.resurrectionTime = resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = block.timestamp;\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n sarcophagus.isRewrapped = true;\\r\\n }\\r\\n\\r\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\r\\n\\r\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\r\\n }\\r\\n\\r\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\r\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n function burySarcophagus(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n // Confirm that the current resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Set resurrection time to infinity\\r\\n sarcophagus.resurrectionTime = type(uint256).max;\\r\\n\\r\\n emit BurySarcophagus(sarcoId);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x9b019288bbff9433124bcccab5f8099b19e9f3bf1a9588221c30b4c5da1106dc\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\ncontract ThirdPartyFacet {\\r\\n event AccuseArchaeologist(\\r\\n bytes32 indexed sarcoId,\\r\\n address indexed accuser,\\r\\n uint256 totalSlashedBondDistributed,\\r\\n uint256 totalDiggingFeesDistributed,\\r\\n address[] accusedArchAddresses\\r\\n );\\r\\n\\r\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\r\\n\\r\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\r\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\r\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\r\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\r\\n\\r\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\r\\n /// @param senderAddress Address of sender\\r\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\r\\n\\r\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\r\\n /// @param currentTime Timestamp of the failed accuse attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\r\\n /// @param signatures the number of signatures passed into the accuse call\\r\\n /// @param publicKeys the number of public keys passed into the accuse call\\r\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\r\\n /// @param sarcoId that should have been signed\\r\\n /// @param paymentAddress payment address that should have been signed\\r\\n /// @param publicKey publicKey that should be derived from signing key\\r\\n /// @param signature invalid signature\\r\\n error InvalidAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes publicKey,\\r\\n LibTypes.Signature signature\\r\\n );\\r\\n\\r\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\r\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\r\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\r\\n /// be able to claim remaining locked bond and diggingFees\\r\\n /// @param sarcoId The identifier of the sarcophagus to clean\\r\\n function clean(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer or admin\\r\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\r\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not already been cleaned\\r\\n if (sarcophagus.isCleaned) {\\r\\n revert SarcophagusAlreadyCleaned(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm that the resurrectionTime + gracePeriod have passed\\r\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\r\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\r\\n }\\r\\n\\r\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\r\\n if (\\r\\n msg.sender == sarcophagus.embalmerAddress &&\\r\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert EmbalmerClaimWindowPassed(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // if sender is admin, confirm embalmerClaimWindow has passed\\r\\n if (\\r\\n msg.sender == LibDiamond.contractOwner() &&\\r\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert TooEarlyForAdminClean(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\r\\n uint256 totalDiggingFeesAndLockedBonds;\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\r\\n\\r\\n // Punish archaeologists that failed to publish their private key in time\\r\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\r\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeesDue += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\r\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\r\\n\\r\\n // slash the archaeologist's locked bond for the sarcophagus\\r\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\r\\n // this to the contract's protocol fees\\r\\n if (msg.sender == sarcophagus.embalmerAddress) {\\r\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\r\\n } else {\\r\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\r\\n }\\r\\n\\r\\n sarcophagus.isCleaned = true;\\r\\n emit Clean(sarcoId, msg.sender);\\r\\n }\\r\\n\\r\\n /**\\r\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\r\\n * and payment address generated with the leaked private keys\\r\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\r\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\r\\n *\\r\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\r\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\r\\n * returned\\r\\n *\\r\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\r\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\r\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\r\\n * @param paymentAddress the address to which rewards should be sent if successful\\r\\n */\\r\\n function accuse(\\r\\n bytes32 sarcoId,\\r\\n bytes[] calldata publicKeys,\\r\\n LibTypes.Signature[] calldata signatures,\\r\\n address paymentAddress\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // verify that current time is not past resurrection time\\r\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n uint256 nSigs = signatures.length;\\r\\n\\r\\n if (nSigs != publicKeys.length) {\\r\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\r\\n }\\r\\n\\r\\n address[] memory accusedArchAddresses = new address[](nSigs);\\r\\n\\r\\n // track the combined locked bond across all archaeologists being accused in this call\\r\\n uint256 totalCursedBond;\\r\\n uint256 accusalCount;\\r\\n for (uint256 i; i < nSigs; ) {\\r\\n if (\\r\\n !LibUtils.verifyAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n )\\r\\n ) {\\r\\n revert InvalidAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n );\\r\\n }\\r\\n\\r\\n // look up the archaeologist responsible for the publicKey\\r\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\r\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[accusedArchaeologistAddress];\\r\\n\\r\\n // verify the accused archaeologist is cursed on the sarcophagus\\r\\n if (accusedArchaeologist.publicKey.length == 0) {\\r\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\r\\n }\\r\\n\\r\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\r\\n if (accusedArchaeologist.isAccused) {\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n continue;\\r\\n }\\r\\n\\r\\n // mark the archaeologist on the sarcophagus as having been accused\\r\\n accusedArchaeologist.isAccused = true;\\r\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\r\\n\\r\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\r\\n sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\r\\n }\\r\\n\\r\\n totalCursedBond += cursedBondDue;\\r\\n\\r\\n // Slash the offending archaeologists bond\\r\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\r\\n if (accusalCount == 0) {\\r\\n return;\\r\\n }\\r\\n\\r\\n {\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\r\\n if (accusalCount >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n } else {\\r\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\r\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\r\\n uint256 totalAccusals;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n ++totalAccusals;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\r\\n if (totalAccusals >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n }\\r\\n }\\r\\n\\r\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\r\\n // be returned to the remaining well behaved archaeologists\\r\\n if (sarcophagus.isCompromised) {\\r\\n // iterate through all archaeologist addresses on the sarcophagus\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n // if the archaeologist has never been accused, release their locked bond back to them\\r\\n if (\\r\\n !sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n LibBonds.freeArchaeologist(\\r\\n sarcoId,\\r\\n sarcophagus.cursedArchaeologistAddresses[i]\\r\\n );\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\r\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\r\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\r\\n s.sarcoToken.transfer(\\r\\n sarcophagus.embalmerAddress,\\r\\n totalDiggingFees + halfTotalCursedBond\\r\\n );\\r\\n\\r\\n // transfer the other half of the cursed bond to the transaction caller\\r\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\r\\n\\r\\n emit AccuseArchaeologist(\\r\\n sarcoId,\\r\\n msg.sender,\\r\\n totalCursedBond,\\r\\n totalDiggingFees,\\r\\n accusedArchAddresses\\r\\n );\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xc4a28de898fe399da500fae3d4cd8ff0a300f3dedbc2548d8c54940fd76a7ea1\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\r\\n\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\nlibrary LibBonds {\\r\\n /// @notice Bonds the archaeologist to a sarcophagus.\\r\\n /// This does the following:\\r\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\r\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\r\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\r\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\r\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\r\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\r\\n ///\\r\\n /// @return the amount of digging fees due the embalmer for this curse\\r\\n function curseArchaeologist(\\r\\n bytes32 sarcoId,\\r\\n EmbalmerFacet.CurseParams calldata archaeologist,\\r\\n uint256 index\\r\\n ) internal returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\r\\n publicKey: archaeologist.publicKey,\\r\\n privateKey: 0,\\r\\n isAccused: false,\\r\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\r\\n curseFee: archaeologist.curseFee\\r\\n });\\r\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\r\\n\\r\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\r\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\r\\n + archaeologist.curseFee;\\r\\n\\r\\n // Use cursed bond percentage to determine how much bond to lock up\\r\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\r\\n\\r\\n // Transfer bond to curse from free bond to cursed bond\\r\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\r\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\r\\n\\r\\n return diggingFeesDue;\\r\\n }\\r\\n\\r\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\r\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\r\\n /// @param archaeologistAddress the address of the archaeologist to free\\r\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\r\\n .sarcophagi[sarcoId]\\r\\n .cursedArchaeologists[archaeologistAddress];\\r\\n\\r\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\r\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondAmount = (diggingFeeAmount * sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\r\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\r\\n\\r\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x8c0a7c621ffa042eee7a312fb919102bf8af87daf434bfc07819acb5b3c06dd9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title A collection of Errors\\r\\n * @notice This library defines all of the Errors that the Sarcophagus system\\r\\n * uses.\\r\\n */\\r\\nlibrary LibErrors {\\r\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\r\\n\\r\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\r\\n\\r\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\r\\n\\r\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\r\\n\\r\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusInactive(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusCompromised(bytes32 sarcoId);\\r\\n\\r\\n error SenderNotEmbalmer(address sender, address embalmer);\\r\\n\\r\\n error InvalidSignature(\\r\\n // address recovered from signature via ecrecover\\r\\n address recoveredAddress,\\r\\n // address we expected to have signed the data\\r\\n address expectedAddress\\r\\n );\\r\\n}\\r\\n\",\"keccak256\":\"0xa0a8e8a9d339d070e5bf21d4b0462e5eb947a60acec58d0cb1013006b6d73cac\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Types shared across facets for the Sarcophagus diamond\\r\\n */\\r\\nlibrary LibTypes {\\r\\n struct Sarcophagus {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n bool isRewrapped;\\r\\n uint8 threshold;\\r\\n string name;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] cursedArchaeologistAddresses;\\r\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\r\\n uint256 cursedBondPercentage;\\r\\n }\\r\\n\\r\\n struct CursedArchaeologist {\\r\\n uint256 diggingFeePerSecond;\\r\\n // Also used for publish checks -- has not published if 0\\r\\n bytes32 privateKey;\\r\\n // Also used for curse checks -- is not bonded if length is 0\\r\\n bytes publicKey;\\r\\n bool isAccused;\\r\\n uint256 curseFee;\\r\\n }\\r\\n\\r\\n struct Signature {\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n struct ArchaeologistProfile {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string peerId;\\r\\n uint256 minimumDiggingFeePerSecond;\\r\\n uint256 freeBond;\\r\\n uint256 cursedBond;\\r\\n uint256 curseFee;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x096d9660852c5179b16d71abe3a818282db9e980fdc431efa77bd92577d60fb8\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\r\\nimport \\\"./LibTypes.sol\\\";\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\n/**\\r\\n * @title Utility functions used within the Sarcophagus system\\r\\n * @notice This library implements various functions that are used throughout\\r\\n * Sarcophagus, mainly to DRY up the codebase\\r\\n * @dev these functions are all stateless, public, pure/view\\r\\n */\\r\\nlibrary LibUtils {\\r\\n /**\\r\\n * @notice The archaeologist needs to sign off on two pieces of data\\r\\n * to guarantee their unrwap will be successful\\r\\n *\\r\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\r\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\r\\n * @param curseParams parameters of curse signed by archaeologist\\r\\n */\\r\\n function verifyArchaeologistSignature(\\r\\n uint256 agreedMaximumRewrapInterval,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 timestamp,\\r\\n EmbalmerFacet.CurseParams calldata curseParams\\r\\n ) internal pure {\\r\\n // Hash the hash of the data payload\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(\\r\\n abi.encode(\\r\\n curseParams.publicKey,\\r\\n agreedMaximumRewrapInterval,\\r\\n maximumResurrectionTime,\\r\\n curseParams.diggingFeePerSecond,\\r\\n timestamp,\\r\\n curseParams.curseFee\\r\\n )\\r\\n )\\r\\n )\\r\\n );\\r\\n\\r\\n // Generate the address from the signature.\\r\\n // ecrecover should always return a valid address.\\r\\n address recoveredAddress = ecrecover(\\r\\n messageHash,\\r\\n curseParams.v,\\r\\n curseParams.r,\\r\\n curseParams.s\\r\\n );\\r\\n\\r\\n if (recoveredAddress != curseParams.archAddress) {\\r\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Verifies that a signature and public key were created from the same private key\\r\\n /// @param sarcoId the sarcoId that was signed\\r\\n /// @param paymentAddress the payment address that was signed\\r\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\r\\n /// @param signature signature on the sarco id and payment address\\r\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\r\\n function verifyAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes calldata publicKey,\\r\\n LibTypes.Signature calldata signature\\r\\n ) internal pure returns (bool) {\\r\\n // removes the 0x04 prefix from an uncompressed public key\\r\\n uint256 pubKeyLength = publicKey.length;\\r\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\r\\n for (uint256 i = 1; i < pubKeyLength; ) {\\r\\n truncatedPublicKey[i - 1] = publicKey[i];\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(abi.encode(sarcoId, paymentAddress))\\r\\n )\\r\\n );\\r\\n // Use ecrecover to get the address that signed the message\\r\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\r\\n\\r\\n address publicKeyAddress = address(\\r\\n uint160(\\r\\n uint256(keccak256(truncatedPublicKey)) &\\r\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\r\\n )\\r\\n );\\r\\n\\r\\n return signingAddress == publicKeyAddress;\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile exists and\\r\\n /// reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check existence of\\r\\n function revertIfArchProfileExists(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check lack of existence of\\r\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\r\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\r\\n /// @return The protocol fees amount\\r\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x4e6fa08e9f931ba0ef0c2c5b0938be70124d00b94c86a3a4ae303472cd5c8fb8\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\n/**\\r\\n * Global diamond storage struct to be shared across facets\\r\\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\\r\\n */\\r\\nstruct AppStorage {\\r\\n // SARCO token contract\\r\\n IERC20 sarcoToken;\\r\\n // The Admin address allowed to call Admin Facet functions\\r\\n address admin;\\r\\n // total protocol fees available to be withdrawn by the admin\\r\\n uint256 totalProtocolFees;\\r\\n /**\\r\\n * Protocol level admin configurations\\r\\n */\\r\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\r\\n uint256 protocolFeeBasePercentage;\\r\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\r\\n uint256 cursedBondPercentage;\\r\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\r\\n uint256 gracePeriod;\\r\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\r\\n uint256 expirationThreshold;\\r\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\r\\n uint256 embalmerClaimWindow;\\r\\n // registered archaeologist addresses\\r\\n address[] archaeologistProfileAddresses;\\r\\n // public key => archaeologist address\\r\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\r\\n // sarcophagus id => sarcophagus object\\r\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\r\\n // archaeologist address => profile\\r\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\r\\n // current balance of rewards available for the archaeologist to withdraw\\r\\n mapping(address => uint256) archaeologistRewards;\\r\\n}\\r\\n\\r\\nlibrary LibAppStorage {\\r\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\r\\n\\r\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n assembly {\\r\\n s.slot := position\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x66f7100a037fcc417379e68914a8831d867f3701c39419f8f04a3af27008438c\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b506132ad806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c80630511f2ec1461004657806355b21ba214610062578063ab7d79691461007e575b600080fd5b610060600480360381019061005b91906122a2565b61009a565b005b61007c600480360381019061007791906123ae565b610432565b005b610098600480360381019061009391906124a7565b610e19565b005b60006100a4611a35565b9050600081600a0160008481526020019081526020016000209050600081600001540361010857826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100ff91906124f6565b60405180910390fd5b8060020160009054906101000a900460ff161561015c57826040517f9af72b8600000000000000000000000000000000000000000000000000000000815260040161015391906124f6565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036101c457826040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016101bb91906124f6565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461027e57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c000000000000000000000000000000000000000000000000000000008152600401610275929190612552565b60405180910390fd5b806000015442106102cc574281600001546040517f2458293a0000000000000000000000000000000000000000000000000000000081526004016102c392919061258a565b60405180910390fd5b600081600901905060008180549050905060005b818110156103d457600084600a016000858481548110610303576103026125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff166103c8576103c787858481548110610397576103966125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611a62565b5b816001019150506102e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360000181905550847f3a0205aa93b1a96da7d6405b2967f91b441383623de2d1ee3b27bfd1642b167a60405160405180910390a25050505050565b600061043c611a35565b9050600081600a016000898152602001908152602001600020600001541461049b57866040517fb9d0d58400000000000000000000000000000000000000000000000000000000815260040161049291906124f6565b60405180910390fd5b80600601548660c001356104af9190612611565b42111561050e57428660c0013582600601548860c001356104d09190612611565b6040517ffafba49500000000000000000000000000000000000000000000000000000000815260040161050593929190612645565b60405180910390fd5b8560800135421061055c574286608001356040517f2458293a00000000000000000000000000000000000000000000000000000000815260040161055392919061258a565b60405180910390fd5b85608001358660200135426105719190612611565b10156105cf57856080013586602001358760200135426105919190612611565b6040517f3d7ad6900000000000000000000000000000000000000000000000000000000081526004016105c693929190612645565b60405180910390fd5b85604001358660800135111561062657856080013586604001356040517f7532a1b000000000000000000000000000000000000000000000000000000000815260040161061d92919061258a565b60405180910390fd5b600081600a016000898152602001908152602001600020905060008087879050905060008103610682576040517fb274cdd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008960a001602081019061069791906126b5565b60ff16036106d1576040517ff412416600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808960a00160208101906106e591906126b5565b60ff16111561073f578860a001602081019061070191906126b5565b816040517fa44e438a0000000000000000000000000000000000000000000000000000000081526004016107369291906126f1565b60405180910390fd5b88806000019061074f9190612729565b8460030191826107609291906129d2565b508860a001602081019061077491906126b5565b8360020160036101000a81548160ff021916908360ff160217905550886080013583600001819055508860c001358360010181905550886020013583600401819055508860400135836005018190555085858460060191826107d79291906129d2565b50338360070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088606001602081019061082e9190612ace565b8360080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508067ffffffffffffffff81111561088a57610889612797565b5b6040519080825280602002602001820160405280156108b85781602001602082028036833780820191505090505b508360090190805190602001906108d09291906121bb565b50836004015483600b018190555060005b81811015610c94576109288989838181106108ff576108fe6125b3565b5b90506020028101906109119190612afb565b60200160208101906109239190612ace565b611c68565b600084600a0160008b8b85818110610943576109426125b3565b5b90506020028101906109559190612afb565b60200160208101906109679190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180546109af906127f5565b905014610a29578888828181106109c9576109c86125b3565b5b90506020028101906109db9190612afb565b60200160208101906109ed9190612ace565b6040517f11298b2f000000000000000000000000000000000000000000000000000000008152600401610a209190612b23565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16856009018a8a84818110610a5857610a576125b3565b5b9050602002810190610a6a9190612afb565b8060000190610a799190612b3e565b604051610a87929190612be0565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610b4257888882818110610ae457610ae36125b3565b5b9050602002810190610af69190612afb565b8060000190610b059190612b3e565b6040517f65453fd5000000000000000000000000000000000000000000000000000000008152600401610b39929190612c48565b60405180910390fd5b610b7e8a602001358b604001358c60c001358c8c86818110610b6757610b666125b3565b5b9050602002810190610b799190612afb565b611d04565b6000610baf8c8b8b85818110610b9757610b966125b3565b5b9050602002810190610ba99190612afb565b84611e82565b90508084610bbd9190612611565b9350898983818110610bd257610bd16125b3565b5b9050602002810190610be49190612afb565b6020016020810190610bf69190612ace565b866009018b8b85818110610c0d57610c0c6125b3565b5b9050602002810190610c1f9190612afb565b8060000190610c2e9190612b3e565b604051610c3c929190612be0565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816001019150506108e1565b506000610ca083612189565b905080856002016000828254610cb69190612611565b925050819055508460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308487610d0b9190612611565b6040518463ffffffff1660e01b8152600401610d2993929190612c6c565b6020604051808303816000875af1158015610d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6c9190612cdb565b505050876060016020810190610d829190612ace565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168a7fe4607f24c5b0a05d9a47b2d4cd8bdb75b50ec717c6bcf5bbc92d48b175d5ce068b8060000190610de19190612729565b8d608001358e60c0013589600901898e8e604051610e06989796959493929190612e6a565b60405180910390a4505050505050505050565b6000610e23611a35565b9050600081600a01600085815260200190815260200160002090506000816000015403610e8757836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610e7e91906124f6565b60405180910390fd5b8060020160009054906101000a900460ff1615610edb57836040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610ed291906124f6565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff816000015403610f4357836040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610f3a91906124f6565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ffd57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c000000000000000000000000000000000000000000000000000000008152600401610ff4929190612552565b60405180910390fd5b8060000154421061104b574281600001546040517f2458293a00000000000000000000000000000000000000000000000000000000815260040161104292919061258a565b60405180910390fd5b8242106110915742836040517f3c6870c000000000000000000000000000000000000000000000000000000000815260040161108892919061258a565b60405180910390fd5b828160040154426110a29190612611565b10156110fc578281600401548260040154426110be9190612611565b6040517fca9b0f900000000000000000000000000000000000000000000000000000000081526004016110f393929190612645565b60405180910390fd5b828160050154101561114b578281600501546040517f7532a1b000000000000000000000000000000000000000000000000000000000815260040161114292919061258a565b60405180910390fd5b600080826009019050600083600b0154905060008280549050905060005b818110156118cf57600086600a01600086848154811061118c5761118b6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff166118c35760008760010154886000015461121f9190612ee4565b826000015461122e9190612f18565b90506000428b61123e9190612ee4565b836000015461124d9190612f18565b9050818111156114085760006127108784846112699190612ee4565b6112739190612f18565b61127d9190612f89565b9050828111156112ca578b8a600001546040517f48d069230000000000000000000000000000000000000000000000000000000081526004016112c192919061258a565b60405180910390fd5b808b600b0160008a88815481106112e4576112e36125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501600082825461135b9190612611565b92505081905550808361136e9190612ee4565b8b600c0160008a8881548110611387576113866125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113fb9190612611565b925050819055505061169a565b818110156116035760006127108783856114229190612ee4565b61142c9190612f18565b6114369190612f89565b9050808b600b0160008a8881548110611452576114516125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546114c99190612ee4565b92505081905550808b600b0160008a88815481106114ea576114e96125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546115619190612611565b92505081905550828b600c0160008a8881548110611582576115816125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546115f69190612611565b9250508190555050611699565b818a600c01600089878154811061161d5761161c6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546116919190612611565b925050819055505b5b80886116a69190612611565b97508860020160029054906101000a900460ff166118c05782600401548a600c0160008987815481106116dc576116db6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117509190612611565b9250508190555061271086846004015461176a9190612f18565b6117749190612f89565b8a600b01600089878154811061178d5761178c6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546118049190612ee4565b9250508190555061271086846004015461181e9190612f18565b6118289190612f89565b8a600b016000898781548110611841576118406125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546118b89190612611565b925050819055505b50505b81600101915050611169565b5060006118db85612189565b9050808760020160008282546118f19190612611565b925050819055508786600001819055504286600101819055508560020160029054906101000a900460ff1661193e5760018660020160026101000a81548160ff0219169083151502179055505b8660000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330848961198c9190612611565b6040518463ffffffff1660e01b81526004016119aa93929190612c6c565b6020604051808303816000875af11580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed9190612cdb565b50887ff2ded5f77c6de574fac210979efbdd01ff3071d109e50651be4e05211f6e4943898784604051611a2293929190612645565b60405180910390a2505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000611a6c611a35565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600082600101548360000154611af69190612ee4565b8260000154611b059190612f18565b90508260020160029054906101000a900460ff16611b3057816004015481611b2d9190612611565b90505b600061271084600b015483611b459190612f18565b611b4f9190612f89565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254611ba59190612ee4565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611c009190612611565b925050819055508185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611c589190612611565b9250508190555050505050505050565b6000611c72611a35565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403611d00576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611cf7929190612fc9565b60405180910390fd5b5050565b6000818060000190611d169190612b3e565b86868560400135878760600135604051602001611d399796959493929190612ff2565b60405160208183030381529060405280519060200120604051602001611d5f91906130d4565b6040516020818303038152906040528051906020012090506000600182846080016020810190611d8f91906126b5565b8560a001358660c0013560405160008152602001604052604051611db694939291906130fa565b6020604051602081039080840390855afa158015611dd8573d6000803e3d6000fd5b505050602060405103519050826020016020810190611df79190612ace565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611e7a5780836020016020810190611e3d9190612ace565b6040517f42d750dc000000000000000000000000000000000000000000000000000000008152600401611e71929190612552565b60405180910390fd5b505050505050565b600080611e8d611a35565b9050600081600a01600087815260200190815260200160002090506040518060a00160405280866040013581526020016000801b8152602001868060000190611ed69190612b3e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600015158152602001866060013581525081600a016000876020016020810190611f489190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081611fab91906131a5565b5060608201518160030160006101000a81548160ff02191690831515021790555060808201518160040155905050846020016020810190611fec9190612ace565b816009018581548110612002576120016125b3565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008560600135826001015483600001546120659190612ee4565b87604001356120749190612f18565b61207e9190612611565b905060006127108460040154836120959190612f18565b61209f9190612f89565b90508084600b0160008960200160208101906120bb9190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546121079190612ee4565b925050819055508084600b0160008960200160208101906121289190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546121749190612611565b92505081905550819450505050509392505050565b600080612194611a35565b90506127108160030154846121a99190612f18565b6121b39190612f89565b915050919050565b828054828255906000526020600020908101928215612234579160200282015b828111156122335782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906121db565b5b5090506122419190612245565b5090565b5b8082111561225e576000816000905550600101612246565b5090565b600080fd5b600080fd5b6000819050919050565b61227f8161226c565b811461228a57600080fd5b50565b60008135905061229c81612276565b92915050565b6000602082840312156122b8576122b7612262565b5b60006122c68482850161228d565b91505092915050565b600080fd5b600060e082840312156122ea576122e96122cf565b5b81905092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612318576123176122f3565b5b8235905067ffffffffffffffff811115612335576123346122f8565b5b602083019150836020820283011115612351576123506122fd565b5b9250929050565b60008083601f84011261236e5761236d6122f3565b5b8235905067ffffffffffffffff81111561238b5761238a6122f8565b5b6020830191508360018202830111156123a7576123a66122fd565b5b9250929050565b600080600080600080608087890312156123cb576123ca612262565b5b60006123d989828a0161228d565b965050602087013567ffffffffffffffff8111156123fa576123f9612267565b5b61240689828a016122d4565b955050604087013567ffffffffffffffff81111561242757612426612267565b5b61243389828a01612302565b9450945050606087013567ffffffffffffffff81111561245657612455612267565b5b61246289828a01612358565b92509250509295509295509295565b6000819050919050565b61248481612471565b811461248f57600080fd5b50565b6000813590506124a18161247b565b92915050565b600080604083850312156124be576124bd612262565b5b60006124cc8582860161228d565b92505060206124dd85828601612492565b9150509250929050565b6124f08161226c565b82525050565b600060208201905061250b60008301846124e7565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061253c82612511565b9050919050565b61254c81612531565b82525050565b60006040820190506125676000830185612543565b6125746020830184612543565b9392505050565b61258481612471565b82525050565b600060408201905061259f600083018561257b565b6125ac602083018461257b565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061261c82612471565b915061262783612471565b925082820190508082111561263f5761263e6125e2565b5b92915050565b600060608201905061265a600083018661257b565b612667602083018561257b565b612674604083018461257b565b949350505050565b600060ff82169050919050565b6126928161267c565b811461269d57600080fd5b50565b6000813590506126af81612689565b92915050565b6000602082840312156126cb576126ca612262565b5b60006126d9848285016126a0565b91505092915050565b6126eb8161267c565b82525050565b600060408201905061270660008301856126e2565b612713602083018461257b565b9392505050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126127465761274561271a565b5b80840192508235915067ffffffffffffffff8211156127685761276761271f565b5b60208301925060018202360383131561278457612783612724565b5b509250929050565b600082905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061280d57607f821691505b6020821081036128205761281f6127c6565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026128887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261284b565b612892868361284b565b95508019841693508086168417925050509392505050565b6000819050919050565b60006128cf6128ca6128c584612471565b6128aa565b612471565b9050919050565b6000819050919050565b6128e9836128b4565b6128fd6128f5826128d6565b848454612858565b825550505050565b600090565b612912612905565b61291d8184846128e0565b505050565b5b818110156129415761293660008261290a565b600181019050612923565b5050565b601f8211156129865761295781612826565b6129608461283b565b8101602085101561296f578190505b61298361297b8561283b565b830182612922565b50505b505050565b600082821c905092915050565b60006129a96000198460080261298b565b1980831691505092915050565b60006129c28383612998565b9150826002028217905092915050565b6129dc838361278c565b67ffffffffffffffff8111156129f5576129f4612797565b5b6129ff82546127f5565b612a0a828285612945565b6000601f831160018114612a395760008415612a27578287013590505b612a3185826129b6565b865550612a99565b601f198416612a4786612826565b60005b82811015612a6f57848901358255600182019150602085019450602081019050612a4a565b86831015612a8c5784890135612a88601f891682612998565b8355505b6001600288020188555050505b50505050505050565b612aab81612531565b8114612ab657600080fd5b50565b600081359050612ac881612aa2565b92915050565b600060208284031215612ae457612ae3612262565b5b6000612af284828501612ab9565b91505092915050565b60008235600160e003833603038112612b1757612b1661271a565b5b80830191505092915050565b6000602082019050612b386000830184612543565b92915050565b60008083356001602003843603038112612b5b57612b5a61271a565b5b80840192508235915067ffffffffffffffff821115612b7d57612b7c61271f565b5b602083019250600182023603831315612b9957612b98612724565b5b509250929050565b600081905092915050565b82818337600083830152505050565b6000612bc78385612ba1565b9350612bd4838584612bac565b82840190509392505050565b6000612bed828486612bbb565b91508190509392505050565b600082825260208201905092915050565b6000601f19601f8301169050919050565b6000612c278385612bf9565b9350612c34838584612bac565b612c3d83612c0a565b840190509392505050565b60006020820190508181036000830152612c63818486612c1b565b90509392505050565b6000606082019050612c816000830186612543565b612c8e6020830185612543565b612c9b604083018461257b565b949350505050565b60008115159050919050565b612cb881612ca3565b8114612cc357600080fd5b50565b600081519050612cd581612caf565b92915050565b600060208284031215612cf157612cf0612262565b5b6000612cff84828501612cc6565b91505092915050565b600082825260208201905092915050565b6000612d258385612d08565b9350612d32838584612bac565b612d3b83612c0a565b840190509392505050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b612d8081612531565b82525050565b6000612d928383612d77565b60208301905092915050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612dde612dd983612d9e565b612dab565b9050919050565b6000612df18254612dcb565b9050919050565b6000600182019050919050565b6000612e1082612d46565b612e1a8185612d51565b9350612e2583612d62565b8060005b83811015612e5d57612e3a82612de5565b612e448882612d86565b9750612e4f83612df8565b925050600181019050612e29565b5085935050505092915050565b600060c0820190508181036000830152612e85818a8c612d19565b9050612e94602083018961257b565b612ea1604083018861257b565b8181036060830152612eb38187612e05565b9050612ec2608083018661257b565b81810360a0830152612ed5818486612d19565b90509998505050505050505050565b6000612eef82612471565b9150612efa83612471565b9250828203905081811115612f1257612f116125e2565b5b92915050565b6000612f2382612471565b9150612f2e83612471565b9250828202612f3c81612471565b91508282048414831517612f5357612f526125e2565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612f9482612471565b9150612f9f83612471565b925082612faf57612fae612f5a565b5b828204905092915050565b612fc381612ca3565b82525050565b6000604082019050612fde6000830185612fba565b612feb6020830184612543565b9392505050565b600060c082019050818103600083015261300d81898b612c1b565b905061301c602083018861257b565b613029604083018761257b565b613036606083018661257b565b613043608083018561257b565b61305060a083018461257b565b98975050505050505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061309d601c8361305c565b91506130a882613067565b601c82019050919050565b6000819050919050565b6130ce6130c98261226c565b6130b3565b82525050565b60006130df82613090565b91506130eb82846130bd565b60208201915081905092915050565b600060808201905061310f60008301876124e7565b61311c60208301866126e2565b61312960408301856124e7565b61313660608301846124e7565b95945050505050565b600081519050919050565b60008190508160005260206000209050919050565b601f8211156131a0576131718161314a565b61317a8461283b565b81016020851015613189578190505b61319d6131958561283b565b830182612922565b50505b505050565b6131ae8261313f565b67ffffffffffffffff8111156131c7576131c6612797565b5b6131d182546127f5565b6131dc82828561315f565b600060209050601f83116001811461320f57600084156131fd578287015190505b61320785826129b6565b86555061326f565b601f19841661321d8661314a565b60005b8281101561324557848901518255600182019150602085019450602081019050613220565b86831015613262578489015161325e601f891682612998565b8355505b6001600288020188555050505b50505050505056fea2646970667358221220662eb1d88628e829550de8d0a59e3f320180bcc6aadd972f3e8c5146278e228a64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100415760003560e01c80630511f2ec1461004657806355b21ba214610062578063ab7d79691461007e575b600080fd5b610060600480360381019061005b91906122a2565b61009a565b005b61007c600480360381019061007791906123ae565b610432565b005b610098600480360381019061009391906124a7565b610e19565b005b60006100a4611a35565b9050600081600a0160008481526020019081526020016000209050600081600001540361010857826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100ff91906124f6565b60405180910390fd5b8060020160009054906101000a900460ff161561015c57826040517f9af72b8600000000000000000000000000000000000000000000000000000000815260040161015391906124f6565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036101c457826040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016101bb91906124f6565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff161461027e57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c000000000000000000000000000000000000000000000000000000008152600401610275929190612552565b60405180910390fd5b806000015442106102cc574281600001546040517f2458293a0000000000000000000000000000000000000000000000000000000081526004016102c392919061258a565b60405180910390fd5b600081600901905060008180549050905060005b818110156103d457600084600a016000858481548110610303576103026125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff166103c8576103c787858481548110610397576103966125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16611a62565b5b816001019150506102e0565b507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8360000181905550847f3a0205aa93b1a96da7d6405b2967f91b441383623de2d1ee3b27bfd1642b167a60405160405180910390a25050505050565b600061043c611a35565b9050600081600a016000898152602001908152602001600020600001541461049b57866040517fb9d0d58400000000000000000000000000000000000000000000000000000000815260040161049291906124f6565b60405180910390fd5b80600601548660c001356104af9190612611565b42111561050e57428660c0013582600601548860c001356104d09190612611565b6040517ffafba49500000000000000000000000000000000000000000000000000000000815260040161050593929190612645565b60405180910390fd5b8560800135421061055c574286608001356040517f2458293a00000000000000000000000000000000000000000000000000000000815260040161055392919061258a565b60405180910390fd5b85608001358660200135426105719190612611565b10156105cf57856080013586602001358760200135426105919190612611565b6040517f3d7ad6900000000000000000000000000000000000000000000000000000000081526004016105c693929190612645565b60405180910390fd5b85604001358660800135111561062657856080013586604001356040517f7532a1b000000000000000000000000000000000000000000000000000000000815260040161061d92919061258a565b60405180910390fd5b600081600a016000898152602001908152602001600020905060008087879050905060008103610682576040517fb274cdd900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60008960a001602081019061069791906126b5565b60ff16036106d1576040517ff412416600000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b808960a00160208101906106e591906126b5565b60ff16111561073f578860a001602081019061070191906126b5565b816040517fa44e438a0000000000000000000000000000000000000000000000000000000081526004016107369291906126f1565b60405180910390fd5b88806000019061074f9190612729565b8460030191826107609291906129d2565b508860a001602081019061077491906126b5565b8360020160036101000a81548160ff021916908360ff160217905550886080013583600001819055508860c001358360010181905550886020013583600401819055508860400135836005018190555085858460060191826107d79291906129d2565b50338360070160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555088606001602081019061082e9190612ace565b8360080160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508067ffffffffffffffff81111561088a57610889612797565b5b6040519080825280602002602001820160405280156108b85781602001602082028036833780820191505090505b508360090190805190602001906108d09291906121bb565b50836004015483600b018190555060005b81811015610c94576109288989838181106108ff576108fe6125b3565b5b90506020028101906109119190612afb565b60200160208101906109239190612ace565b611c68565b600084600a0160008b8b85818110610943576109426125b3565b5b90506020028101906109559190612afb565b60200160208101906109679190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060020180546109af906127f5565b905014610a29578888828181106109c9576109c86125b3565b5b90506020028101906109db9190612afb565b60200160208101906109ed9190612ace565b6040517f11298b2f000000000000000000000000000000000000000000000000000000008152600401610a209190612b23565b60405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16856009018a8a84818110610a5857610a576125b3565b5b9050602002810190610a6a9190612afb565b8060000190610a799190612b3e565b604051610a87929190612be0565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610b4257888882818110610ae457610ae36125b3565b5b9050602002810190610af69190612afb565b8060000190610b059190612b3e565b6040517f65453fd5000000000000000000000000000000000000000000000000000000008152600401610b39929190612c48565b60405180910390fd5b610b7e8a602001358b604001358c60c001358c8c86818110610b6757610b666125b3565b5b9050602002810190610b799190612afb565b611d04565b6000610baf8c8b8b85818110610b9757610b966125b3565b5b9050602002810190610ba99190612afb565b84611e82565b90508084610bbd9190612611565b9350898983818110610bd257610bd16125b3565b5b9050602002810190610be49190612afb565b6020016020810190610bf69190612ace565b866009018b8b85818110610c0d57610c0c6125b3565b5b9050602002810190610c1f9190612afb565b8060000190610c2e9190612b3e565b604051610c3c929190612be0565b908152602001604051809103902060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550816001019150506108e1565b506000610ca083612189565b905080856002016000828254610cb69190612611565b925050819055508460000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd33308487610d0b9190612611565b6040518463ffffffff1660e01b8152600401610d2993929190612c6c565b6020604051808303816000875af1158015610d48573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610d6c9190612cdb565b505050876060016020810190610d829190612ace565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff168a7fe4607f24c5b0a05d9a47b2d4cd8bdb75b50ec717c6bcf5bbc92d48b175d5ce068b8060000190610de19190612729565b8d608001358e60c0013589600901898e8e604051610e06989796959493929190612e6a565b60405180910390a4505050505050505050565b6000610e23611a35565b9050600081600a01600085815260200190815260200160002090506000816000015403610e8757836040517f018da688000000000000000000000000000000000000000000000000000000008152600401610e7e91906124f6565b60405180910390fd5b8060020160009054906101000a900460ff1615610edb57836040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610ed291906124f6565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff816000015403610f4357836040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610f3a91906124f6565b60405180910390fd5b3373ffffffffffffffffffffffffffffffffffffffff168160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1614610ffd57338160070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166040517f0e37d99c000000000000000000000000000000000000000000000000000000008152600401610ff4929190612552565b60405180910390fd5b8060000154421061104b574281600001546040517f2458293a00000000000000000000000000000000000000000000000000000000815260040161104292919061258a565b60405180910390fd5b8242106110915742836040517f3c6870c000000000000000000000000000000000000000000000000000000000815260040161108892919061258a565b60405180910390fd5b828160040154426110a29190612611565b10156110fc578281600401548260040154426110be9190612611565b6040517fca9b0f900000000000000000000000000000000000000000000000000000000081526004016110f393929190612645565b60405180910390fd5b828160050154101561114b578281600501546040517f7532a1b000000000000000000000000000000000000000000000000000000000815260040161114292919061258a565b60405180910390fd5b600080826009019050600083600b0154905060008280549050905060005b818110156118cf57600086600a01600086848154811061118c5761118b6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff166118c35760008760010154886000015461121f9190612ee4565b826000015461122e9190612f18565b90506000428b61123e9190612ee4565b836000015461124d9190612f18565b9050818111156114085760006127108784846112699190612ee4565b6112739190612f18565b61127d9190612f89565b9050828111156112ca578b8a600001546040517f48d069230000000000000000000000000000000000000000000000000000000081526004016112c192919061258a565b60405180910390fd5b808b600b0160008a88815481106112e4576112e36125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600501600082825461135b9190612611565b92505081905550808361136e9190612ee4565b8b600c0160008a8881548110611387576113866125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546113fb9190612611565b925050819055505061169a565b818110156116035760006127108783856114229190612ee4565b61142c9190612f18565b6114369190612f89565b9050808b600b0160008a8881548110611452576114516125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546114c99190612ee4565b92505081905550808b600b0160008a88815481106114ea576114e96125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546115619190612611565b92505081905550828b600c0160008a8881548110611582576115816125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546115f69190612611565b9250508190555050611699565b818a600c01600089878154811061161d5761161c6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546116919190612611565b925050819055505b5b80886116a69190612611565b97508860020160029054906101000a900460ff166118c05782600401548a600c0160008987815481106116dc576116db6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546117509190612611565b9250508190555061271086846004015461176a9190612f18565b6117749190612f89565b8a600b01600089878154811061178d5761178c6125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546118049190612ee4565b9250508190555061271086846004015461181e9190612f18565b6118289190612f89565b8a600b016000898781548110611841576118406125b3565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546118b89190612611565b925050819055505b50505b81600101915050611169565b5060006118db85612189565b9050808760020160008282546118f19190612611565b925050819055508786600001819055504286600101819055508560020160029054906101000a900460ff1661193e5760018660020160026101000a81548160ff0219169083151502179055505b8660000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff166323b872dd3330848961198c9190612611565b6040518463ffffffff1660e01b81526004016119aa93929190612c6c565b6020604051808303816000875af11580156119c9573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119ed9190612cdb565b50887ff2ded5f77c6de574fac210979efbdd01ff3071d109e50651be4e05211f6e4943898784604051611a2293929190612645565b60405180910390a2505050505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b6000611a6c611a35565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000209050600082600101548360000154611af69190612ee4565b8260000154611b059190612f18565b90508260020160029054906101000a900460ff16611b3057816004015481611b2d9190612611565b90505b600061271084600b015483611b459190612f18565b611b4f9190612f89565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254611ba59190612ee4565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206004016000828254611c009190612611565b925050819055508185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000828254611c589190612611565b9250508190555050505050505050565b6000611c72611a35565b9050600081600b0160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206000015403611d00576001826040517f2eeb3571000000000000000000000000000000000000000000000000000000008152600401611cf7929190612fc9565b60405180910390fd5b5050565b6000818060000190611d169190612b3e565b86868560400135878760600135604051602001611d399796959493929190612ff2565b60405160208183030381529060405280519060200120604051602001611d5f91906130d4565b6040516020818303038152906040528051906020012090506000600182846080016020810190611d8f91906126b5565b8560a001358660c0013560405160008152602001604052604051611db694939291906130fa565b6020604051602081039080840390855afa158015611dd8573d6000803e3d6000fd5b505050602060405103519050826020016020810190611df79190612ace565b73ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614611e7a5780836020016020810190611e3d9190612ace565b6040517f42d750dc000000000000000000000000000000000000000000000000000000008152600401611e71929190612552565b60405180910390fd5b505050505050565b600080611e8d611a35565b9050600081600a01600087815260200190815260200160002090506040518060a00160405280866040013581526020016000801b8152602001868060000190611ed69190612b3e565b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050508152602001600015158152602001866060013581525081600a016000876020016020810190611f489190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008201518160000155602082015181600101556040820151816002019081611fab91906131a5565b5060608201518160030160006101000a81548160ff02191690831515021790555060808201518160040155905050846020016020810190611fec9190612ace565b816009018581548110612002576120016125b3565b5b9060005260206000200160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060008560600135826001015483600001546120659190612ee4565b87604001356120749190612f18565b61207e9190612611565b905060006127108460040154836120959190612f18565b61209f9190612f89565b90508084600b0160008960200160208101906120bb9190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060040160008282546121079190612ee4565b925050819055508084600b0160008960200160208101906121289190612ace565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546121749190612611565b92505081905550819450505050509392505050565b600080612194611a35565b90506127108160030154846121a99190612f18565b6121b39190612f89565b915050919050565b828054828255906000526020600020908101928215612234579160200282015b828111156122335782518260006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550916020019190600101906121db565b5b5090506122419190612245565b5090565b5b8082111561225e576000816000905550600101612246565b5090565b600080fd5b600080fd5b6000819050919050565b61227f8161226c565b811461228a57600080fd5b50565b60008135905061229c81612276565b92915050565b6000602082840312156122b8576122b7612262565b5b60006122c68482850161228d565b91505092915050565b600080fd5b600060e082840312156122ea576122e96122cf565b5b81905092915050565b600080fd5b600080fd5b600080fd5b60008083601f840112612318576123176122f3565b5b8235905067ffffffffffffffff811115612335576123346122f8565b5b602083019150836020820283011115612351576123506122fd565b5b9250929050565b60008083601f84011261236e5761236d6122f3565b5b8235905067ffffffffffffffff81111561238b5761238a6122f8565b5b6020830191508360018202830111156123a7576123a66122fd565b5b9250929050565b600080600080600080608087890312156123cb576123ca612262565b5b60006123d989828a0161228d565b965050602087013567ffffffffffffffff8111156123fa576123f9612267565b5b61240689828a016122d4565b955050604087013567ffffffffffffffff81111561242757612426612267565b5b61243389828a01612302565b9450945050606087013567ffffffffffffffff81111561245657612455612267565b5b61246289828a01612358565b92509250509295509295509295565b6000819050919050565b61248481612471565b811461248f57600080fd5b50565b6000813590506124a18161247b565b92915050565b600080604083850312156124be576124bd612262565b5b60006124cc8582860161228d565b92505060206124dd85828601612492565b9150509250929050565b6124f08161226c565b82525050565b600060208201905061250b60008301846124e7565b92915050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061253c82612511565b9050919050565b61254c81612531565b82525050565b60006040820190506125676000830185612543565b6125746020830184612543565b9392505050565b61258481612471565b82525050565b600060408201905061259f600083018561257b565b6125ac602083018461257b565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600061261c82612471565b915061262783612471565b925082820190508082111561263f5761263e6125e2565b5b92915050565b600060608201905061265a600083018661257b565b612667602083018561257b565b612674604083018461257b565b949350505050565b600060ff82169050919050565b6126928161267c565b811461269d57600080fd5b50565b6000813590506126af81612689565b92915050565b6000602082840312156126cb576126ca612262565b5b60006126d9848285016126a0565b91505092915050565b6126eb8161267c565b82525050565b600060408201905061270660008301856126e2565b612713602083018461257b565b9392505050565b600080fd5b600080fd5b600080fd5b600080833560016020038436030381126127465761274561271a565b5b80840192508235915067ffffffffffffffff8211156127685761276761271f565b5b60208301925060018202360383131561278457612783612724565b5b509250929050565b600082905092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b6000600282049050600182168061280d57607f821691505b6020821081036128205761281f6127c6565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b6000600883026128887fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8261284b565b612892868361284b565b95508019841693508086168417925050509392505050565b6000819050919050565b60006128cf6128ca6128c584612471565b6128aa565b612471565b9050919050565b6000819050919050565b6128e9836128b4565b6128fd6128f5826128d6565b848454612858565b825550505050565b600090565b612912612905565b61291d8184846128e0565b505050565b5b818110156129415761293660008261290a565b600181019050612923565b5050565b601f8211156129865761295781612826565b6129608461283b565b8101602085101561296f578190505b61298361297b8561283b565b830182612922565b50505b505050565b600082821c905092915050565b60006129a96000198460080261298b565b1980831691505092915050565b60006129c28383612998565b9150826002028217905092915050565b6129dc838361278c565b67ffffffffffffffff8111156129f5576129f4612797565b5b6129ff82546127f5565b612a0a828285612945565b6000601f831160018114612a395760008415612a27578287013590505b612a3185826129b6565b865550612a99565b601f198416612a4786612826565b60005b82811015612a6f57848901358255600182019150602085019450602081019050612a4a565b86831015612a8c5784890135612a88601f891682612998565b8355505b6001600288020188555050505b50505050505050565b612aab81612531565b8114612ab657600080fd5b50565b600081359050612ac881612aa2565b92915050565b600060208284031215612ae457612ae3612262565b5b6000612af284828501612ab9565b91505092915050565b60008235600160e003833603038112612b1757612b1661271a565b5b80830191505092915050565b6000602082019050612b386000830184612543565b92915050565b60008083356001602003843603038112612b5b57612b5a61271a565b5b80840192508235915067ffffffffffffffff821115612b7d57612b7c61271f565b5b602083019250600182023603831315612b9957612b98612724565b5b509250929050565b600081905092915050565b82818337600083830152505050565b6000612bc78385612ba1565b9350612bd4838584612bac565b82840190509392505050565b6000612bed828486612bbb565b91508190509392505050565b600082825260208201905092915050565b6000601f19601f8301169050919050565b6000612c278385612bf9565b9350612c34838584612bac565b612c3d83612c0a565b840190509392505050565b60006020820190508181036000830152612c63818486612c1b565b90509392505050565b6000606082019050612c816000830186612543565b612c8e6020830185612543565b612c9b604083018461257b565b949350505050565b60008115159050919050565b612cb881612ca3565b8114612cc357600080fd5b50565b600081519050612cd581612caf565b92915050565b600060208284031215612cf157612cf0612262565b5b6000612cff84828501612cc6565b91505092915050565b600082825260208201905092915050565b6000612d258385612d08565b9350612d32838584612bac565b612d3b83612c0a565b840190509392505050565b600081549050919050565b600082825260208201905092915050565b60008190508160005260206000209050919050565b612d8081612531565b82525050565b6000612d928383612d77565b60208301905092915050565b60008160001c9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000612dde612dd983612d9e565b612dab565b9050919050565b6000612df18254612dcb565b9050919050565b6000600182019050919050565b6000612e1082612d46565b612e1a8185612d51565b9350612e2583612d62565b8060005b83811015612e5d57612e3a82612de5565b612e448882612d86565b9750612e4f83612df8565b925050600181019050612e29565b5085935050505092915050565b600060c0820190508181036000830152612e85818a8c612d19565b9050612e94602083018961257b565b612ea1604083018861257b565b8181036060830152612eb38187612e05565b9050612ec2608083018661257b565b81810360a0830152612ed5818486612d19565b90509998505050505050505050565b6000612eef82612471565b9150612efa83612471565b9250828203905081811115612f1257612f116125e2565b5b92915050565b6000612f2382612471565b9150612f2e83612471565b9250828202612f3c81612471565b91508282048414831517612f5357612f526125e2565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000612f9482612471565b9150612f9f83612471565b925082612faf57612fae612f5a565b5b828204905092915050565b612fc381612ca3565b82525050565b6000604082019050612fde6000830185612fba565b612feb6020830184612543565b9392505050565b600060c082019050818103600083015261300d81898b612c1b565b905061301c602083018861257b565b613029604083018761257b565b613036606083018661257b565b613043608083018561257b565b61305060a083018461257b565b98975050505050505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061309d601c8361305c565b91506130a882613067565b601c82019050919050565b6000819050919050565b6130ce6130c98261226c565b6130b3565b82525050565b60006130df82613090565b91506130eb82846130bd565b60208201915081905092915050565b600060808201905061310f60008301876124e7565b61311c60208301866126e2565b61312960408301856124e7565b61313660608301846124e7565b95945050505050565b600081519050919050565b60008190508160005260206000209050919050565b601f8211156131a0576131718161314a565b61317a8461283b565b81016020851015613189578190505b61319d6131958561283b565b830182612922565b50505b505050565b6131ae8261313f565b67ffffffffffffffff8111156131c7576131c6612797565b5b6131d182546127f5565b6131dc82828561315f565b600060209050601f83116001811461320f57600084156131fd578287015190505b61320785826129b6565b86555061326f565b601f19841661321d8661314a565b60005b8281101561324557848901518255600182019150602085019450602081019050613220565b86831015613262578489015161325e601f891682612998565b8355505b6001600288020188555050505b50505050505056fea2646970667358221220662eb1d88628e829550de8d0a59e3f320180bcc6aadd972f3e8c5146278e228a64736f6c63430008120033", - "devdoc": { - "errors": { - "DuplicatePublicKey(bytes)": [ - { - "params": { - "publicKey": "the duplicated public key" - } - } - ], - "ResurrectionTimeInPast(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed rewrap attempt", - "resurrectionTime": "Resurrection timestamp which has already passed" - } - } - ], - "ResurrectionTimePastMaxResurrectionTime(uint256,uint256)": [ - { - "params": { - "maxResurrectionTime": "The maximum allowed resurrection time", - "resurrectionTime": "The resurrection time defined during the sarcophagus creation or rewrap" - } - } - ], - "ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)": [ - { - "params": { - "maximumPermissibleResurrectionTime": "Resurrection timestamp which is too far in the future", - "resurrectionTime": "Resurrection timestamp which is too far in the future", - "sarcophagusMaximumRewrapInterval": "Maximum rewrap interval set for the sarcophagus" - } - } - ], - "SarcophagusAlreadyExists(bytes32)": [ - { - "params": { - "sarcoId": "Id that is already in use" - } - } - ], - "SarcophagusParametersExpired(uint256,uint256,uint256)": [ - { - "params": { - "creationDeadline": "Deadline for creation of a sarcophagus with the supplied parameters", - "creationTime": "Time when the sarcophagus parameters were created", - "currentTime": "Timestamp of the failed create attempt" - } - } - ] - }, - "events": { - "BurySarcophagus(bytes32)": { - "params": { - "sarcoId": "Id of sarcophagus that was buried" - } - }, - "CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)": { - "params": { - "arweaveTxId": "arweave tx id for the sarcophagus", - "creationTime": "Creation time as set during negotiation, not the same as blocktime at which event is emitted", - "cursedArchaeologists": "Array of addresses of cursed archaeologists", - "embalmer": "Address of embalmer", - "name": "Name of the new sarcophagus", - "recipient": "Address of recipient", - "resurrectionTime": "Resurrection time of the new sarcophagus", - "sarcoId": "Id of the new sarcophagus", - "totalDiggingFees": "Total digging fees charged to embalmer to create the sarcophagus" - } - }, - "RewrapSarcophagus(bytes32,uint256,uint256,uint256)": { - "params": { - "resurrectionTime": "New resurrection time for the sarcophagus", - "rewrapSarcophagusProtocolFees": "Total protocol fees charged to the embalmer for the rewrap", - "sarcoId": "Id of sarcophagus that was rewrapped", - "totalDiggingFees": "Total digging fees charged to the embalmer for the rewrap" - } - } - }, - "kind": "dev", - "methods": { - "burySarcophagus(bytes32)": { - "params": { - "sarcoId": "the identifier of the sarcophagus" - } - }, - "createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)": { - "params": { - "arweaveTxId": "id of tx storing the sarcophagus payload on arweave", - "sarcoId": "the identifier of the sarcophagus", - "sarcophagusParams": "params to set on sarcophagus being created", - "selectedArchaeologists": "the archaeologists the embalmer has selected to curse" - } - }, - "rewrapSarcophagus(bytes32,uint256)": { - "params": { - "resurrectionTime": "the new resurrection time", - "sarcoId": "the identifier of the sarcophagus" - } - } - }, - "version": 1 - }, - "userdoc": { - "errors": { - "ArchaeologistListContainsDuplicate(address)": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once" - } - ], - "DuplicatePublicKey(bytes)": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus" - } - ], - "NoArchaeologistsProvided()": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with no archaeologists" - } - ], - "ResurrectionTimeInPast(uint256,uint256)": [ - { - "notice": "Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed" - } - ], - "ResurrectionTimePastMaxResurrectionTime(uint256,uint256)": [ - { - "notice": "Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time" - } - ], - "ResurrectionTimeTooFarInFuture(uint256,uint256,uint256)": [ - { - "notice": "Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval" - } - ], - "SarcophagusAlreadyExists(bytes32)": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use" - } - ], - "SarcophagusParametersExpired(uint256,uint256,uint256)": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with expired parameters" - } - ], - "ThresholdCannotBeZero()": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0" - } - ], - "ThresholdGreaterThanTotalNumberOfArchaeologists(uint8,uint256)": [ - { - "notice": "Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists" - } - ] - }, - "events": { - "BurySarcophagus(bytes32)": { - "notice": "Emitted when a sarcophagus is buried" - }, - "CreateSarcophagus(bytes32,string,uint256,uint256,address,address,address[],uint256,string)": { - "notice": "Emitted when a sarcophagus is created" - }, - "RewrapSarcophagus(bytes32,uint256,uint256,uint256)": { - "notice": "Emitted when a sarcophagus is rewrapped" - } - }, - "kind": "user", - "methods": { - "burySarcophagus(bytes32)": { - "notice": "Terminates a sarcophagus by setting its resurrection time to infinity and returning locked bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried." - }, - "createSarcophagus(bytes32,(string,uint256,uint256,address,uint256,uint8,uint256),(bytes,address,uint256,uint256,uint8,bytes32,bytes32)[],string)": { - "notice": "Creates a sarcophagus with the supplied parameters and locks a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration of the sarcophagus until its resurrection time. Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters: - `publicKey` that matches the private key the archaeologist is responsible for - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap. - `creationTime` of sarcophagus - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant. - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant." - }, - "rewrapSarcophagus(bytes32,uint256)": { - "notice": "Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried." - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/deployments/baseGoerli/ThirdPartyFacet.json b/deployments/baseGoerli/ThirdPartyFacet.json deleted file mode 100644 index 4c292fb..0000000 --- a/deployments/baseGoerli/ThirdPartyFacet.json +++ /dev/null @@ -1,473 +0,0 @@ -{ - "address": "0x7C488A0a555211A6300B8BE9A1937F31d41eFA2e", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "archaeologist", - "type": "address" - } - ], - "name": "ArchaeologistNotOnSarcophagus", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "signatures", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "publicKeys", - "type": "uint256" - } - ], - "name": "DifferentNumberOfSignaturesAndPublicKeys", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "embalmerClaimWindowEnd", - "type": "uint256" - } - ], - "name": "EmbalmerClaimWindowPassed", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "paymentAddress", - "type": "address" - }, - { - "internalType": "bytes", - "name": "publicKey", - "type": "bytes" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct LibTypes.Signature", - "name": "signature", - "type": "tuple" - } - ], - "name": "InvalidAccusalSignature", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "resurrectionTime", - "type": "uint256" - } - ], - "name": "ResurrectionTimeInPast", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusAlreadyCleaned", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusCompromised", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusDoesNotExist", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "SarcophagusInactive", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "senderAddress", - "type": "address" - } - ], - "name": "SenderNotEmbalmerOrAdmin", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "embalmerClaimWindowEnd", - "type": "uint256" - } - ], - "name": "TooEarlyForAdminClean", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "currentTime", - "type": "uint256" - }, - { - "internalType": "uint256", - "name": "publishDeadline", - "type": "uint256" - } - ], - "name": "TooEarlyForClean", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "accuser", - "type": "address" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalSlashedBondDistributed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "uint256", - "name": "totalDiggingFeesDistributed", - "type": "uint256" - }, - { - "indexed": false, - "internalType": "address[]", - "name": "accusedArchAddresses", - "type": "address[]" - } - ], - "name": "AccuseArchaeologist", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "cleaner", - "type": "address" - } - ], - "name": "Clean", - "type": "event" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - }, - { - "internalType": "bytes[]", - "name": "publicKeys", - "type": "bytes[]" - }, - { - "components": [ - { - "internalType": "uint8", - "name": "v", - "type": "uint8" - }, - { - "internalType": "bytes32", - "name": "r", - "type": "bytes32" - }, - { - "internalType": "bytes32", - "name": "s", - "type": "bytes32" - } - ], - "internalType": "struct LibTypes.Signature[]", - "name": "signatures", - "type": "tuple[]" - }, - { - "internalType": "address", - "name": "paymentAddress", - "type": "address" - } - ], - "name": "accuse", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "sarcoId", - "type": "bytes32" - } - ], - "name": "clean", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - } - ], - "transactionHash": "0xbab08595e31e360013f3aa3feb5c8b3df474194d459a868b31de4d6d3ecdee49", - "receipt": { - "to": "0x4e59b44847b379578588920cA78FbF26c0B4956C", - "from": "0xb38c80e2263a060bd077ECE9b2c81a7a18ec74B5", - "contractAddress": null, - "transactionIndex": 2, - "gasUsed": "1898237", - "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x551c9840f59a6bf7926c79960603ca247490bf6fe455a69982ffb6b76d18131e", - "transactionHash": "0xbab08595e31e360013f3aa3feb5c8b3df474194d459a868b31de4d6d3ecdee49", - "logs": [], - "blockNumber": 9669972, - "cumulativeGasUsed": "2273925", - "status": 1, - "byzantium": true - }, - "args": [], - "numDeployments": 1, - "solcInputHash": "b7fcd450a9977c08df561a1e7df764e7", - "metadata": "{\"compiler\":{\"version\":\"0.8.18+commit.87f61d96\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"archaeologist\",\"type\":\"address\"}],\"name\":\"ArchaeologistNotOnSarcophagus\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"signatures\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"publicKeys\",\"type\":\"uint256\"}],\"name\":\"DifferentNumberOfSignaturesAndPublicKeys\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindowEnd\",\"type\":\"uint256\"}],\"name\":\"EmbalmerClaimWindowPassed\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"paymentAddress\",\"type\":\"address\"},{\"internalType\":\"bytes\",\"name\":\"publicKey\",\"type\":\"bytes\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct LibTypes.Signature\",\"name\":\"signature\",\"type\":\"tuple\"}],\"name\":\"InvalidAccusalSignature\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"resurrectionTime\",\"type\":\"uint256\"}],\"name\":\"ResurrectionTimeInPast\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusAlreadyCleaned\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusCompromised\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusDoesNotExist\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"SarcophagusInactive\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"senderAddress\",\"type\":\"address\"}],\"name\":\"SenderNotEmbalmerOrAdmin\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"embalmerClaimWindowEnd\",\"type\":\"uint256\"}],\"name\":\"TooEarlyForAdminClean\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"currentTime\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"publishDeadline\",\"type\":\"uint256\"}],\"name\":\"TooEarlyForClean\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"accuser\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalSlashedBondDistributed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"totalDiggingFeesDistributed\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"accusedArchAddresses\",\"type\":\"address[]\"}],\"name\":\"AccuseArchaeologist\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"cleaner\",\"type\":\"address\"}],\"name\":\"Clean\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"},{\"internalType\":\"bytes[]\",\"name\":\"publicKeys\",\"type\":\"bytes[]\"},{\"components\":[{\"internalType\":\"uint8\",\"name\":\"v\",\"type\":\"uint8\"},{\"internalType\":\"bytes32\",\"name\":\"r\",\"type\":\"bytes32\"},{\"internalType\":\"bytes32\",\"name\":\"s\",\"type\":\"bytes32\"}],\"internalType\":\"struct LibTypes.Signature[]\",\"name\":\"signatures\",\"type\":\"tuple[]\"},{\"internalType\":\"address\",\"name\":\"paymentAddress\",\"type\":\"address\"}],\"name\":\"accuse\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"sarcoId\",\"type\":\"bytes32\"}],\"name\":\"clean\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)\":[{\"params\":{\"publicKeys\":\"the number of public keys passed into the accuse call\",\"signatures\":\"the number of signatures passed into the accuse call\"}}],\"EmbalmerClaimWindowPassed(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed clean attempt\",\"embalmerClaimWindowEnd\":\"Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\"}}],\"InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))\":[{\"params\":{\"paymentAddress\":\"payment address that should have been signed\",\"publicKey\":\"publicKey that should be derived from signing key\",\"sarcoId\":\"that should have been signed\",\"signature\":\"invalid signature\"}}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed accuse attempt\",\"resurrectionTime\":\"Resurrection timestamp which has already passed\"}}],\"SarcophagusAlreadyCleaned(bytes32)\":[{\"params\":{\"sarcoId\":\"ID of sarcophagus archaeologist has attempted to publish a private key on\"}}],\"SenderNotEmbalmerOrAdmin(address)\":[{\"params\":{\"senderAddress\":\"Address of sender\"}}],\"TooEarlyForAdminClean(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed clean attempt\",\"embalmerClaimWindowEnd\":\"Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\"}}],\"TooEarlyForClean(uint256,uint256)\":[{\"params\":{\"currentTime\":\"Timestamp of the failed clean attempt\",\"publishDeadline\":\"Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\"}}]},\"kind\":\"dev\",\"methods\":{\"accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)\":{\"params\":{\"paymentAddress\":\"the address to which rewards should be sent if successful\",\"publicKeys\":\"an array of public keys corresponding to leaked private keys - order must match order of signatures\",\"sarcoId\":\"The identifier of the sarcophagus having leaked private keys\",\"signatures\":\"an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\"}},\"clean(bytes32)\":{\"params\":{\"sarcoId\":\"The identifier of the sarcophagus to clean\"}}},\"version\":1},\"userdoc\":{\"errors\":{\"DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)\":[{\"notice\":\"Emitted when accuse is called with an unequal numbers of public keys and signatures\"}],\"EmbalmerClaimWindowPassed(uint256,uint256)\":[{\"notice\":\"Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\"}],\"InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))\":[{\"notice\":\"Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\"}],\"ResurrectionTimeInPast(uint256,uint256)\":[{\"notice\":\"Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\"}],\"SarcophagusAlreadyCleaned(bytes32)\":[{\"notice\":\"Clean has been called on a sarcophagus that has already been cleaned\"}],\"SenderNotEmbalmerOrAdmin(address)\":[{\"notice\":\"Clean has been called by someone other than the admin or embalmer of the sarcophagus\"}],\"TooEarlyForAdminClean(uint256,uint256)\":[{\"notice\":\"Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\"}],\"TooEarlyForClean(uint256,uint256)\":[{\"notice\":\"Clean has been called before the deadline for archaeologists to publish private keys has passed\"}]},\"kind\":\"user\",\"methods\":{\"accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)\":{\"notice\":\"Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id and payment address generated with the leaked private keys If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus state will be updated to Accused and bonds for all remaining unaccused archaeologists will be returned\"},\"clean(bytes32)\":{\"notice\":\"If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod, their locked bonds and diggingFees may be claimed by either the embalmer or the admin embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will be able to claim remaining locked bond and diggingFees\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/facets/ThirdPartyFacet.sol\":\"ThirdPartyFacet\"},\"evmVersion\":\"paris\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":false,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\\n *\\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\\n * need to send a transaction, and thus is not required to hold Ether at all.\\n */\\ninterface IERC20Permit {\\n /**\\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\\n * given ``owner``'s signed approval.\\n *\\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\\n * ordering also apply here.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `deadline` must be a timestamp in the future.\\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\\n * over the EIP712-formatted function arguments.\\n * - the signature must use ``owner``'s current nonce (see {nonces}).\\n *\\n * For more information on the signature format, see the\\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\\n * section].\\n */\\n function permit(\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) external;\\n\\n /**\\n * @dev Returns the current nonce for `owner`. This value must be\\n * included whenever a signature is generated for {permit}.\\n *\\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\\n * prevents a signature from being used multiple times.\\n */\\n function nonces(address owner) external view returns (uint256);\\n\\n /**\\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\\n */\\n // solhint-disable-next-line func-name-mixedcase\\n function DOMAIN_SEPARATOR() external view returns (bytes32);\\n}\\n\",\"keccak256\":\"0xf41ca991f30855bf80ffd11e9347856a517b977f0a6c2d52e6421a99b7840329\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../IERC20.sol\\\";\\nimport \\\"../extensions/draft-IERC20Permit.sol\\\";\\nimport \\\"../../../utils/Address.sol\\\";\\n\\n/**\\n * @title SafeERC20\\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\\n * contract returns false). Tokens that return no value (and instead revert or\\n * throw on failure) are also supported, non-reverting calls are assumed to be\\n * successful.\\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\\n */\\nlibrary SafeERC20 {\\n using Address for address;\\n\\n function safeTransfer(\\n IERC20 token,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\\n }\\n\\n function safeTransferFrom(\\n IERC20 token,\\n address from,\\n address to,\\n uint256 value\\n ) internal {\\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\\n }\\n\\n /**\\n * @dev Deprecated. This function has issues similar to the ones found in\\n * {IERC20-approve}, and its usage is discouraged.\\n *\\n * Whenever possible, use {safeIncreaseAllowance} and\\n * {safeDecreaseAllowance} instead.\\n */\\n function safeApprove(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n // safeApprove should only be called when setting an initial allowance,\\n // or when resetting it to zero. To increase and decrease it, use\\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\\n require(\\n (value == 0) || (token.allowance(address(this), spender) == 0),\\n \\\"SafeERC20: approve from non-zero to non-zero allowance\\\"\\n );\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\\n }\\n\\n function safeIncreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n uint256 newAllowance = token.allowance(address(this), spender) + value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n\\n function safeDecreaseAllowance(\\n IERC20 token,\\n address spender,\\n uint256 value\\n ) internal {\\n unchecked {\\n uint256 oldAllowance = token.allowance(address(this), spender);\\n require(oldAllowance >= value, \\\"SafeERC20: decreased allowance below zero\\\");\\n uint256 newAllowance = oldAllowance - value;\\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\\n }\\n }\\n\\n function safePermit(\\n IERC20Permit token,\\n address owner,\\n address spender,\\n uint256 value,\\n uint256 deadline,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal {\\n uint256 nonceBefore = token.nonces(owner);\\n token.permit(owner, spender, value, deadline, v, r, s);\\n uint256 nonceAfter = token.nonces(owner);\\n require(nonceAfter == nonceBefore + 1, \\\"SafeERC20: permit did not succeed\\\");\\n }\\n\\n /**\\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\\n * on the return value: the return value is optional (but if data is returned, it must not be false).\\n * @param token The token targeted by the call.\\n * @param data The call data (encoded using abi.encode or one of its variants).\\n */\\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\\n // the target address contains contract code and also asserts for success in the low-level call.\\n\\n bytes memory returndata = address(token).functionCall(data, \\\"SafeERC20: low-level call failed\\\");\\n if (returndata.length > 0) {\\n // Return data is optional\\n require(abi.decode(returndata, (bool)), \\\"SafeERC20: ERC20 operation did not succeed\\\");\\n }\\n }\\n}\\n\",\"keccak256\":\"0x9b72f93be69ca894d8492c244259615c4a742afc8d63720dbc8bb81087d9b238\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Address.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\\n\\npragma solidity ^0.8.1;\\n\\n/**\\n * @dev Collection of functions related to the address type\\n */\\nlibrary Address {\\n /**\\n * @dev Returns true if `account` is a contract.\\n *\\n * [IMPORTANT]\\n * ====\\n * It is unsafe to assume that an address for which this function returns\\n * false is an externally-owned account (EOA) and not a contract.\\n *\\n * Among others, `isContract` will return false for the following\\n * types of addresses:\\n *\\n * - an externally-owned account\\n * - a contract in construction\\n * - an address where a contract will be created\\n * - an address where a contract lived, but was destroyed\\n * ====\\n *\\n * [IMPORTANT]\\n * ====\\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\\n *\\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\\n * constructor.\\n * ====\\n */\\n function isContract(address account) internal view returns (bool) {\\n // This method relies on extcodesize/address.code.length, which returns 0\\n // for contracts in construction, since the code is only stored at the end\\n // of the constructor execution.\\n\\n return account.code.length > 0;\\n }\\n\\n /**\\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\\n * `recipient`, forwarding all available gas and reverting on errors.\\n *\\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\\n * imposed by `transfer`, making them unable to receive funds via\\n * `transfer`. {sendValue} removes this limitation.\\n *\\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\\n *\\n * IMPORTANT: because control is transferred to `recipient`, care must be\\n * taken to not create reentrancy vulnerabilities. Consider using\\n * {ReentrancyGuard} or the\\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\\n */\\n function sendValue(address payable recipient, uint256 amount) internal {\\n require(address(this).balance >= amount, \\\"Address: insufficient balance\\\");\\n\\n (bool success, ) = recipient.call{value: amount}(\\\"\\\");\\n require(success, \\\"Address: unable to send value, recipient may have reverted\\\");\\n }\\n\\n /**\\n * @dev Performs a Solidity function call using a low level `call`. A\\n * plain `call` is an unsafe replacement for a function call: use this\\n * function instead.\\n *\\n * If `target` reverts with a revert reason, it is bubbled up by this\\n * function (like regular Solidity function calls).\\n *\\n * Returns the raw returned data. To convert to the expected return value,\\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\\n *\\n * Requirements:\\n *\\n * - `target` must be a contract.\\n * - calling `target` with `data` must not revert.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, \\\"Address: low-level call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\\n * `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, 0, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but also transferring `value` wei to `target`.\\n *\\n * Requirements:\\n *\\n * - the calling contract must have an ETH balance of at least `value`.\\n * - the called Solidity function must be `payable`.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value\\n ) internal returns (bytes memory) {\\n return functionCallWithValue(target, data, value, \\\"Address: low-level call with value failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\\n * with `errorMessage` as a fallback revert reason when `target` reverts.\\n *\\n * _Available since v3.1._\\n */\\n function functionCallWithValue(\\n address target,\\n bytes memory data,\\n uint256 value,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n require(address(this).balance >= value, \\\"Address: insufficient balance for call\\\");\\n (bool success, bytes memory returndata) = target.call{value: value}(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\\n return functionStaticCall(target, data, \\\"Address: low-level static call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a static call.\\n *\\n * _Available since v3.3._\\n */\\n function functionStaticCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.staticcall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\\n return functionDelegateCall(target, data, \\\"Address: low-level delegate call failed\\\");\\n }\\n\\n /**\\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\\n * but performing a delegate call.\\n *\\n * _Available since v3.4._\\n */\\n function functionDelegateCall(\\n address target,\\n bytes memory data,\\n string memory errorMessage\\n ) internal returns (bytes memory) {\\n (bool success, bytes memory returndata) = target.delegatecall(data);\\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\\n *\\n * _Available since v4.8._\\n */\\n function verifyCallResultFromTarget(\\n address target,\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal view returns (bytes memory) {\\n if (success) {\\n if (returndata.length == 0) {\\n // only check isContract if the call was successful and the return data is empty\\n // otherwise we already know that it was a contract\\n require(isContract(target), \\\"Address: call to non-contract\\\");\\n }\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n /**\\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\\n * revert reason or using the provided one.\\n *\\n * _Available since v4.3._\\n */\\n function verifyCallResult(\\n bool success,\\n bytes memory returndata,\\n string memory errorMessage\\n ) internal pure returns (bytes memory) {\\n if (success) {\\n return returndata;\\n } else {\\n _revert(returndata, errorMessage);\\n }\\n }\\n\\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\\n // Look for revert reason and bubble it up if present\\n if (returndata.length > 0) {\\n // The easiest way to bubble the revert reason is using memory via assembly\\n /// @solidity memory-safe-assembly\\n assembly {\\n let returndata_size := mload(returndata)\\n revert(add(32, returndata), returndata_size)\\n }\\n } else {\\n revert(errorMessage);\\n }\\n }\\n}\\n\",\"keccak256\":\"0xf96f969e24029d43d0df89e59d365f277021dac62b48e1c1e3ebe0acdd7f1ca1\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./math/Math.sol\\\";\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _SYMBOLS = \\\"0123456789abcdef\\\";\\n uint8 private constant _ADDRESS_LENGTH = 20;\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n uint256 length = Math.log10(value) + 1;\\n string memory buffer = new string(length);\\n uint256 ptr;\\n /// @solidity memory-safe-assembly\\n assembly {\\n ptr := add(buffer, add(32, length))\\n }\\n while (true) {\\n ptr--;\\n /// @solidity memory-safe-assembly\\n assembly {\\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\\n }\\n value /= 10;\\n if (value == 0) break;\\n }\\n return buffer;\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n unchecked {\\n return toHexString(value, Math.log256(value) + 1);\\n }\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\\n */\\n function toHexString(address addr) internal pure returns (string memory) {\\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\\n }\\n}\\n\",\"keccak256\":\"0xa4d1d62251f8574deb032a35fc948386a9b4de74b812d4f545a1ac120486b48a\",\"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\"},\"contracts/facets/EmbalmerFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/utils/Strings.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\n\\r\\ncontract EmbalmerFacet {\\r\\n /// @notice Emitted when a sarcophagus is created\\r\\n /// @param sarcoId Id of the new sarcophagus\\r\\n /// @param name Name of the new sarcophagus\\r\\n /// @param resurrectionTime Resurrection time of the new sarcophagus\\r\\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\\r\\n /// @param embalmer Address of embalmer\\r\\n /// @param recipient Address of recipient\\r\\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\\r\\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\\r\\n /// @param arweaveTxId arweave tx id for the sarcophagus\\r\\n event CreateSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n string name,\\r\\n uint256 resurrectionTime,\\r\\n uint256 creationTime,\\r\\n address indexed embalmer,\\r\\n address indexed recipient,\\r\\n address[] cursedArchaeologists,\\r\\n uint256 totalDiggingFees,\\r\\n string arweaveTxId\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is rewrapped\\r\\n /// @param sarcoId Id of sarcophagus that was rewrapped\\r\\n /// @param resurrectionTime New resurrection time for the sarcophagus\\r\\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\\r\\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\\r\\n event RewrapSarcophagus(\\r\\n bytes32 indexed sarcoId,\\r\\n uint256 resurrectionTime,\\r\\n uint256 totalDiggingFees,\\r\\n uint256 rewrapSarcophagusProtocolFees\\r\\n );\\r\\n\\r\\n /// @notice Emitted when a sarcophagus is buried\\r\\n /// @param sarcoId Id of sarcophagus that was buried\\r\\n event BurySarcophagus(bytes32 indexed sarcoId);\\r\\n\\r\\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\\r\\n struct SarcophagusParams {\\r\\n string name;\\r\\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\\r\\n uint256 maximumRewrapInterval;\\r\\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\\r\\n uint256 maximumResurrectionTime;\\r\\n address recipientAddress;\\r\\n uint256 resurrectionTime;\\r\\n uint8 threshold;\\r\\n uint256 creationTime;\\r\\n }\\r\\n\\r\\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\\r\\n struct CurseParams {\\r\\n bytes publicKey;\\r\\n address archAddress;\\r\\n uint256 diggingFeePerSecond;\\r\\n uint256 curseFee;\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\\r\\n /// @param sarcoId Id that is already in use\\r\\n error SarcophagusAlreadyExists(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\\r\\n /// @param currentTime Timestamp of the failed create attempt\\r\\n /// @param creationTime Time when the sarcophagus parameters were created\\r\\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\\r\\n error SarcophagusParametersExpired(\\r\\n uint256 currentTime,\\r\\n uint256 creationTime,\\r\\n uint256 creationDeadline\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\\r\\n error NoArchaeologistsProvided();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\\r\\n error ThresholdCannotBeZero();\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\\r\\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n uint8 threshold,\\r\\n uint256 totalNumberOfArchaeologists\\r\\n );\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\\r\\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\\r\\n /// @param currentTime Timestamp of the failed rewrap attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\\r\\n /// @param publicKey the duplicated public key\\r\\n error DuplicatePublicKey(bytes publicKey);\\r\\n\\r\\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\\r\\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\\r\\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\\r\\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\\r\\n error ResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\\r\\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\\r\\n /// @param maxResurrectionTime The maximum allowed resurrection time\\r\\n error ResurrectionTimePastMaxResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 maxResurrectionTime\\r\\n );\\r\\n\\r\\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\\r\\n\\r\\n error NewResurrectionTimeIsZero();\\r\\n\\r\\n error NewResurrectionTimeTooFarInFuture(\\r\\n uint256 resurrectionTime,\\r\\n uint256 sarcophagusMaximumRewrapInterval,\\r\\n uint256 maximumPermissibleResurrectionTime\\r\\n );\\r\\n\\r\\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n uint256 resurrectionTime,\\r\\n uint256 previousResurrectionTime\\r\\n );\\r\\n\\r\\n /// @notice Creates a sarcophagus with the supplied parameters and locks\\r\\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\\r\\n /// of the sarcophagus until its resurrection time.\\r\\n ///\\r\\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\\r\\n /// - `publicKey` that matches the private key the archaeologist is responsible for\\r\\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\\r\\n /// - `creationTime` of sarcophagus\\r\\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\\r\\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\\r\\n ///\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param sarcophagusParams params to set on sarcophagus being created\\r\\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\\r\\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\\r\\n function createSarcophagus(\\r\\n bytes32 sarcoId,\\r\\n SarcophagusParams calldata sarcophagusParams,\\r\\n CurseParams[] calldata selectedArchaeologists,\\r\\n string calldata arweaveTxId\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n // Confirm that sarcophagus with supplied id doesn't already exist\\r\\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\\r\\n revert SarcophagusAlreadyExists(sarcoId);\\r\\n }\\r\\n\\r\\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\\r\\n // off by its cursed archaeologists.\\r\\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\\r\\n revert SarcophagusParametersExpired(\\r\\n block.timestamp,\\r\\n sarcophagusParams.creationTime,\\r\\n sarcophagusParams.creationTime + s.expirationThreshold\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\\r\\n if (\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\\r\\n sarcophagusParams.resurrectionTime\\r\\n ) {\\r\\n revert ResurrectionTimeTooFarInFuture(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagusParams.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the resurrection time is less than the max resurrection time\\r\\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // track total digging fees due upon creation of sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n {\\r\\n uint256 nSelectedArchs = selectedArchaeologists.length;\\r\\n // Validate archaeologist and threshold lengths\\r\\n if (nSelectedArchs == 0) {\\r\\n revert NoArchaeologistsProvided();\\r\\n }\\r\\n\\r\\n if (sarcophagusParams.threshold == 0) {\\r\\n revert ThresholdCannotBeZero();\\r\\n }\\r\\n\\r\\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\\r\\n // used to distribute keyshares among archaeologists\\r\\n if (sarcophagusParams.threshold > nSelectedArchs) {\\r\\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\\r\\n sarcophagusParams.threshold,\\r\\n nSelectedArchs\\r\\n );\\r\\n }\\r\\n\\r\\n // create the sarcophagus\\r\\n sarcophagus.name = sarcophagusParams.name;\\r\\n sarcophagus.threshold = sarcophagusParams.threshold;\\r\\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\\r\\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\\r\\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\\r\\n sarcophagus.arweaveTxId = arweaveTxId;\\r\\n sarcophagus.embalmerAddress = msg.sender;\\r\\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\\r\\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\\r\\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\\r\\n\\r\\n for (uint256 i; i < nSelectedArchs; ) {\\r\\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\\r\\n\\r\\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\\r\\n .publicKey\\r\\n .length != 0\\r\\n ) {\\r\\n revert ArchaeologistListContainsDuplicate(\\r\\n selectedArchaeologists[i].archAddress\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm archaeologist is not re-using a key pair\\r\\n if (\\r\\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\\r\\n address(0)\\r\\n ) {\\r\\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\\r\\n }\\r\\n\\r\\n LibUtils.verifyArchaeologistSignature(\\r\\n sarcophagusParams.maximumRewrapInterval,\\r\\n sarcophagusParams.maximumResurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n selectedArchaeologists[i]\\r\\n );\\r\\n\\r\\n // Curse the archaeologist on this sarcophagus\\r\\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\\r\\n sarcoId,\\r\\n selectedArchaeologists[i],\\r\\n i\\r\\n );\\r\\n\\r\\n totalDiggingFees += diggingFeesDue;\\r\\n\\r\\n // \\\"Consume\\\" this public key so it cannot be reused in the future\\r\\n s.publicKeyToArchaeologistAddress[\\r\\n selectedArchaeologists[i].publicKey\\r\\n ] = selectedArchaeologists[i].archAddress;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n s.totalProtocolFees += protocolFees;\\r\\n s.sarcoToken.transferFrom(\\r\\n msg.sender,\\r\\n address(this),\\r\\n totalDiggingFees + protocolFees\\r\\n );\\r\\n }\\r\\n emit CreateSarcophagus(\\r\\n sarcoId,\\r\\n sarcophagusParams.name,\\r\\n sarcophagusParams.resurrectionTime,\\r\\n sarcophagusParams.creationTime,\\r\\n msg.sender,\\r\\n sarcophagusParams.recipientAddress,\\r\\n sarcophagus.cursedArchaeologistAddresses,\\r\\n totalDiggingFees,\\r\\n arweaveTxId\\r\\n );\\r\\n }\\r\\n\\r\\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n /// @param resurrectionTime the new resurrection time\\r\\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n\\r\\n // Confirm resurrection time has not yet passed\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time is in future\\r\\n if (block.timestamp >= resurrectionTime) {\\r\\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\\r\\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\\r\\n revert NewResurrectionTimeTooFarInFuture(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumRewrapInterval,\\r\\n block.timestamp + sarcophagus.maximumRewrapInterval\\r\\n );\\r\\n }\\r\\n\\r\\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\\r\\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\\r\\n revert ResurrectionTimePastMaxResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.maximumResurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\\r\\n uint256 totalDiggingFees;\\r\\n\\r\\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\\r\\n\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n // Previous digging fees calculation ignores curseFee\\r\\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\\r\\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\\r\\n (resurrectionTime - block.timestamp);\\r\\n\\r\\n // If the new digging fees are greater than the previous digging fees, we need to\\r\\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\\r\\n if (newDiggingFees > prevDiggingFees) {\\r\\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\\r\\n if (cursedBondIncrease > prevDiggingFees) {\\r\\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\\r\\n resurrectionTime,\\r\\n sarcophagus.resurrectionTime\\r\\n );\\r\\n }\\r\\n\\r\\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond += cursedBondIncrease;\\r\\n\\r\\n // Rewards are now previous digging fees - difference\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\\r\\n } else if (newDiggingFees < prevDiggingFees) {\\r\\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\\r\\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\\r\\n cursedBondPercentage) / 10000;\\r\\n\\r\\n // Decrease archaeologist's cursed bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .cursedBond -= cursedBondDecrease;\\r\\n\\r\\n // Increase archaeologist's free bond by the difference\\r\\n s\\r\\n .archaeologistProfiles[archaeologistAddresses[i]]\\r\\n .freeBond += cursedBondDecrease;\\r\\n\\r\\n // Rewards are equal to the previous digging fees\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n } else {\\r\\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\\r\\n }\\r\\n\\r\\n // Add digging fees due for the new interval\\r\\n totalDiggingFees += newDiggingFees;\\r\\n\\r\\n // If sarcophagus has not been rewrapped yet, pay out the curseFee and unlock the curseFee bond\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n // Pay archaeologists the curse fee to their rewards\\r\\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\\r\\n\\r\\n // Unlock the curseFee cursed bond by debiting the cursed bond and crediting free bond\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].cursedBond -= ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n s.archaeologistProfiles[archaeologistAddresses[i]].freeBond += ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\\r\\n }\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\\r\\n\\r\\n // Add the protocol fee to the total protocol fees in storage\\r\\n s.totalProtocolFees += protocolFees;\\r\\n\\r\\n // Update the sarcophagus resurrectionTime and previousRewrapTime\\r\\n sarcophagus.resurrectionTime = resurrectionTime;\\r\\n sarcophagus.previousRewrapTime = block.timestamp;\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n sarcophagus.isRewrapped = true;\\r\\n }\\r\\n\\r\\n // Transfer the new digging fees and protocol fees from embalmer to contract\\r\\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\\r\\n\\r\\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\\r\\n }\\r\\n\\r\\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\\r\\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\\r\\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\\r\\n /// @param sarcoId the identifier of the sarcophagus\\r\\n function burySarcophagus(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer\\r\\n if (sarcophagus.embalmerAddress != msg.sender) {\\r\\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\\r\\n }\\r\\n // Confirm that the current resurrection time is in the future\\r\\n if (block.timestamp >= sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\\r\\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\\r\\n uint256 nArchAddresses = archaeologistAddresses.length;\\r\\n for (uint256 i; i < nArchAddresses; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[archaeologistAddresses[i]];\\r\\n\\r\\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\\r\\n if (!cursedArchaeologist.isAccused) {\\r\\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Set resurrection time to infinity\\r\\n sarcophagus.resurrectionTime = type(uint256).max;\\r\\n\\r\\n emit BurySarcophagus(sarcoId);\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x9b019288bbff9433124bcccab5f8099b19e9f3bf1a9588221c30b4c5da1106dc\",\"license\":\"Unlicense\"},\"contracts/facets/ThirdPartyFacet.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport {LibDiamond} from \\\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\\\";\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport {LibBonds} from \\\"../libraries/LibBonds.sol\\\";\\r\\nimport {LibUtils} from \\\"../libraries/LibUtils.sol\\\";\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\ncontract ThirdPartyFacet {\\r\\n event AccuseArchaeologist(\\r\\n bytes32 indexed sarcoId,\\r\\n address indexed accuser,\\r\\n uint256 totalSlashedBondDistributed,\\r\\n uint256 totalDiggingFeesDistributed,\\r\\n address[] accusedArchAddresses\\r\\n );\\r\\n\\r\\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\\r\\n\\r\\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\\r\\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\\r\\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\\r\\n\\r\\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\\r\\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\\r\\n\\r\\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\\r\\n /// @param senderAddress Address of sender\\r\\n error SenderNotEmbalmerOrAdmin(address senderAddress);\\r\\n\\r\\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\\r\\n /// @param currentTime Timestamp of the failed clean attempt\\r\\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\\r\\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\\r\\n\\r\\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\\r\\n /// @param currentTime Timestamp of the failed accuse attempt\\r\\n /// @param resurrectionTime Resurrection timestamp which has already passed\\r\\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\\r\\n /// @param signatures the number of signatures passed into the accuse call\\r\\n /// @param publicKeys the number of public keys passed into the accuse call\\r\\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\\r\\n\\r\\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\\r\\n /// @param sarcoId that should have been signed\\r\\n /// @param paymentAddress payment address that should have been signed\\r\\n /// @param publicKey publicKey that should be derived from signing key\\r\\n /// @param signature invalid signature\\r\\n error InvalidAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes publicKey,\\r\\n LibTypes.Signature signature\\r\\n );\\r\\n\\r\\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\\r\\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\\r\\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\\r\\n /// be able to claim remaining locked bond and diggingFees\\r\\n /// @param sarcoId The identifier of the sarcophagus to clean\\r\\n function clean(bytes32 sarcoId) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm the sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm tx sender is embalmer or admin\\r\\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\\r\\n revert SenderNotEmbalmerOrAdmin(msg.sender);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not already been cleaned\\r\\n if (sarcophagus.isCleaned) {\\r\\n revert SarcophagusAlreadyCleaned(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm that the resurrectionTime + gracePeriod have passed\\r\\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\\r\\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\\r\\n }\\r\\n\\r\\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\\r\\n if (\\r\\n msg.sender == sarcophagus.embalmerAddress &&\\r\\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert EmbalmerClaimWindowPassed(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // if sender is admin, confirm embalmerClaimWindow has passed\\r\\n if (\\r\\n msg.sender == LibDiamond.contractOwner() &&\\r\\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n ) {\\r\\n revert TooEarlyForAdminClean(\\r\\n block.timestamp,\\r\\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\\r\\n );\\r\\n }\\r\\n\\r\\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\\r\\n uint256 totalDiggingFeesAndLockedBonds;\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\\r\\n\\r\\n // Punish archaeologists that failed to publish their private key in time\\r\\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\\r\\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeesDue += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\\r\\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\\r\\n\\r\\n // slash the archaeologist's locked bond for the sarcophagus\\r\\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\\r\\n // this to the contract's protocol fees\\r\\n if (msg.sender == sarcophagus.embalmerAddress) {\\r\\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\\r\\n } else {\\r\\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\\r\\n }\\r\\n\\r\\n sarcophagus.isCleaned = true;\\r\\n emit Clean(sarcoId, msg.sender);\\r\\n }\\r\\n\\r\\n /**\\r\\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\\r\\n * and payment address generated with the leaked private keys\\r\\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\\r\\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\\r\\n *\\r\\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\\r\\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\\r\\n * returned\\r\\n *\\r\\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\\r\\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\\r\\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\\r\\n * @param paymentAddress the address to which rewards should be sent if successful\\r\\n */\\r\\n function accuse(\\r\\n bytes32 sarcoId,\\r\\n bytes[] calldata publicKeys,\\r\\n LibTypes.Signature[] calldata signatures,\\r\\n address paymentAddress\\r\\n ) external {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n // Confirm sarcophagus exists\\r\\n if (sarcophagus.resurrectionTime == 0) {\\r\\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\\r\\n }\\r\\n\\r\\n // verify that current time is not past resurrection time\\r\\n if (block.timestamp > sarcophagus.resurrectionTime) {\\r\\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus has not been compromised\\r\\n if (sarcophagus.isCompromised) {\\r\\n revert LibErrors.SarcophagusCompromised(sarcoId);\\r\\n }\\r\\n\\r\\n // Confirm the sarcophagus is not buried\\r\\n if (sarcophagus.resurrectionTime == type(uint256).max) {\\r\\n revert LibErrors.SarcophagusInactive(sarcoId);\\r\\n }\\r\\n\\r\\n uint256 nSigs = signatures.length;\\r\\n\\r\\n if (nSigs != publicKeys.length) {\\r\\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\\r\\n }\\r\\n\\r\\n address[] memory accusedArchAddresses = new address[](nSigs);\\r\\n\\r\\n // track the combined locked bond across all archaeologists being accused in this call\\r\\n uint256 totalCursedBond;\\r\\n uint256 accusalCount;\\r\\n for (uint256 i; i < nSigs; ) {\\r\\n if (\\r\\n !LibUtils.verifyAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n )\\r\\n ) {\\r\\n revert InvalidAccusalSignature(\\r\\n sarcoId,\\r\\n paymentAddress,\\r\\n publicKeys[i],\\r\\n signatures[i]\\r\\n );\\r\\n }\\r\\n\\r\\n // look up the archaeologist responsible for the publicKey\\r\\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\\r\\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\\r\\n .cursedArchaeologists[accusedArchaeologistAddress];\\r\\n\\r\\n // verify the accused archaeologist is cursed on the sarcophagus\\r\\n if (accusedArchaeologist.publicKey.length == 0) {\\r\\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\\r\\n }\\r\\n\\r\\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\\r\\n if (accusedArchaeologist.isAccused) {\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n continue;\\r\\n }\\r\\n\\r\\n // mark the archaeologist on the sarcophagus as having been accused\\r\\n accusedArchaeologist.isAccused = true;\\r\\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\\r\\n\\r\\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\\r\\n sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n // If the sarcophagus has not been rewrapped, also slash the curse fee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\\r\\n }\\r\\n\\r\\n totalCursedBond += cursedBondDue;\\r\\n\\r\\n // Slash the offending archaeologists bond\\r\\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n\\r\\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\\r\\n if (accusalCount == 0) {\\r\\n return;\\r\\n }\\r\\n\\r\\n {\\r\\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\\r\\n\\r\\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\\r\\n if (accusalCount >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n } else {\\r\\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\\r\\n // check if total number of historical accusals on sarcophagus is greater than threshold\\r\\n uint256 totalAccusals;\\r\\n\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n if (\\r\\n sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n ++totalAccusals;\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\\r\\n if (totalAccusals >= sarcophagus.threshold) {\\r\\n sarcophagus.isCompromised = true;\\r\\n }\\r\\n }\\r\\n\\r\\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\\r\\n // be returned to the remaining well behaved archaeologists\\r\\n if (sarcophagus.isCompromised) {\\r\\n // iterate through all archaeologist addresses on the sarcophagus\\r\\n for (uint256 i; i < nCursedArchs; ) {\\r\\n // if the archaeologist has never been accused, release their locked bond back to them\\r\\n if (\\r\\n !sarcophagus\\r\\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\\r\\n .isAccused\\r\\n ) {\\r\\n LibBonds.freeArchaeologist(\\r\\n sarcoId,\\r\\n sarcophagus.cursedArchaeologistAddresses[i]\\r\\n );\\r\\n }\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n }\\r\\n }\\r\\n\\r\\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\\r\\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\\r\\n // transfer the cursed half, plus the current digging fees, to the embalmer\\r\\n s.sarcoToken.transfer(\\r\\n sarcophagus.embalmerAddress,\\r\\n totalDiggingFees + halfTotalCursedBond\\r\\n );\\r\\n\\r\\n // transfer the other half of the cursed bond to the transaction caller\\r\\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\\r\\n\\r\\n emit AccuseArchaeologist(\\r\\n sarcoId,\\r\\n msg.sender,\\r\\n totalCursedBond,\\r\\n totalDiggingFees,\\r\\n accusedArchAddresses\\r\\n );\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0xc4a28de898fe399da500fae3d4cd8ff0a300f3dedbc2548d8c54940fd76a7ea1\",\"license\":\"Unlicense\"},\"contracts/libraries/LibBonds.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"./LibErrors.sol\\\";\\r\\n\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\nlibrary LibBonds {\\r\\n /// @notice Bonds the archaeologist to a sarcophagus.\\r\\n /// This does the following:\\r\\n /// - adds the archaeologist's curse params and address to the sarcophagus\\r\\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\\r\\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\\r\\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\\r\\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\\r\\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\\r\\n ///\\r\\n /// @return the amount of digging fees due the embalmer for this curse\\r\\n function curseArchaeologist(\\r\\n bytes32 sarcoId,\\r\\n EmbalmerFacet.CurseParams calldata archaeologist,\\r\\n uint256 index\\r\\n ) internal returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\\r\\n publicKey: archaeologist.publicKey,\\r\\n privateKey: 0,\\r\\n isAccused: false,\\r\\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\\r\\n curseFee: archaeologist.curseFee\\r\\n });\\r\\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\\r\\n\\r\\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\\r\\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\\r\\n + archaeologist.curseFee;\\r\\n\\r\\n // Use cursed bond percentage to determine how much bond to lock up\\r\\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\\r\\n\\r\\n // Transfer bond to curse from free bond to cursed bond\\r\\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\\r\\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\\r\\n\\r\\n return diggingFeesDue;\\r\\n }\\r\\n\\r\\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\\r\\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\\r\\n /// @param archaeologistAddress the address of the archaeologist to free\\r\\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\\r\\n\\r\\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\\r\\n .sarcophagi[sarcoId]\\r\\n .cursedArchaeologists[archaeologistAddress];\\r\\n\\r\\n // Calculate the digging fees to be paid since the last rewrap (or creation)\\r\\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\\r\\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\\r\\n\\r\\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\\r\\n if (!sarcophagus.isRewrapped) {\\r\\n diggingFeeAmount += cursedArchaeologist.curseFee;\\r\\n }\\r\\n\\r\\n uint256 cursedBondAmount = (diggingFeeAmount * sarcophagus.cursedBondPercentage) / 10000;\\r\\n\\r\\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\\r\\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\\r\\n\\r\\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x8c0a7c621ffa042eee7a312fb919102bf8af87daf434bfc07819acb5b3c06dd9\",\"license\":\"Unlicense\"},\"contracts/libraries/LibErrors.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title A collection of Errors\\r\\n * @notice This library defines all of the Errors that the Sarcophagus system\\r\\n * uses.\\r\\n */\\r\\nlibrary LibErrors {\\r\\n error ArchaeologistNotOnSarcophagus(address archaeologist);\\r\\n\\r\\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\\r\\n\\r\\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\\r\\n\\r\\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\\r\\n\\r\\n error SarcophagusDoesNotExist(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusInactive(bytes32 sarcoId);\\r\\n\\r\\n error SarcophagusCompromised(bytes32 sarcoId);\\r\\n\\r\\n error SenderNotEmbalmer(address sender, address embalmer);\\r\\n\\r\\n error InvalidSignature(\\r\\n // address recovered from signature via ecrecover\\r\\n address recoveredAddress,\\r\\n // address we expected to have signed the data\\r\\n address expectedAddress\\r\\n );\\r\\n}\\r\\n\",\"keccak256\":\"0xa0a8e8a9d339d070e5bf21d4b0462e5eb947a60acec58d0cb1013006b6d73cac\",\"license\":\"Unlicense\"},\"contracts/libraries/LibTypes.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\n/**\\r\\n * @title Types shared across facets for the Sarcophagus diamond\\r\\n */\\r\\nlibrary LibTypes {\\r\\n struct Sarcophagus {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 resurrectionTime;\\r\\n uint256 previousRewrapTime;\\r\\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\\r\\n bool isCompromised;\\r\\n bool isCleaned;\\r\\n bool isRewrapped;\\r\\n uint8 threshold;\\r\\n string name;\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string arweaveTxId;\\r\\n address embalmerAddress;\\r\\n address recipientAddress;\\r\\n address[] cursedArchaeologistAddresses;\\r\\n mapping(address => CursedArchaeologist) cursedArchaeologists;\\r\\n uint256 cursedBondPercentage;\\r\\n }\\r\\n\\r\\n struct CursedArchaeologist {\\r\\n uint256 diggingFeePerSecond;\\r\\n // Also used for publish checks -- has not published if 0\\r\\n bytes32 privateKey;\\r\\n // Also used for curse checks -- is not bonded if length is 0\\r\\n bytes publicKey;\\r\\n bool isAccused;\\r\\n uint256 curseFee;\\r\\n }\\r\\n\\r\\n struct Signature {\\r\\n uint8 v;\\r\\n bytes32 r;\\r\\n bytes32 s;\\r\\n }\\r\\n\\r\\n struct ArchaeologistProfile {\\r\\n // Also used for existence checks -- does not exist if 0\\r\\n uint256 maximumRewrapInterval;\\r\\n uint256 maximumResurrectionTime;\\r\\n string peerId;\\r\\n uint256 minimumDiggingFeePerSecond;\\r\\n uint256 freeBond;\\r\\n uint256 cursedBond;\\r\\n uint256 curseFee;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x096d9660852c5179b16d71abe3a818282db9e980fdc431efa77bd92577d60fb8\",\"license\":\"Unlicense\"},\"contracts/libraries/LibUtils.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"../storage/LibAppStorage.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\nimport {LibErrors} from \\\"../libraries/LibErrors.sol\\\";\\r\\nimport \\\"../facets/ThirdPartyFacet.sol\\\";\\r\\nimport \\\"./LibTypes.sol\\\";\\r\\nimport \\\"../facets/EmbalmerFacet.sol\\\";\\r\\n\\r\\n/**\\r\\n * @title Utility functions used within the Sarcophagus system\\r\\n * @notice This library implements various functions that are used throughout\\r\\n * Sarcophagus, mainly to DRY up the codebase\\r\\n * @dev these functions are all stateless, public, pure/view\\r\\n */\\r\\nlibrary LibUtils {\\r\\n /**\\r\\n * @notice The archaeologist needs to sign off on two pieces of data\\r\\n * to guarantee their unrwap will be successful\\r\\n *\\r\\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\\r\\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\\r\\n * @param curseParams parameters of curse signed by archaeologist\\r\\n */\\r\\n function verifyArchaeologistSignature(\\r\\n uint256 agreedMaximumRewrapInterval,\\r\\n uint256 maximumResurrectionTime,\\r\\n uint256 timestamp,\\r\\n EmbalmerFacet.CurseParams calldata curseParams\\r\\n ) internal pure {\\r\\n // Hash the hash of the data payload\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(\\r\\n abi.encode(\\r\\n curseParams.publicKey,\\r\\n agreedMaximumRewrapInterval,\\r\\n maximumResurrectionTime,\\r\\n curseParams.diggingFeePerSecond,\\r\\n timestamp,\\r\\n curseParams.curseFee\\r\\n )\\r\\n )\\r\\n )\\r\\n );\\r\\n\\r\\n // Generate the address from the signature.\\r\\n // ecrecover should always return a valid address.\\r\\n address recoveredAddress = ecrecover(\\r\\n messageHash,\\r\\n curseParams.v,\\r\\n curseParams.r,\\r\\n curseParams.s\\r\\n );\\r\\n\\r\\n if (recoveredAddress != curseParams.archAddress) {\\r\\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Verifies that a signature and public key were created from the same private key\\r\\n /// @param sarcoId the sarcoId that was signed\\r\\n /// @param paymentAddress the payment address that was signed\\r\\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\\r\\n /// @param signature signature on the sarco id and payment address\\r\\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\\r\\n function verifyAccusalSignature(\\r\\n bytes32 sarcoId,\\r\\n address paymentAddress,\\r\\n bytes calldata publicKey,\\r\\n LibTypes.Signature calldata signature\\r\\n ) internal pure returns (bool) {\\r\\n // removes the 0x04 prefix from an uncompressed public key\\r\\n uint256 pubKeyLength = publicKey.length;\\r\\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\\r\\n for (uint256 i = 1; i < pubKeyLength; ) {\\r\\n truncatedPublicKey[i - 1] = publicKey[i];\\r\\n unchecked {\\r\\n ++i;\\r\\n }\\r\\n }\\r\\n bytes32 messageHash = keccak256(\\r\\n abi.encodePacked(\\r\\n \\\"\\\\x19Ethereum Signed Message:\\\\n32\\\",\\r\\n keccak256(abi.encode(sarcoId, paymentAddress))\\r\\n )\\r\\n );\\r\\n // Use ecrecover to get the address that signed the message\\r\\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\\r\\n\\r\\n address publicKeyAddress = address(\\r\\n uint160(\\r\\n uint256(keccak256(truncatedPublicKey)) &\\r\\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\\r\\n )\\r\\n );\\r\\n\\r\\n return signingAddress == publicKeyAddress;\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile exists and\\r\\n /// reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check existence of\\r\\n function revertIfArchProfileExists(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\\r\\n ///\\r\\n /// @param archaeologist the archaeologist address to check lack of existence of\\r\\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\\r\\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\\r\\n }\\r\\n }\\r\\n\\r\\n /// @notice Calculates the protocol fees to be taken from the embalmer.\\r\\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\\r\\n /// @return The protocol fees amount\\r\\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\\r\\n AppStorage storage s = LibAppStorage.getAppStorage();\\r\\n\\r\\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x4e6fa08e9f931ba0ef0c2c5b0938be70124d00b94c86a3a4ae303472cd5c8fb8\",\"license\":\"Unlicense\"},\"contracts/storage/LibAppStorage.sol\":{\"content\":\"// SPDX-License-Identifier: Unlicense\\r\\npragma solidity 0.8.18;\\r\\n\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/IERC20.sol\\\";\\r\\nimport \\\"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\\\";\\r\\nimport \\\"../libraries/LibTypes.sol\\\";\\r\\n\\r\\n/**\\r\\n * Global diamond storage struct to be shared across facets\\r\\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\\r\\n */\\r\\nstruct AppStorage {\\r\\n // SARCO token contract\\r\\n IERC20 sarcoToken;\\r\\n // The Admin address allowed to call Admin Facet functions\\r\\n address admin;\\r\\n // total protocol fees available to be withdrawn by the admin\\r\\n uint256 totalProtocolFees;\\r\\n /**\\r\\n * Protocol level admin configurations\\r\\n */\\r\\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\\r\\n uint256 protocolFeeBasePercentage;\\r\\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\\r\\n uint256 cursedBondPercentage;\\r\\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\\r\\n uint256 gracePeriod;\\r\\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\\r\\n uint256 expirationThreshold;\\r\\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\\r\\n uint256 embalmerClaimWindow;\\r\\n // registered archaeologist addresses\\r\\n address[] archaeologistProfileAddresses;\\r\\n // public key => archaeologist address\\r\\n mapping(bytes => address) publicKeyToArchaeologistAddress;\\r\\n // sarcophagus id => sarcophagus object\\r\\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\\r\\n // archaeologist address => profile\\r\\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\\r\\n // current balance of rewards available for the archaeologist to withdraw\\r\\n mapping(address => uint256) archaeologistRewards;\\r\\n}\\r\\n\\r\\nlibrary LibAppStorage {\\r\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"sarcophagus.storage.1\\\");\\r\\n\\r\\n function getAppStorage() internal pure returns (AppStorage storage s) {\\r\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\r\\n assembly {\\r\\n s.slot := position\\r\\n }\\r\\n }\\r\\n}\\r\\n\",\"keccak256\":\"0x66f7100a037fcc417379e68914a8831d867f3701c39419f8f04a3af27008438c\",\"license\":\"Unlicense\"},\"hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\n\\ninterface IDiamondCut {\\n enum FacetCutAction {Add, Replace, Remove}\\n // Add=0, Replace=1, Remove=2\\n\\n struct FacetCut {\\n address facetAddress;\\n FacetCutAction action;\\n bytes4[] functionSelectors;\\n }\\n\\n /// @notice Add/replace/remove any number of functions and optionally execute\\n /// a function with delegatecall\\n /// @param _diamondCut Contains the facet addresses and function selectors\\n /// @param _init The address of the contract or facet to execute _calldata\\n /// @param _calldata A function call, including function selector and arguments\\n /// _calldata is executed with delegatecall on _init\\n function diamondCut(\\n FacetCut[] calldata _diamondCut,\\n address _init,\\n bytes calldata _calldata\\n ) external;\\n\\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\\n}\\n\",\"keccak256\":\"0xc00c16bfa30a3fa5f3dc684f7f8ba62c259962b25f647d9588739458989717fc\",\"license\":\"MIT\"},\"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity ^0.8.0;\\n\\n/******************************************************************************\\\\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\\n/******************************************************************************/\\nimport { IDiamondCut } from \\\"../interfaces/IDiamondCut.sol\\\";\\n\\nlibrary LibDiamond {\\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\\\"diamond.standard.diamond.storage\\\");\\n\\n struct FacetAddressAndPosition {\\n address facetAddress;\\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\\n }\\n\\n struct FacetFunctionSelectors {\\n bytes4[] functionSelectors;\\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\\n }\\n\\n struct DiamondStorage {\\n // maps function selector to the facet address and\\n // the position of the selector in the facetFunctionSelectors.selectors array\\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\\n // maps facet addresses to function selectors\\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\\n // facet addresses\\n address[] facetAddresses;\\n // Used to query if a contract implements an interface.\\n // Used to implement ERC-165.\\n mapping(bytes4 => bool) supportedInterfaces;\\n // owner of the contract\\n address contractOwner;\\n }\\n\\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\\n bytes32 position = DIAMOND_STORAGE_POSITION;\\n assembly {\\n ds.slot := position\\n }\\n }\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n function setContractOwner(address _newOwner) internal {\\n DiamondStorage storage ds = diamondStorage();\\n address previousOwner = ds.contractOwner;\\n ds.contractOwner = _newOwner;\\n emit OwnershipTransferred(previousOwner, _newOwner);\\n }\\n\\n function contractOwner() internal view returns (address contractOwner_) {\\n contractOwner_ = diamondStorage().contractOwner;\\n }\\n\\n function enforceIsContractOwner() internal view {\\n require(msg.sender == diamondStorage().contractOwner, \\\"LibDiamond: Must be contract owner\\\");\\n }\\n\\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\\n\\n // Internal function version of diamondCut\\n function diamondCut(\\n IDiamondCut.FacetCut[] memory _diamondCut,\\n address _init,\\n bytes memory _calldata\\n ) internal {\\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\\n if (action == IDiamondCut.FacetCutAction.Add) {\\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\\n } else {\\n revert(\\\"LibDiamondCut: Incorrect FacetCutAction\\\");\\n }\\n }\\n emit DiamondCut(_diamondCut, _init, _calldata);\\n initializeDiamondCut(_init, _calldata);\\n }\\n\\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage(); \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress); \\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress == address(0), \\\"LibDiamondCut: Can't add function that already exists\\\");\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n require(_facetAddress != address(0), \\\"LibDiamondCut: Add facet can't be address(0)\\\");\\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\\n // add new facet address if it does not exist\\n if (selectorPosition == 0) {\\n addFacet(ds, _facetAddress);\\n }\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n require(oldFacetAddress != _facetAddress, \\\"LibDiamondCut: Can't replace function with same function\\\");\\n removeFunction(ds, oldFacetAddress, selector);\\n addFunction(ds, selector, selectorPosition, _facetAddress);\\n selectorPosition++;\\n }\\n }\\n\\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\\n require(_functionSelectors.length > 0, \\\"LibDiamondCut: No selectors in facet to cut\\\");\\n DiamondStorage storage ds = diamondStorage();\\n // if function does not exist then do nothing and return\\n require(_facetAddress == address(0), \\\"LibDiamondCut: Remove facet address must be address(0)\\\");\\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\\n bytes4 selector = _functionSelectors[selectorIndex];\\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\\n removeFunction(ds, oldFacetAddress, selector);\\n }\\n }\\n\\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\\n enforceHasContractCode(_facetAddress, \\\"LibDiamondCut: New facet has no code\\\");\\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\\n ds.facetAddresses.push(_facetAddress);\\n } \\n\\n\\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\\n }\\n\\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \\n require(_facetAddress != address(0), \\\"LibDiamondCut: Can't remove function that doesn't exist\\\");\\n // an immutable function is a function defined directly in a diamond\\n require(_facetAddress != address(this), \\\"LibDiamondCut: Can't remove immutable function\\\");\\n // replace selector with last selector, then delete last selector\\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\\n // if not the same then replace _selector with lastSelector\\n if (selectorPosition != lastSelectorPosition) {\\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\\n }\\n // delete the last selector\\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\\n delete ds.selectorToFacetAndPosition[_selector];\\n\\n // if no more selectors for facet address then delete the facet address\\n if (lastSelectorPosition == 0) {\\n // replace facet address with last facet address and delete last facet address\\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n if (facetAddressPosition != lastFacetAddressPosition) {\\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\\n }\\n ds.facetAddresses.pop();\\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\\n }\\n }\\n\\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\\n if (_init == address(0)) {\\n require(_calldata.length == 0, \\\"LibDiamondCut: _init is address(0) but_calldata is not empty\\\");\\n } else {\\n require(_calldata.length > 0, \\\"LibDiamondCut: _calldata is empty but _init is not address(0)\\\");\\n if (_init != address(this)) {\\n enforceHasContractCode(_init, \\\"LibDiamondCut: _init address has no code\\\");\\n }\\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\\n if (!success) {\\n if (error.length > 0) {\\n // bubble up the error\\n revert(string(error));\\n } else {\\n revert(\\\"LibDiamondCut: _init function reverted\\\");\\n }\\n }\\n }\\n }\\n\\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\\n uint256 contractSize;\\n assembly {\\n contractSize := extcodesize(_contract)\\n }\\n require(contractSize > 0, _errorMessage);\\n }\\n}\\n\",\"keccak256\":\"0x2205345e83eb86f5281f159a9215a096cb6d404782619f9b8e9d7a4a46c32a37\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x608060405234801561001057600080fd5b50612173806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806397b03b531461003b578063ebad22f814610057575b600080fd5b61005560048036038101906100509190611763565b610073565b005b610071600480360381019061006c91906118a9565b610885565b005b600061007d611280565b9050600081600a016000848152602001908152602001600020905060008160000154036100e157826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100d8919061195f565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561017457506101446112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156101b657336040517fd5fa066e0000000000000000000000000000000000000000000000000000000081526004016101ad9190611989565b60405180910390fd5b8060020160009054906101000a900460ff161561020a57826040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610201919061195f565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361027257826040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610269919061195f565b60405180910390fd5b8060020160019054906101000a900460ff16156102c657826040517fc921f1850000000000000000000000000000000000000000000000000000000081526004016102bd919061195f565b60405180910390fd5b816005015481600001546102da91906119dd565b42116103325742826005015482600001546102f591906119dd565b6040517f808b7d7c000000000000000000000000000000000000000000000000000000008152600401610329929190611a20565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156103b257508160070154826005015482600001546103a591906119dd565b6103af91906119dd565b42115b1561041857428260070154836005015483600001546103d191906119dd565b6103db91906119dd565b6040517f569861b100000000000000000000000000000000000000000000000000000000815260040161040f929190611a20565b60405180910390fd5b6104206112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561047c575081600701548260050154826000015461046e91906119dd565b61047891906119dd565b4211155b156104e2574282600701548360050154836000015461049b91906119dd565b6104a591906119dd565b6040517ff88af35b0000000000000000000000000000000000000000000000000000000081526004016104d9929190611a20565b60405180910390fd5b6000808260090180549050905060005b818110156106dd57600084600a01600086600901848154811061051857610517611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff161580156105a457506000801b8160010154145b156106d1576000856001015486600001546105bf9190611a78565b82600001546105ce9190611aac565b90508560020160029054906101000a900460ff166105f9578160040154816105f691906119dd565b90505b600061271087600b01548361060e9190611aac565b6106189190611b1d565b9050808261062691906119dd565b8661063191906119dd565b95508088600b0160008960090187815481106106505761064f611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546106c79190611a78565b9250508190555050505b816001019150506104f2565b508260070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603610801578360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016107b8929190611b4e565b6020604051808303816000875af11580156107d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fb9190611baf565b5061081d565b8184600201600082825461081591906119dd565b925050819055505b60018360020160016101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16857ffa165ffb1378fffa7397821a24fb52e993eab195619a2573789fca8a9e12b26660405160405180910390a35050505050565b600061088f611280565b9050600081600a016000898152602001908152602001600020905060008160000154036108f357876040517f018da6880000000000000000000000000000000000000000000000000000000081526004016108ea919061195f565b60405180910390fd5b8060000154421115610942574281600001546040517f2458293a000000000000000000000000000000000000000000000000000000008152600401610939929190611a20565b60405180910390fd5b8060020160009054906101000a900460ff161561099657876040517f9af72b8600000000000000000000000000000000000000000000000000000000815260040161098d919061195f565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036109fe57876040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016109f5919061195f565b60405180910390fd5b6000858590509050878790508114610a525780888890506040517fcc1d5b80000000000000000000000000000000000000000000000000000000008152600401610a49929190611a20565b60405180910390fd5b60008167ffffffffffffffff811115610a6e57610a6d611bdc565b5b604051908082528060200260200182016040528015610a9c5781602001602082028036833780820191505090505b50905060008060005b84811015610e1857610af58d898e8e85818110610ac557610ac4611a49565b5b9050602002810190610ad79190611c1a565b8e8e87818110610aea57610ae9611a49565b5b9050606002016112e0565b610b79578c888d8d84818110610b0e57610b0d611a49565b5b9050602002810190610b209190611c1a565b8d8d86818110610b3357610b32611a49565b5b9050606002016040517f272bd265000000000000000000000000000000000000000000000000000000008152600401610b70959493929190611dba565b60405180910390fd5b6000876009018d8d84818110610b9257610b91611a49565b5b9050602002810190610ba49190611c1a565b604051610bb2929190611e38565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600087600a0160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002018054610c3990611e80565b905003610c7d57336040517f82881f03000000000000000000000000000000000000000000000000000000008152600401610c749190611989565b60405180910390fd5b8060030160009054906101000a900460ff1615610ca1578260010192505050610e13565b60018160030160006101000a81548160ff02191690831515021790555081868580610ccb90611eb1565b965081518110610cde57610cdd611a49565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600061271089600b01548a600101548b60000154610d369190611a78565b8460000154610d459190611aac565b610d4f9190611aac565b610d599190611b1d565b90508860020160029054906101000a900460ff16610da05761271089600b01548360040154610d889190611aac565b610d929190611b1d565b81610d9d91906119dd565b90505b8086610dac91906119dd565b9550808a600b0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254610e029190611a78565b925050819055508360010193505050505b610aa5565b5060008103610e2c57505050505050611278565b6000856009018054905090508560020160039054906101000a900460ff1660ff168210610e755760018660020160006101000a81548160ff021916908315150217905550610f6c565b6000805b82811015610f305787600a016000896009018381548110610e9d57610e9c611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1615610f255781610f2290611eb1565b91505b806001019050610e79565b508660020160039054906101000a900460ff1660ff168110610f6a5760018760020160006101000a81548160ff0219169083151502179055505b505b8560020160009054906101000a900460ff161561107c5760005b8181101561107a5786600a016000886009018381548110610faa57610fa9611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1661106f5761106e8e88600901838154811061103e5761103d611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166114f0565b5b806001019050610f86565b505b506000600183901c9050600061271087600b015461109a9190611b1d565b846110a59190611b1d565b90508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8860070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848461111891906119dd565b6040518363ffffffff1660e01b8152600401611135929190611b4e565b6020604051808303816000875af1158015611154573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111789190611baf565b508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a846040518363ffffffff1660e01b81526004016111d8929190611b4e565b6020604051808303816000875af11580156111f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121b9190611baf565b503373ffffffffffffffffffffffffffffffffffffffff168e7fe9dec50cc13b92f93757042597e26d7b2af2ac85e441e773d4701a50093ec8d886848960405161126793929190611fb7565b60405180910390a350505050505050505b505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b60006112b76116f6565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008084849050905060006001826112f89190611a78565b67ffffffffffffffff81111561131157611310611bdc565b5b6040519080825280601f01601f1916602001820160405280156113435781602001600182028036833780820191505090505b5090506000600190505b828110156113cb5786868281811061136857611367611a49565b5b9050013560f81c60f81b826001836113809190611a78565b8151811061139157611390611a49565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080600101905061134d565b50600088886040516020016113e1929190611ff5565b604051602081830303815290604052805190602001206040516020016114079190612096565b604051602081830303815290604052805190602001209050600060018287600001602081019061143791906120bc565b886020013589604001356040516000815260200160405260405161145e94939291906120f8565b6020604051602081039080840390855afa158015611480573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff848051906020012060001c1690508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149550505050505095945050505050565b60006114fa611280565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546115849190611a78565b82600001546115939190611aac565b90508260020160029054906101000a900460ff166115be578160040154816115bb91906119dd565b90505b600061271084600b0154836115d39190611aac565b6115dd9190611b1d565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546116339190611a78565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401600082825461168e91906119dd565b925050819055508185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546116e691906119dd565b9250508190555050505050505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b600080fd5b600080fd5b6000819050919050565b6117408161172d565b811461174b57600080fd5b50565b60008135905061175d81611737565b92915050565b60006020828403121561177957611778611723565b5b60006117878482850161174e565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126117b5576117b4611790565b5b8235905067ffffffffffffffff8111156117d2576117d1611795565b5b6020830191508360208202830111156117ee576117ed61179a565b5b9250929050565b60008083601f84011261180b5761180a611790565b5b8235905067ffffffffffffffff81111561182857611827611795565b5b6020830191508360608202830111156118445761184361179a565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006118768261184b565b9050919050565b6118868161186b565b811461189157600080fd5b50565b6000813590506118a38161187d565b92915050565b600080600080600080608087890312156118c6576118c5611723565b5b60006118d489828a0161174e565b965050602087013567ffffffffffffffff8111156118f5576118f4611728565b5b61190189828a0161179f565b9550955050604087013567ffffffffffffffff81111561192457611923611728565b5b61193089828a016117f5565b9350935050606061194389828a01611894565b9150509295509295509295565b6119598161172d565b82525050565b60006020820190506119746000830184611950565b92915050565b6119838161186b565b82525050565b600060208201905061199e600083018461197a565b92915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006119e8826119a4565b91506119f3836119a4565b9250828201905080821115611a0b57611a0a6119ae565b5b92915050565b611a1a816119a4565b82525050565b6000604082019050611a356000830185611a11565b611a426020830184611a11565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000611a83826119a4565b9150611a8e836119a4565b9250828203905081811115611aa657611aa56119ae565b5b92915050565b6000611ab7826119a4565b9150611ac2836119a4565b9250828202611ad0816119a4565b91508282048414831517611ae757611ae66119ae565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611b28826119a4565b9150611b33836119a4565b925082611b4357611b42611aee565b5b828204905092915050565b6000604082019050611b63600083018561197a565b611b706020830184611a11565b9392505050565b60008115159050919050565b611b8c81611b77565b8114611b9757600080fd5b50565b600081519050611ba981611b83565b92915050565b600060208284031215611bc557611bc4611723565b5b6000611bd384828501611b9a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112611c3757611c36611c0b565b5b80840192508235915067ffffffffffffffff821115611c5957611c58611c10565b5b602083019250600182023603831315611c7557611c74611c15565b5b509250929050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b6000611cba8385611c7d565b9350611cc7838584611c8e565b611cd083611c9d565b840190509392505050565b600060ff82169050919050565b611cf181611cdb565b8114611cfc57600080fd5b50565b600081359050611d0e81611ce8565b92915050565b6000611d236020840184611cff565b905092915050565b611d3481611cdb565b82525050565b6000611d49602084018461174e565b905092915050565b611d5a8161172d565b82525050565b60608201611d716000830183611d14565b611d7e6000850182611d2b565b50611d8c6020830183611d3a565b611d996020850182611d51565b50611da76040830183611d3a565b611db46040850182611d51565b50505050565b600060c082019050611dcf6000830188611950565b611ddc602083018761197a565b8181036040830152611def818587611cae565b9050611dfe6060830184611d60565b9695505050505050565b600081905092915050565b6000611e1f8385611e08565b9350611e2c838584611c8e565b82840190509392505050565b6000611e45828486611e13565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e9857607f821691505b602082108103611eab57611eaa611e51565b5b50919050565b6000611ebc826119a4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611eee57611eed6119ae565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611f2e8161186b565b82525050565b6000611f408383611f25565b60208301905092915050565b6000602082019050919050565b6000611f6482611ef9565b611f6e8185611f04565b9350611f7983611f15565b8060005b83811015611faa578151611f918882611f34565b9750611f9c83611f4c565b925050600181019050611f7d565b5085935050505092915050565b6000606082019050611fcc6000830186611a11565b611fd96020830185611a11565b8181036040830152611feb8184611f59565b9050949350505050565b600060408201905061200a6000830185611950565b612017602083018461197a565b9392505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061205f601c8361201e565b915061206a82612029565b601c82019050919050565b6000819050919050565b61209061208b8261172d565b612075565b82525050565b60006120a182612052565b91506120ad828461207f565b60208201915081905092915050565b6000602082840312156120d2576120d1611723565b5b60006120e084828501611cff565b91505092915050565b6120f281611cdb565b82525050565b600060808201905061210d6000830187611950565b61211a60208301866120e9565b6121276040830185611950565b6121346060830184611950565b9594505050505056fea2646970667358221220c767af2fa21e5fc41a262a536035fbaa54b6835e5664dc72fb0b02cf4a7d8dec64736f6c63430008120033", - "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106100365760003560e01c806397b03b531461003b578063ebad22f814610057575b600080fd5b61005560048036038101906100509190611763565b610073565b005b610071600480360381019061006c91906118a9565b610885565b005b600061007d611280565b9050600081600a016000848152602001908152602001600020905060008160000154036100e157826040517f018da6880000000000000000000000000000000000000000000000000000000081526004016100d8919061195f565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161415801561017457506101446112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614155b156101b657336040517fd5fa066e0000000000000000000000000000000000000000000000000000000081526004016101ad9190611989565b60405180910390fd5b8060020160009054906101000a900460ff161561020a57826040517f9af72b86000000000000000000000000000000000000000000000000000000008152600401610201919061195f565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81600001540361027257826040517f7c6a6d70000000000000000000000000000000000000000000000000000000008152600401610269919061195f565b60405180910390fd5b8060020160019054906101000a900460ff16156102c657826040517fc921f1850000000000000000000000000000000000000000000000000000000081526004016102bd919061195f565b60405180910390fd5b816005015481600001546102da91906119dd565b42116103325742826005015482600001546102f591906119dd565b6040517f808b7d7c000000000000000000000000000000000000000000000000000000008152600401610329929190611a20565b60405180910390fd5b8060070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161480156103b257508160070154826005015482600001546103a591906119dd565b6103af91906119dd565b42115b1561041857428260070154836005015483600001546103d191906119dd565b6103db91906119dd565b6040517f569861b100000000000000000000000000000000000000000000000000000000815260040161040f929190611a20565b60405180910390fd5b6104206112ad565b73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614801561047c575081600701548260050154826000015461046e91906119dd565b61047891906119dd565b4211155b156104e2574282600701548360050154836000015461049b91906119dd565b6104a591906119dd565b6040517ff88af35b0000000000000000000000000000000000000000000000000000000081526004016104d9929190611a20565b60405180910390fd5b6000808260090180549050905060005b818110156106dd57600084600a01600086600901848154811061051857610517611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090508060030160009054906101000a900460ff161580156105a457506000801b8160010154145b156106d1576000856001015486600001546105bf9190611a78565b82600001546105ce9190611aac565b90508560020160029054906101000a900460ff166105f9578160040154816105f691906119dd565b90505b600061271087600b01548361060e9190611aac565b6106189190611b1d565b9050808261062691906119dd565b8661063191906119dd565b95508088600b0160008960090187815481106106505761064f611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546106c79190611a78565b9250508190555050505b816001019150506104f2565b508260070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1603610801578360000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8460070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16846040518363ffffffff1660e01b81526004016107b8929190611b4e565b6020604051808303816000875af11580156107d7573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107fb9190611baf565b5061081d565b8184600201600082825461081591906119dd565b925050819055505b60018360020160016101000a81548160ff0219169083151502179055503373ffffffffffffffffffffffffffffffffffffffff16857ffa165ffb1378fffa7397821a24fb52e993eab195619a2573789fca8a9e12b26660405160405180910390a35050505050565b600061088f611280565b9050600081600a016000898152602001908152602001600020905060008160000154036108f357876040517f018da6880000000000000000000000000000000000000000000000000000000081526004016108ea919061195f565b60405180910390fd5b8060000154421115610942574281600001546040517f2458293a000000000000000000000000000000000000000000000000000000008152600401610939929190611a20565b60405180910390fd5b8060020160009054906101000a900460ff161561099657876040517f9af72b8600000000000000000000000000000000000000000000000000000000815260040161098d919061195f565b60405180910390fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8160000154036109fe57876040517f7c6a6d700000000000000000000000000000000000000000000000000000000081526004016109f5919061195f565b60405180910390fd5b6000858590509050878790508114610a525780888890506040517fcc1d5b80000000000000000000000000000000000000000000000000000000008152600401610a49929190611a20565b60405180910390fd5b60008167ffffffffffffffff811115610a6e57610a6d611bdc565b5b604051908082528060200260200182016040528015610a9c5781602001602082028036833780820191505090505b50905060008060005b84811015610e1857610af58d898e8e85818110610ac557610ac4611a49565b5b9050602002810190610ad79190611c1a565b8e8e87818110610aea57610ae9611a49565b5b9050606002016112e0565b610b79578c888d8d84818110610b0e57610b0d611a49565b5b9050602002810190610b209190611c1a565b8d8d86818110610b3357610b32611a49565b5b9050606002016040517f272bd265000000000000000000000000000000000000000000000000000000008152600401610b70959493929190611dba565b60405180910390fd5b6000876009018d8d84818110610b9257610b91611a49565b5b9050602002810190610ba49190611c1a565b604051610bb2929190611e38565b908152602001604051809103902060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600087600a0160008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000816002018054610c3990611e80565b905003610c7d57336040517f82881f03000000000000000000000000000000000000000000000000000000008152600401610c749190611989565b60405180910390fd5b8060030160009054906101000a900460ff1615610ca1578260010192505050610e13565b60018160030160006101000a81548160ff02191690831515021790555081868580610ccb90611eb1565b965081518110610cde57610cdd611a49565b5b602002602001019073ffffffffffffffffffffffffffffffffffffffff16908173ffffffffffffffffffffffffffffffffffffffff1681525050600061271089600b01548a600101548b60000154610d369190611a78565b8460000154610d459190611aac565b610d4f9190611aac565b610d599190611b1d565b90508860020160029054906101000a900460ff16610da05761271089600b01548360040154610d889190611aac565b610d929190611b1d565b81610d9d91906119dd565b90505b8086610dac91906119dd565b9550808a600b0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206005016000828254610e029190611a78565b925050819055508360010193505050505b610aa5565b5060008103610e2c57505050505050611278565b6000856009018054905090508560020160039054906101000a900460ff1660ff168210610e755760018660020160006101000a81548160ff021916908315150217905550610f6c565b6000805b82811015610f305787600a016000896009018381548110610e9d57610e9c611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1615610f255781610f2290611eb1565b91505b806001019050610e79565b508660020160039054906101000a900460ff1660ff168110610f6a5760018760020160006101000a81548160ff0219169083151502179055505b505b8560020160009054906101000a900460ff161561107c5760005b8181101561107a5786600a016000886009018381548110610faa57610fa9611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060030160009054906101000a900460ff1661106f5761106e8e88600901838154811061103e5761103d611a49565b5b9060005260206000200160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff166114f0565b5b806001019050610f86565b505b506000600183901c9050600061271087600b015461109a9190611b1d565b846110a59190611b1d565b90508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8860070160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16848461111891906119dd565b6040518363ffffffff1660e01b8152600401611135929190611b4e565b6020604051808303816000875af1158015611154573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111789190611baf565b508760000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8a846040518363ffffffff1660e01b81526004016111d8929190611b4e565b6020604051808303816000875af11580156111f7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061121b9190611baf565b503373ffffffffffffffffffffffffffffffffffffffff168e7fe9dec50cc13b92f93757042597e26d7b2af2ac85e441e773d4701a50093ec8d886848960405161126793929190611fb7565b60405180910390a350505050505050505b505050505050565b6000807ff20877bf9d9fb9260326061ac66e420582d0e2a7736ab6a6c3afd0604e1902dd90508091505090565b60006112b76116f6565b60040160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b60008084849050905060006001826112f89190611a78565b67ffffffffffffffff81111561131157611310611bdc565b5b6040519080825280601f01601f1916602001820160405280156113435781602001600182028036833780820191505090505b5090506000600190505b828110156113cb5786868281811061136857611367611a49565b5b9050013560f81c60f81b826001836113809190611a78565b8151811061139157611390611a49565b5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535080600101905061134d565b50600088886040516020016113e1929190611ff5565b604051602081830303815290604052805190602001206040516020016114079190612096565b604051602081830303815290604052805190602001209050600060018287600001602081019061143791906120bc565b886020013589604001356040516000815260200160405260405161145e94939291906120f8565b6020604051602081039080840390855afa158015611480573d6000803e3d6000fd5b505050602060405103519050600073ffffffffffffffffffffffffffffffffffffffff848051906020012060001c1690508073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16149550505050505095945050505050565b60006114fa611280565b9050600081600a0160008581526020019081526020016000209050600082600a016000868152602001908152602001600020600a0160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002090506000826001015483600001546115849190611a78565b82600001546115939190611aac565b90508260020160029054906101000a900460ff166115be578160040154816115bb91906119dd565b90505b600061271084600b0154836115d39190611aac565b6115dd9190611b1d565b90508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060050160008282546116339190611a78565b925050819055508085600b0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020600401600082825461168e91906119dd565b925050819055508185600c0160008873ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008282546116e691906119dd565b9250508190555050505050505050565b6000807fc8fcad8db84d3cc18b4c41d551ea0ee66dd599cde068d998e57d5e09332c131c90508091505090565b600080fd5b600080fd5b6000819050919050565b6117408161172d565b811461174b57600080fd5b50565b60008135905061175d81611737565b92915050565b60006020828403121561177957611778611723565b5b60006117878482850161174e565b91505092915050565b600080fd5b600080fd5b600080fd5b60008083601f8401126117b5576117b4611790565b5b8235905067ffffffffffffffff8111156117d2576117d1611795565b5b6020830191508360208202830111156117ee576117ed61179a565b5b9250929050565b60008083601f84011261180b5761180a611790565b5b8235905067ffffffffffffffff81111561182857611827611795565b5b6020830191508360608202830111156118445761184361179a565b5b9250929050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006118768261184b565b9050919050565b6118868161186b565b811461189157600080fd5b50565b6000813590506118a38161187d565b92915050565b600080600080600080608087890312156118c6576118c5611723565b5b60006118d489828a0161174e565b965050602087013567ffffffffffffffff8111156118f5576118f4611728565b5b61190189828a0161179f565b9550955050604087013567ffffffffffffffff81111561192457611923611728565b5b61193089828a016117f5565b9350935050606061194389828a01611894565b9150509295509295509295565b6119598161172d565b82525050565b60006020820190506119746000830184611950565b92915050565b6119838161186b565b82525050565b600060208201905061199e600083018461197a565b92915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006119e8826119a4565b91506119f3836119a4565b9250828201905080821115611a0b57611a0a6119ae565b5b92915050565b611a1a816119a4565b82525050565b6000604082019050611a356000830185611a11565b611a426020830184611a11565b9392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000611a83826119a4565b9150611a8e836119a4565b9250828203905081811115611aa657611aa56119ae565b5b92915050565b6000611ab7826119a4565b9150611ac2836119a4565b9250828202611ad0816119a4565b91508282048414831517611ae757611ae66119ae565b5b5092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b6000611b28826119a4565b9150611b33836119a4565b925082611b4357611b42611aee565b5b828204905092915050565b6000604082019050611b63600083018561197a565b611b706020830184611a11565b9392505050565b60008115159050919050565b611b8c81611b77565b8114611b9757600080fd5b50565b600081519050611ba981611b83565b92915050565b600060208284031215611bc557611bc4611723565b5b6000611bd384828501611b9a565b91505092915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b600080fd5b600080fd5b600080fd5b60008083356001602003843603038112611c3757611c36611c0b565b5b80840192508235915067ffffffffffffffff821115611c5957611c58611c10565b5b602083019250600182023603831315611c7557611c74611c15565b5b509250929050565b600082825260208201905092915050565b82818337600083830152505050565b6000601f19601f8301169050919050565b6000611cba8385611c7d565b9350611cc7838584611c8e565b611cd083611c9d565b840190509392505050565b600060ff82169050919050565b611cf181611cdb565b8114611cfc57600080fd5b50565b600081359050611d0e81611ce8565b92915050565b6000611d236020840184611cff565b905092915050565b611d3481611cdb565b82525050565b6000611d49602084018461174e565b905092915050565b611d5a8161172d565b82525050565b60608201611d716000830183611d14565b611d7e6000850182611d2b565b50611d8c6020830183611d3a565b611d996020850182611d51565b50611da76040830183611d3a565b611db46040850182611d51565b50505050565b600060c082019050611dcf6000830188611950565b611ddc602083018761197a565b8181036040830152611def818587611cae565b9050611dfe6060830184611d60565b9695505050505050565b600081905092915050565b6000611e1f8385611e08565b9350611e2c838584611c8e565b82840190509392505050565b6000611e45828486611e13565b91508190509392505050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611e9857607f821691505b602082108103611eab57611eaa611e51565b5b50919050565b6000611ebc826119a4565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8203611eee57611eed6119ae565b5b600182019050919050565b600081519050919050565b600082825260208201905092915050565b6000819050602082019050919050565b611f2e8161186b565b82525050565b6000611f408383611f25565b60208301905092915050565b6000602082019050919050565b6000611f6482611ef9565b611f6e8185611f04565b9350611f7983611f15565b8060005b83811015611faa578151611f918882611f34565b9750611f9c83611f4c565b925050600181019050611f7d565b5085935050505092915050565b6000606082019050611fcc6000830186611a11565b611fd96020830185611a11565b8181036040830152611feb8184611f59565b9050949350505050565b600060408201905061200a6000830185611950565b612017602083018461197a565b9392505050565b600081905092915050565b7f19457468657265756d205369676e6564204d6573736167653a0a333200000000600082015250565b600061205f601c8361201e565b915061206a82612029565b601c82019050919050565b6000819050919050565b61209061208b8261172d565b612075565b82525050565b60006120a182612052565b91506120ad828461207f565b60208201915081905092915050565b6000602082840312156120d2576120d1611723565b5b60006120e084828501611cff565b91505092915050565b6120f281611cdb565b82525050565b600060808201905061210d6000830187611950565b61211a60208301866120e9565b6121276040830185611950565b6121346060830184611950565b9594505050505056fea2646970667358221220c767af2fa21e5fc41a262a536035fbaa54b6835e5664dc72fb0b02cf4a7d8dec64736f6c63430008120033", - "devdoc": { - "errors": { - "DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)": [ - { - "params": { - "publicKeys": "the number of public keys passed into the accuse call", - "signatures": "the number of signatures passed into the accuse call" - } - } - ], - "EmbalmerClaimWindowPassed(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed clean attempt", - "embalmerClaimWindowEnd": "Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow" - } - } - ], - "InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))": [ - { - "params": { - "paymentAddress": "payment address that should have been signed", - "publicKey": "publicKey that should be derived from signing key", - "sarcoId": "that should have been signed", - "signature": "invalid signature" - } - } - ], - "ResurrectionTimeInPast(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed accuse attempt", - "resurrectionTime": "Resurrection timestamp which has already passed" - } - } - ], - "SarcophagusAlreadyCleaned(bytes32)": [ - { - "params": { - "sarcoId": "ID of sarcophagus archaeologist has attempted to publish a private key on" - } - } - ], - "SenderNotEmbalmerOrAdmin(address)": [ - { - "params": { - "senderAddress": "Address of sender" - } - } - ], - "TooEarlyForAdminClean(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed clean attempt", - "embalmerClaimWindowEnd": "Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow" - } - } - ], - "TooEarlyForClean(uint256,uint256)": [ - { - "params": { - "currentTime": "Timestamp of the failed clean attempt", - "publishDeadline": "Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod" - } - } - ] - }, - "kind": "dev", - "methods": { - "accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)": { - "params": { - "paymentAddress": "the address to which rewards should be sent if successful", - "publicKeys": "an array of public keys corresponding to leaked private keys - order must match order of signatures", - "sarcoId": "The identifier of the sarcophagus having leaked private keys", - "signatures": "an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys" - } - }, - "clean(bytes32)": { - "params": { - "sarcoId": "The identifier of the sarcophagus to clean" - } - } - }, - "version": 1 - }, - "userdoc": { - "errors": { - "DifferentNumberOfSignaturesAndPublicKeys(uint256,uint256)": [ - { - "notice": "Emitted when accuse is called with an unequal numbers of public keys and signatures" - } - ], - "EmbalmerClaimWindowPassed(uint256,uint256)": [ - { - "notice": "Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed" - } - ], - "InvalidAccusalSignature(bytes32,address,bytes,(uint8,bytes32,bytes32))": [ - { - "notice": "Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey" - } - ], - "ResurrectionTimeInPast(uint256,uint256)": [ - { - "notice": "Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed" - } - ], - "SarcophagusAlreadyCleaned(bytes32)": [ - { - "notice": "Clean has been called on a sarcophagus that has already been cleaned" - } - ], - "SenderNotEmbalmerOrAdmin(address)": [ - { - "notice": "Clean has been called by someone other than the admin or embalmer of the sarcophagus" - } - ], - "TooEarlyForAdminClean(uint256,uint256)": [ - { - "notice": "Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed" - } - ], - "TooEarlyForClean(uint256,uint256)": [ - { - "notice": "Clean has been called before the deadline for archaeologists to publish private keys has passed" - } - ] - }, - "kind": "user", - "methods": { - "accuse(bytes32,bytes[],(uint8,bytes32,bytes32)[],address)": { - "notice": "Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id and payment address generated with the leaked private keys If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus state will be updated to Accused and bonds for all remaining unaccused archaeologists will be returned" - }, - "clean(bytes32)": { - "notice": "If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod, their locked bonds and diggingFees may be claimed by either the embalmer or the admin embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will be able to claim remaining locked bond and diggingFees" - } - }, - "version": 1 - }, - "storageLayout": { - "storage": [], - "types": null - } -} \ No newline at end of file diff --git a/deployments/baseGoerli/solcInputs/b7fcd450a9977c08df561a1e7df764e7.json b/deployments/baseGoerli/solcInputs/b7fcd450a9977c08df561a1e7df764e7.json deleted file mode 100644 index 4833aa0..0000000 --- a/deployments/baseGoerli/solcInputs/b7fcd450a9977c08df561a1e7df764e7.json +++ /dev/null @@ -1,110 +0,0 @@ -{ - "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/draft-IERC20Permit.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\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/token/ERC20/utils/SafeERC20.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" - }, - "@openzeppelin/contracts/utils/Address.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" - }, - "@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/Strings.sol": { - "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" - }, - "contracts/facets/AdminFacet.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\n\r\npragma solidity 0.8.18;\r\n\r\nimport \"../storage/LibAppStorage.sol\";\r\n\r\nimport {LibDiamond} from \"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\";\r\n\r\n/// @notice Caller of any function in this facet must be the admin address\r\ncontract AdminFacet {\r\n event SetProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage);\r\n event SetCursedBondPercentage(uint256 cursedBondPercentage);\r\n event WithdrawProtocolFees(uint256 totalProtocolFees, address withdrawalAddress);\r\n event SetGracePeriod(uint256 gracePeriod);\r\n event SetEmbalmerClaimWindow(uint256 embalmerClaimWindow);\r\n event SetExpirationThreshold(uint256 expirationThreshold);\r\n event AdminTransferred(address indexed previousAdmin, address indexed newAdmin);\r\n\r\n /// @notice Admin has attempted to set a zero value\r\n error CannotSetZeroValue();\r\n\r\n /// @notice Caller must be the admin address\r\n error CallerIsNotAdmin();\r\n\r\n /// @notice Provided address cannot be zero address\r\n error ZeroAddress();\r\n\r\n modifier onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n if (msg.sender != s.admin) {\r\n revert CallerIsNotAdmin();\r\n }\r\n _;\r\n }\r\n\r\n /// @notice Withdraws the total protocol fee amount from the contract to the specified address\r\n /// @param withdrawalAddress - the address to withdraw funds to\r\n function withdrawProtocolFees(address withdrawalAddress) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n // Get the total protocol fees from storage\r\n uint256 totalProtocolFees = s.totalProtocolFees;\r\n // Set the total protocol fees to 0 before the transfer to avoid reentrancy\r\n s.totalProtocolFees = 0;\r\n // Transfer the protocol fee amount to the sender after setting state\r\n s.sarcoToken.transfer(withdrawalAddress, totalProtocolFees);\r\n emit WithdrawProtocolFees(totalProtocolFees, withdrawalAddress);\r\n }\r\n\r\n /// @notice Sets the protocol fee base percentage, used to calculate protocol fees\r\n /// @notice The denominator is 10000\r\n /// @param protocolFeeBasePercentage percentage to set\r\n function setProtocolFeeBasePercentage(uint256 protocolFeeBasePercentage) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\r\n emit SetProtocolFeeBasePercentage(protocolFeeBasePercentage);\r\n }\r\n\r\n /// @notice Sets the digging fee / cursed bond ratio\r\n /// @notice The denominator is 10000\r\n /// used to calculate how much bond archaeologists must lock per curse.\r\n /// @param cursedBondPercentage ratio to set.\r\n function setCursedBondPercentage(uint256 cursedBondPercentage) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n if (cursedBondPercentage == 0) {\r\n revert CannotSetZeroValue();\r\n }\r\n s.cursedBondPercentage = cursedBondPercentage;\r\n emit SetCursedBondPercentage(cursedBondPercentage);\r\n }\r\n\r\n /// @notice Updates the resurrection grace period\r\n /// @notice Denominated in seconds\r\n /// @param gracePeriod to set\r\n function setGracePeriod(uint256 gracePeriod) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n s.gracePeriod = gracePeriod;\r\n emit SetGracePeriod(gracePeriod);\r\n }\r\n\r\n /// @notice Updates the embalmerClaimWindow\r\n /// @notice Denominated in seconds\r\n /// @param embalmerClaimWindow to set\r\n function setEmbalmerClaimWindow(uint256 embalmerClaimWindow) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n s.embalmerClaimWindow = embalmerClaimWindow;\r\n emit SetEmbalmerClaimWindow(embalmerClaimWindow);\r\n }\r\n\r\n /// @notice Updates the expirationThreshold used during sarcophagus creation\r\n /// @notice Denominated in seconds\r\n /// @param expirationThreshold to set\r\n function setExpirationThreshold(uint256 expirationThreshold) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n s.expirationThreshold = expirationThreshold;\r\n emit SetExpirationThreshold(expirationThreshold);\r\n }\r\n\r\n /// @notice Transfers admin address to newAdmin.\r\n /// @param newAdmin to set\r\n function transferAdmin(address newAdmin) external onlyAdmin {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n if (newAdmin == address(0)) {\r\n revert ZeroAddress();\r\n }\r\n s.admin = newAdmin;\r\n emit AdminTransferred(msg.sender, newAdmin);\r\n }\r\n}\r\n" - }, - "contracts/facets/ArchaeologistFacet.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\nimport \"../storage/LibAppStorage.sol\";\r\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\r\nimport {LibPrivateKeys} from \"../libraries/LibPrivateKeys.sol\";\r\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\r\nimport {LibBonds} from \"../libraries/LibBonds.sol\";\r\n\r\ncontract ArchaeologistFacet {\r\n /// @notice Emitted when an archaeologist successfully publishes their private key for a sarcophagus\r\n /// @param sarcoId ID of sarcophagus archaeologist has published the private key on\r\n /// @param privateKey private key that has been published\r\n event PublishPrivateKey(\r\n bytes32 indexed sarcoId,\r\n bytes32 privateKey,\r\n address indexed archaeologist\r\n );\r\n\r\n event DepositFreeBond(address indexed archaeologist, uint256 depositedBond);\r\n\r\n event RegisterArchaeologist(\r\n address indexed archaeologist,\r\n string peerId,\r\n uint256 minimumDiggingFee,\r\n uint256 maximumRewrapInterval,\r\n uint256 freeBond,\r\n uint256 maximumResurrectionTime,\r\n uint256 curseFee\r\n );\r\n\r\n event UpdateArchaeologist(\r\n address indexed archaeologist,\r\n string peerId,\r\n uint256 minimumDiggingFee,\r\n uint256 maximumRewrapInterval,\r\n uint256 freeBond,\r\n uint256 maximumResurrectionTime,\r\n uint256 curseFee\r\n );\r\n\r\n event WithdrawFreeBond(address indexed archaeologist, uint256 withdrawnBond);\r\n\r\n event WithdrawReward(address indexed archaeologist, uint256 withdrawnReward);\r\n\r\n /// @notice An archaeologist that has already been successfully accused has attempted to publish their private key\r\n /// @param archaeologistAddress Address of accused archaeologist who is attempting to publish their private key\r\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a key on\r\n error ArchaeologistHasBeenAccused(address archaeologistAddress, bytes32 sarcoId);\r\n\r\n /// @notice Archaeologist has attempted to publish a key before the resurrection time\r\n /// @param currentTime Timestamp of the failed publish attempt\r\n /// @param resurrectionTime Time after which the sarcophagus can be resurrected\r\n error TooEarlyForPublish(uint256 currentTime, uint256 resurrectionTime);\r\n\r\n /// @notice Archaeologist has attempted to publish a key after the end of the resurrection window\r\n /// @param currentTime Timestamp of the failed publish attempt\r\n /// @param publishDeadline Time after which the sarcophagus can no longer be resurrected (resurrectionTime + gracePeriod)\r\n error TooLateForPublish(uint256 currentTime, uint256 publishDeadline);\r\n\r\n /// @notice Archaeologist has attempted to publish a key for a sarcophagus twice\r\n /// @param archaeologistAddress address of publishing archaeologist\r\n error ArchaeologistAlreadyPublishedPrivateKey(address archaeologistAddress);\r\n\r\n /// @notice Archaeologist has attempted to set a zero minimumDiggingFeePerSecond or maximumRewrapInterval\r\n error CannotSetZeroProfileValue();\r\n\r\n /// @notice Archaeologist has attempted to publish the incorrect private key for a sarcophagus\r\n /// @param archaeologistAddress address of publishing archaeologist\r\n /// @param publicKey publicKey stored for archaeologist on the sarcophagus\r\n /// @param privateKey privateKey the archaeologist has attempted to publish\r\n error ArchaeologistPublishedIncorrectPrivateKey(\r\n address archaeologistAddress,\r\n bytes publicKey,\r\n bytes32 privateKey\r\n );\r\n\r\n /// @notice Registers the archaeologist profile\r\n /// @param peerId The libp2p identifier for the archaeologist\r\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\r\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\r\n /// for a resurrection\r\n /// @param freeBond How much bond the archaeologist wants to deposit during the register call (if any)\r\n /// @param maximumResurrectionTime The time beyond which the archaeologist is not willing to accept new curses or rewraps\r\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\r\n function registerArchaeologist(\r\n string memory peerId,\r\n uint256 minimumDiggingFeePerSecond,\r\n uint256 maximumRewrapInterval,\r\n uint256 freeBond,\r\n uint256 maximumResurrectionTime,\r\n uint256 curseFee\r\n ) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n // verify that the archaeologist does not already exist\r\n LibUtils.revertIfArchProfileExists(msg.sender);\r\n\r\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\r\n revert CannotSetZeroProfileValue();\r\n }\r\n\r\n // create a new archaeologist\r\n LibTypes.ArchaeologistProfile memory newArch = LibTypes.ArchaeologistProfile({\r\n peerId: peerId,\r\n minimumDiggingFeePerSecond: minimumDiggingFeePerSecond,\r\n maximumResurrectionTime: maximumResurrectionTime,\r\n maximumRewrapInterval: maximumRewrapInterval,\r\n freeBond: freeBond,\r\n cursedBond: 0,\r\n curseFee: curseFee\r\n });\r\n\r\n // transfer SARCO tokens from the archaeologist to this contract, to be\r\n // used as their free bond. can be 0.\r\n if (freeBond != 0) {\r\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\r\n }\r\n\r\n // save the new archaeologist into relevant data structures\r\n s.archaeologistProfiles[msg.sender] = newArch;\r\n s.archaeologistProfileAddresses.push(msg.sender);\r\n\r\n emit RegisterArchaeologist(\r\n msg.sender,\r\n newArch.peerId,\r\n newArch.minimumDiggingFeePerSecond,\r\n newArch.maximumRewrapInterval,\r\n newArch.freeBond,\r\n newArch.maximumResurrectionTime,\r\n newArch.curseFee\r\n );\r\n }\r\n\r\n /// @notice Updates the archaeologist profile\r\n /// @param peerId The libp2p identifier for the archaeologist\r\n /// @param minimumDiggingFeePerSecond The archaeologist's minimum amount to earn per second for being cursed\r\n /// @param freeBond How much bond the archaeologist wants to deposit during the update call (if any)\r\n /// @param maximumRewrapInterval The longest interval of time from a rewrap time the arch will accept\r\n /// for a resurrection\r\n /// @param curseFee The fee the archaeologist sets to roughly cover the cost of a publishPrivateKey transaction\r\n function updateArchaeologist(\r\n string memory peerId,\r\n uint256 minimumDiggingFeePerSecond,\r\n uint256 maximumRewrapInterval,\r\n uint256 freeBond,\r\n uint256 maximumResurrectionTime,\r\n uint256 curseFee\r\n ) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n\r\n // verify that the archaeologist exists\r\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\r\n\r\n if (maximumRewrapInterval == 0 || minimumDiggingFeePerSecond == 0) {\r\n revert CannotSetZeroProfileValue();\r\n }\r\n\r\n LibTypes.ArchaeologistProfile storage existingArch = s.archaeologistProfiles[msg.sender];\r\n existingArch.peerId = peerId;\r\n existingArch.minimumDiggingFeePerSecond = minimumDiggingFeePerSecond;\r\n existingArch.maximumRewrapInterval = maximumRewrapInterval;\r\n existingArch.maximumResurrectionTime = maximumResurrectionTime;\r\n existingArch.curseFee = curseFee;\r\n\r\n // transfer SARCO tokens from the archaeologist to this contract, to be\r\n // used as their free bond. can be 0.\r\n if (freeBond != 0) {\r\n s.archaeologistProfiles[msg.sender].freeBond += freeBond;\r\n s.sarcoToken.transferFrom(msg.sender, address(this), freeBond);\r\n }\r\n\r\n emit UpdateArchaeologist(\r\n msg.sender,\r\n existingArch.peerId,\r\n existingArch.minimumDiggingFeePerSecond,\r\n existingArch.maximumRewrapInterval,\r\n freeBond,\r\n existingArch.maximumResurrectionTime,\r\n existingArch.curseFee\r\n );\r\n }\r\n\r\n /// @notice Deposits an archaeologist's free bond to the contract.\r\n /// @param amount The amount to deposit\r\n function depositFreeBond(uint256 amount) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\r\n\r\n // Increase the archaeologist's free bond in app storage\r\n s.archaeologistProfiles[msg.sender].freeBond += amount;\r\n\r\n // Transfer the amount of sarcoToken from the archaeologist to the contract\r\n s.sarcoToken.transferFrom(msg.sender, address(this), amount);\r\n // Emit an event\r\n emit DepositFreeBond(msg.sender, amount);\r\n }\r\n\r\n /// @notice Withdraws an archaeologist's free bond from the contract.\r\n /// @param amount The amount to withdraw\r\n function withdrawFreeBond(uint256 amount) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibUtils.revertIfArchProfileDoesNotExist(msg.sender);\r\n // Decrease the archaeologist's free bond amount.\r\n // Reverts if there is not enough free bond on the contract.\r\n s.archaeologistProfiles[msg.sender].freeBond -= amount;\r\n\r\n // Transfer the amount of sarcoToken to the archaeologist\r\n s.sarcoToken.transfer(msg.sender, amount);\r\n\r\n emit WithdrawFreeBond(msg.sender, amount);\r\n }\r\n\r\n /// @notice Withdraws all rewards from an archaeologist's reward pool\r\n function withdrawReward() external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n uint256 amountToWithdraw = s.archaeologistRewards[msg.sender];\r\n s.archaeologistRewards[msg.sender] = 0;\r\n\r\n // Transfer the amount of sarcoToken to the archaeologist\r\n s.sarcoToken.transfer(msg.sender, amountToWithdraw);\r\n\r\n emit WithdrawReward(msg.sender, amountToWithdraw);\r\n }\r\n\r\n /// @notice Publishes the private key for which the archaeologist is responsible during the\r\n /// sarcophagus resurrection window.\r\n /// Pays digging fees to the archaeologist and releases their locked bond.\r\n /// Cannot be called on a compromised or buried sarcophagus.\r\n /// @param sarcoId The identifier of the sarcophagus for which the archaeologist is responsible\r\n /// @param privateKey The private key the archaeologist is publishing\r\n function publishPrivateKey(bytes32 sarcoId, bytes32 privateKey) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // Confirm sarcophagus exists\r\n if (sarcophagus.resurrectionTime == 0) {\r\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\r\n }\r\n\r\n // Confirm sarcophagus has not been compromised\r\n if (sarcophagus.isCompromised) {\r\n revert LibErrors.SarcophagusCompromised(sarcoId);\r\n }\r\n\r\n // Confirm sarcophagus is not buried\r\n if (sarcophagus.resurrectionTime == type(uint256).max) {\r\n revert LibErrors.SarcophagusInactive(sarcoId);\r\n }\r\n\r\n // Confirm current time is after resurrectionTime\r\n if (block.timestamp < sarcophagus.resurrectionTime) {\r\n revert TooEarlyForPublish(block.timestamp, sarcophagus.resurrectionTime);\r\n }\r\n\r\n // Confirm current time is within gracePeriod\r\n if (block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod) {\r\n revert TooLateForPublish(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\r\n }\r\n\r\n // Confirm tx sender is an archaeologist on the sarcophagus\r\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\r\n .sarcophagi[sarcoId]\r\n .cursedArchaeologists[msg.sender];\r\n if (cursedArchaeologist.publicKey.length == 0) {\r\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\r\n }\r\n\r\n // Confirm archaeologist has not already leaked their private key\r\n if (cursedArchaeologist.isAccused) {\r\n revert ArchaeologistHasBeenAccused(msg.sender, sarcoId);\r\n }\r\n\r\n // Confirm archaeologist has not already published their private key\r\n if (cursedArchaeologist.privateKey != 0) {\r\n revert ArchaeologistAlreadyPublishedPrivateKey(msg.sender);\r\n }\r\n\r\n // Confirm that the private key being submitted matches the public key stored on the\r\n // sarcophagus for this archaeologist\r\n if (!LibPrivateKeys.isPublicKeyOfPrivateKey(privateKey, cursedArchaeologist.publicKey)) {\r\n revert ArchaeologistPublishedIncorrectPrivateKey(\r\n msg.sender,\r\n cursedArchaeologist.publicKey,\r\n privateKey\r\n );\r\n }\r\n\r\n // Store the private key on cursed archaeologist\r\n cursedArchaeologist.privateKey = privateKey;\r\n\r\n // Free archaeologist locked bond and transfer digging fees\r\n LibBonds.freeArchaeologist(sarcoId, msg.sender);\r\n\r\n emit PublishPrivateKey(sarcoId, privateKey, msg.sender);\r\n }\r\n}\r\n" - }, - "contracts/facets/EmbalmerFacet.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"@openzeppelin/contracts/utils/Strings.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\nimport \"../storage/LibAppStorage.sol\";\r\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\r\nimport {LibBonds} from \"../libraries/LibBonds.sol\";\r\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\r\n\r\ncontract EmbalmerFacet {\r\n /// @notice Emitted when a sarcophagus is created\r\n /// @param sarcoId Id of the new sarcophagus\r\n /// @param name Name of the new sarcophagus\r\n /// @param resurrectionTime Resurrection time of the new sarcophagus\r\n /// @param creationTime Creation time as set during negotiation, not the same as blocktime at which event is emitted\r\n /// @param embalmer Address of embalmer\r\n /// @param recipient Address of recipient\r\n /// @param cursedArchaeologists Array of addresses of cursed archaeologists\r\n /// @param totalDiggingFees Total digging fees charged to embalmer to create the sarcophagus\r\n /// @param arweaveTxId arweave tx id for the sarcophagus\r\n event CreateSarcophagus(\r\n bytes32 indexed sarcoId,\r\n string name,\r\n uint256 resurrectionTime,\r\n uint256 creationTime,\r\n address indexed embalmer,\r\n address indexed recipient,\r\n address[] cursedArchaeologists,\r\n uint256 totalDiggingFees,\r\n string arweaveTxId\r\n );\r\n\r\n /// @notice Emitted when a sarcophagus is rewrapped\r\n /// @param sarcoId Id of sarcophagus that was rewrapped\r\n /// @param resurrectionTime New resurrection time for the sarcophagus\r\n /// @param totalDiggingFees Total digging fees charged to the embalmer for the rewrap\r\n /// @param rewrapSarcophagusProtocolFees Total protocol fees charged to the embalmer for the rewrap\r\n event RewrapSarcophagus(\r\n bytes32 indexed sarcoId,\r\n uint256 resurrectionTime,\r\n uint256 totalDiggingFees,\r\n uint256 rewrapSarcophagusProtocolFees\r\n );\r\n\r\n /// @notice Emitted when a sarcophagus is buried\r\n /// @param sarcoId Id of sarcophagus that was buried\r\n event BurySarcophagus(bytes32 indexed sarcoId);\r\n\r\n /// @notice Parameters of a sarcophagus, supplied during sarcophagus creation\r\n struct SarcophagusParams {\r\n string name;\r\n // highest rewrap interval cursed archaeologists have agreed to accept for lifetime of sarcophagus\r\n uint256 maximumRewrapInterval;\r\n // The timestamp beyond which the sarcophagus can no longer be rewrapped\r\n uint256 maximumResurrectionTime;\r\n address recipientAddress;\r\n uint256 resurrectionTime;\r\n uint8 threshold;\r\n uint256 creationTime;\r\n }\r\n\r\n /// @notice Parameters of an archaeologist's curse, supplied during sarcophagus creation\r\n struct CurseParams {\r\n bytes publicKey;\r\n address archAddress;\r\n uint256 diggingFeePerSecond;\r\n uint256 curseFee;\r\n uint8 v;\r\n bytes32 r;\r\n bytes32 s;\r\n }\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an id that is already in use\r\n /// @param sarcoId Id that is already in use\r\n error SarcophagusAlreadyExists(bytes32 sarcoId);\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with expired parameters\r\n /// @param currentTime Timestamp of the failed create attempt\r\n /// @param creationTime Time when the sarcophagus parameters were created\r\n /// @param creationDeadline Deadline for creation of a sarcophagus with the supplied parameters\r\n error SarcophagusParametersExpired(\r\n uint256 currentTime,\r\n uint256 creationTime,\r\n uint256 creationDeadline\r\n );\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with no archaeologists\r\n error NoArchaeologistsProvided();\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a shamir secret sharing threshold of 0\r\n error ThresholdCannotBeZero();\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with more required archaeologists than total archaeologists\r\n error ThresholdGreaterThanTotalNumberOfArchaeologists(\r\n uint8 threshold,\r\n uint256 totalNumberOfArchaeologists\r\n );\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with an archaeologist list that contains the same archaeologist more than once\r\n error ArchaeologistListContainsDuplicate(address archaeologistAddress);\r\n\r\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that has already passed\r\n /// @param currentTime Timestamp of the failed rewrap attempt\r\n /// @param resurrectionTime Resurrection timestamp which has already passed\r\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\r\n\r\n /// @notice Emitted when an embalmer attempts to create a sarcophagus with a public key that has already been assigned to another sarcophagus\r\n /// @param publicKey the duplicated public key\r\n error DuplicatePublicKey(bytes publicKey);\r\n\r\n /// @notice Emitted when an embalmer attempts to rewrap a sarcophagus with a resurrection time that exceeds the maximum rewrap interval\r\n /// @param resurrectionTime Resurrection timestamp which is too far in the future\r\n /// @param sarcophagusMaximumRewrapInterval Maximum rewrap interval set for the sarcophagus\r\n /// @param maximumPermissibleResurrectionTime Resurrection timestamp which is too far in the future\r\n error ResurrectionTimeTooFarInFuture(\r\n uint256 resurrectionTime,\r\n uint256 sarcophagusMaximumRewrapInterval,\r\n uint256 maximumPermissibleResurrectionTime\r\n );\r\n\r\n /// @notice Emitted when the resurrection time defined during sarcohpagus creation or rewrap goes past the max resurrection time\r\n /// @param resurrectionTime The resurrection time defined during the sarcophagus creation or rewrap\r\n /// @param maxResurrectionTime The maximum allowed resurrection time\r\n error ResurrectionTimePastMaxResurrectionTime(\r\n uint256 resurrectionTime,\r\n uint256 maxResurrectionTime\r\n );\r\n\r\n error NewResurrectionTimeInPast(uint256 currentTime, uint256 newResurrectionTime);\r\n\r\n error NewResurrectionTimeIsZero();\r\n\r\n error NewResurrectionTimeTooFarInFuture(\r\n uint256 resurrectionTime,\r\n uint256 sarcophagusMaximumRewrapInterval,\r\n uint256 maximumPermissibleResurrectionTime\r\n );\r\n\r\n error ResurrectionTimeTooFarPastPreviousResurrectionTime(\r\n uint256 resurrectionTime,\r\n uint256 previousResurrectionTime\r\n );\r\n\r\n /// @notice Creates a sarcophagus with the supplied parameters and locks\r\n /// a portion of each archaeologist's freeBond equal to the digging fees calculated for the duration\r\n /// of the sarcophagus until its resurrection time.\r\n ///\r\n /// Verifies that each supplied archaeologist has signed off on the sarcophagus negotiation parameters:\r\n /// - `publicKey` that matches the private key the archaeologist is responsible for\r\n /// - `maximumRewrapInterval` to be enforced for the lifetime of the sarcophagus. No new resurrection time for future rewraps may exceed this interval from time of rewrap.\r\n /// - `creationTime` of sarcophagus\r\n /// - `diggingFeePerSecond` agreed to be paid to the archaeologist during the lifetime of the sarcophagus. Paid per rewrap and publishPrivateKey. Constant.\r\n /// - `curseFee` agreed to be paid to the archaeologist once during the lifetime of the sarcophagus to cover cost of publishPrivateKey tx. Paid either on first rewrap or publishPrivateKey if no rewrap has occurred Constant.\r\n ///\r\n /// @param sarcoId the identifier of the sarcophagus\r\n /// @param sarcophagusParams params to set on sarcophagus being created\r\n /// @param selectedArchaeologists the archaeologists the embalmer has selected to curse\r\n /// @param arweaveTxId id of tx storing the sarcophagus payload on arweave\r\n function createSarcophagus(\r\n bytes32 sarcoId,\r\n SarcophagusParams calldata sarcophagusParams,\r\n CurseParams[] calldata selectedArchaeologists,\r\n string calldata arweaveTxId\r\n ) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n\r\n // Confirm that sarcophagus with supplied id doesn't already exist\r\n if (s.sarcophagi[sarcoId].resurrectionTime != 0) {\r\n revert SarcophagusAlreadyExists(sarcoId);\r\n }\r\n\r\n // Ensure too much time hasn't passed since the sarcophagus `creationTime` that has been signed\r\n // off by its cursed archaeologists.\r\n if (block.timestamp > sarcophagusParams.creationTime + s.expirationThreshold) {\r\n revert SarcophagusParametersExpired(\r\n block.timestamp,\r\n sarcophagusParams.creationTime,\r\n sarcophagusParams.creationTime + s.expirationThreshold\r\n );\r\n }\r\n\r\n // Confirm that resurrection time is in the future\r\n if (block.timestamp >= sarcophagusParams.resurrectionTime) {\r\n revert ResurrectionTimeInPast(block.timestamp, sarcophagusParams.resurrectionTime);\r\n }\r\n\r\n // Confirm that resurrection or rewrap will occur before the maximumRewrapInterval elapses\r\n if (\r\n block.timestamp + sarcophagusParams.maximumRewrapInterval <\r\n sarcophagusParams.resurrectionTime\r\n ) {\r\n revert ResurrectionTimeTooFarInFuture(\r\n sarcophagusParams.resurrectionTime,\r\n sarcophagusParams.maximumRewrapInterval,\r\n block.timestamp + sarcophagusParams.maximumRewrapInterval\r\n );\r\n }\r\n\r\n // Confirm that the resurrection time is less than the max resurrection time\r\n if (sarcophagusParams.resurrectionTime > sarcophagusParams.maximumResurrectionTime) {\r\n revert ResurrectionTimePastMaxResurrectionTime(\r\n sarcophagusParams.resurrectionTime,\r\n sarcophagusParams.maximumResurrectionTime\r\n );\r\n }\r\n\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // track total digging fees due upon creation of sarcophagus\r\n uint256 totalDiggingFees;\r\n\r\n {\r\n uint256 nSelectedArchs = selectedArchaeologists.length;\r\n // Validate archaeologist and threshold lengths\r\n if (nSelectedArchs == 0) {\r\n revert NoArchaeologistsProvided();\r\n }\r\n\r\n if (sarcophagusParams.threshold == 0) {\r\n revert ThresholdCannotBeZero();\r\n }\r\n\r\n // Ensure that k <= n in the effective k-of-n shamir secret sharing scheme\r\n // used to distribute keyshares among archaeologists\r\n if (sarcophagusParams.threshold > nSelectedArchs) {\r\n revert ThresholdGreaterThanTotalNumberOfArchaeologists(\r\n sarcophagusParams.threshold,\r\n nSelectedArchs\r\n );\r\n }\r\n\r\n // create the sarcophagus\r\n sarcophagus.name = sarcophagusParams.name;\r\n sarcophagus.threshold = sarcophagusParams.threshold;\r\n sarcophagus.resurrectionTime = sarcophagusParams.resurrectionTime;\r\n sarcophagus.previousRewrapTime = sarcophagusParams.creationTime;\r\n sarcophagus.maximumRewrapInterval = sarcophagusParams.maximumRewrapInterval;\r\n sarcophagus.maximumResurrectionTime = sarcophagusParams.maximumResurrectionTime;\r\n sarcophagus.arweaveTxId = arweaveTxId;\r\n sarcophagus.embalmerAddress = msg.sender;\r\n sarcophagus.recipientAddress = sarcophagusParams.recipientAddress;\r\n sarcophagus.cursedArchaeologistAddresses = new address[](nSelectedArchs);\r\n sarcophagus.cursedBondPercentage = s.cursedBondPercentage;\r\n\r\n for (uint256 i; i < nSelectedArchs; ) {\r\n LibUtils.revertIfArchProfileDoesNotExist(selectedArchaeologists[i].archAddress);\r\n\r\n // Confirm archaeologist isn't already cursed on this sarcophagus (no duplicates)\r\n if (\r\n sarcophagus\r\n .cursedArchaeologists[selectedArchaeologists[i].archAddress]\r\n .publicKey\r\n .length != 0\r\n ) {\r\n revert ArchaeologistListContainsDuplicate(\r\n selectedArchaeologists[i].archAddress\r\n );\r\n }\r\n\r\n // Confirm archaeologist is not re-using a key pair\r\n if (\r\n s.publicKeyToArchaeologistAddress[selectedArchaeologists[i].publicKey] !=\r\n address(0)\r\n ) {\r\n revert DuplicatePublicKey(selectedArchaeologists[i].publicKey);\r\n }\r\n\r\n LibUtils.verifyArchaeologistSignature(\r\n sarcophagusParams.maximumRewrapInterval,\r\n sarcophagusParams.maximumResurrectionTime,\r\n sarcophagusParams.creationTime,\r\n selectedArchaeologists[i]\r\n );\r\n\r\n // Curse the archaeologist on this sarcophagus\r\n uint256 diggingFeesDue = LibBonds.curseArchaeologist(\r\n sarcoId,\r\n selectedArchaeologists[i],\r\n i\r\n );\r\n\r\n totalDiggingFees += diggingFeesDue;\r\n\r\n // \"Consume\" this public key so it cannot be reused in the future\r\n s.publicKeyToArchaeologistAddress[\r\n selectedArchaeologists[i].publicKey\r\n ] = selectedArchaeologists[i].archAddress;\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n // Transfer totalDiggingFees and the protocolFees in SARCO from embalmer to this contract\r\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\r\n s.totalProtocolFees += protocolFees;\r\n s.sarcoToken.transferFrom(\r\n msg.sender,\r\n address(this),\r\n totalDiggingFees + protocolFees\r\n );\r\n }\r\n emit CreateSarcophagus(\r\n sarcoId,\r\n sarcophagusParams.name,\r\n sarcophagusParams.resurrectionTime,\r\n sarcophagusParams.creationTime,\r\n msg.sender,\r\n sarcophagusParams.recipientAddress,\r\n sarcophagus.cursedArchaeologistAddresses,\r\n totalDiggingFees,\r\n arweaveTxId\r\n );\r\n }\r\n\r\n /// @notice Updates the resurrectionTime on a sarcophagus. Callable by the embalmer of a sarcophagus if its\r\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\r\n /// @param sarcoId the identifier of the sarcophagus\r\n /// @param resurrectionTime the new resurrection time\r\n function rewrapSarcophagus(bytes32 sarcoId, uint256 resurrectionTime) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // Confirm the sarcophagus exists\r\n if (sarcophagus.resurrectionTime == 0) {\r\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus has not been compromised\r\n if (sarcophagus.isCompromised) {\r\n revert LibErrors.SarcophagusCompromised(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus is not buried\r\n if (sarcophagus.resurrectionTime == type(uint256).max) {\r\n revert LibErrors.SarcophagusInactive(sarcoId);\r\n }\r\n\r\n // Confirm tx sender is embalmer\r\n if (sarcophagus.embalmerAddress != msg.sender) {\r\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\r\n }\r\n\r\n // Confirm resurrection time has not yet passed\r\n if (block.timestamp >= sarcophagus.resurrectionTime) {\r\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\r\n }\r\n\r\n // Confirm that new resurrection time is in future\r\n if (block.timestamp >= resurrectionTime) {\r\n revert NewResurrectionTimeInPast(block.timestamp, resurrectionTime);\r\n }\r\n\r\n // Confirm that new resurrection time doesn't exceed sarcophagus's maximumRewrapInterval\r\n if (block.timestamp + sarcophagus.maximumRewrapInterval < resurrectionTime) {\r\n revert NewResurrectionTimeTooFarInFuture(\r\n resurrectionTime,\r\n sarcophagus.maximumRewrapInterval,\r\n block.timestamp + sarcophagus.maximumRewrapInterval\r\n );\r\n }\r\n\r\n // Confirm that the new resurrection time doesn't exceed the maximumResurrectionTime\r\n if (sarcophagus.maximumResurrectionTime < resurrectionTime) {\r\n revert ResurrectionTimePastMaxResurrectionTime(\r\n resurrectionTime,\r\n sarcophagus.maximumResurrectionTime\r\n );\r\n }\r\n\r\n // track total digging fees to be paid by embalmer across all archaeologists on the sarcophagus\r\n uint256 totalDiggingFees;\r\n\r\n // pay digging fee to each cursed archaeologist on the sarcophagus that has not been accused\r\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\r\n uint256 cursedBondPercentage = sarcophagus.cursedBondPercentage;\r\n\r\n uint256 nArchAddresses = archaeologistAddresses.length;\r\n for (uint256 i; i < nArchAddresses; ) {\r\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\r\n .cursedArchaeologists[archaeologistAddresses[i]];\r\n\r\n if (!cursedArchaeologist.isAccused) {\r\n // Previous digging fees calculation ignores curseFee\r\n // curseFee rewards and bond are handled separately if this sarcophagus has not been rewrapped yet\r\n uint256 prevDiggingFees = cursedArchaeologist.diggingFeePerSecond *\r\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\r\n\r\n uint256 newDiggingFees = cursedArchaeologist.diggingFeePerSecond *\r\n (resurrectionTime - block.timestamp);\r\n\r\n // If the new digging fees are greater than the previous digging fees, we need to\r\n // increase the archaeologist's cursed bond to cover the necessary cursed bond amount\r\n if (newDiggingFees > prevDiggingFees) {\r\n uint256 cursedBondIncrease = ((newDiggingFees - prevDiggingFees) *\r\n cursedBondPercentage) / 10000;\r\n\r\n // If the previous cycle's rewards can't cover the cursed bond increase, revert\r\n if (cursedBondIncrease > prevDiggingFees) {\r\n revert ResurrectionTimeTooFarPastPreviousResurrectionTime(\r\n resurrectionTime,\r\n sarcophagus.resurrectionTime\r\n );\r\n }\r\n\r\n // Increase the archaeologist's cursed bond using digging fees paid by the embalmer\r\n s.archaeologistProfiles[archaeologistAddresses[i]]\r\n .cursedBond += cursedBondIncrease;\r\n\r\n // Rewards are now previous digging fees - difference\r\n s.archaeologistRewards[archaeologistAddresses[i]] += (prevDiggingFees - cursedBondIncrease);\r\n } else if (newDiggingFees < prevDiggingFees) {\r\n // New digging fees are less than the previous digging fees, so some of the cursed bond can be unlocked\r\n uint256 cursedBondDecrease = ((prevDiggingFees - newDiggingFees) *\r\n cursedBondPercentage) / 10000;\r\n\r\n // Decrease archaeologist's cursed bond by the difference\r\n s\r\n .archaeologistProfiles[archaeologistAddresses[i]]\r\n .cursedBond -= cursedBondDecrease;\r\n\r\n // Increase archaeologist's free bond by the difference\r\n s\r\n .archaeologistProfiles[archaeologistAddresses[i]]\r\n .freeBond += cursedBondDecrease;\r\n\r\n // Rewards are equal to the previous digging fees\r\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\r\n } else {\r\n // Rewards are equal to the previous digging fees, the cursed bond can remain the same\r\n s.archaeologistRewards[archaeologistAddresses[i]] += prevDiggingFees;\r\n }\r\n\r\n // Add digging fees due for the new interval\r\n totalDiggingFees += newDiggingFees;\r\n\r\n // If sarcophagus has not been rewrapped yet, pay out the curseFee and unlock the curseFee bond\r\n if (!sarcophagus.isRewrapped) {\r\n // Pay archaeologists the curse fee to their rewards\r\n s.archaeologistRewards[archaeologistAddresses[i]] += cursedArchaeologist.curseFee;\r\n\r\n // Unlock the curseFee cursed bond by debiting the cursed bond and crediting free bond\r\n s.archaeologistProfiles[archaeologistAddresses[i]].cursedBond -= ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\r\n s.archaeologistProfiles[archaeologistAddresses[i]].freeBond += ((cursedArchaeologist.curseFee * cursedBondPercentage) / 10000);\r\n }\r\n }\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n uint256 protocolFees = LibUtils.calculateProtocolFees(totalDiggingFees);\r\n\r\n // Add the protocol fee to the total protocol fees in storage\r\n s.totalProtocolFees += protocolFees;\r\n\r\n // Update the sarcophagus resurrectionTime and previousRewrapTime\r\n sarcophagus.resurrectionTime = resurrectionTime;\r\n sarcophagus.previousRewrapTime = block.timestamp;\r\n\r\n if (!sarcophagus.isRewrapped) {\r\n sarcophagus.isRewrapped = true;\r\n }\r\n\r\n // Transfer the new digging fees and protocol fees from embalmer to contract\r\n s.sarcoToken.transferFrom(msg.sender, address(this), totalDiggingFees + protocolFees);\r\n\r\n emit RewrapSarcophagus(sarcoId, resurrectionTime, totalDiggingFees, protocolFees);\r\n }\r\n\r\n /// @notice Terminates a sarcophagus by setting its resurrection time to infinity and returning locked\r\n /// bonds to all innocent cursed archaeologists. Callable by the embalmer of a sarcophagus if its\r\n /// resurrection time has not passed, it has not been compromised by k or more accusals, and it has not been buried.\r\n /// @param sarcoId the identifier of the sarcophagus\r\n function burySarcophagus(bytes32 sarcoId) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // Confirm the sarcophagus exists\r\n if (sarcophagus.resurrectionTime == 0) {\r\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus has not been compromised\r\n if (sarcophagus.isCompromised) {\r\n revert LibErrors.SarcophagusCompromised(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus is not buried\r\n if (sarcophagus.resurrectionTime == type(uint256).max) {\r\n revert LibErrors.SarcophagusInactive(sarcoId);\r\n }\r\n\r\n // Confirm tx sender is embalmer\r\n if (sarcophagus.embalmerAddress != msg.sender) {\r\n revert LibErrors.SenderNotEmbalmer(msg.sender, sarcophagus.embalmerAddress);\r\n }\r\n // Confirm that the current resurrection time is in the future\r\n if (block.timestamp >= sarcophagus.resurrectionTime) {\r\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\r\n }\r\n\r\n // for each archaeologist on the sarcophagus, unlock bond and pay digging fees\r\n address[] storage archaeologistAddresses = sarcophagus.cursedArchaeologistAddresses;\r\n uint256 nArchAddresses = archaeologistAddresses.length;\r\n for (uint256 i; i < nArchAddresses; ) {\r\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\r\n .cursedArchaeologists[archaeologistAddresses[i]];\r\n\r\n // if the archaeologist hasn't been accused transfer them their digging fees and return their locked bond\r\n if (!cursedArchaeologist.isAccused) {\r\n LibBonds.freeArchaeologist(sarcoId, archaeologistAddresses[i]);\r\n }\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n // Set resurrection time to infinity\r\n sarcophagus.resurrectionTime = type(uint256).max;\r\n\r\n emit BurySarcophagus(sarcoId);\r\n }\r\n}\r\n" - }, - "contracts/facets/ThirdPartyFacet.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport {LibDiamond} from \"hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol\";\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\r\nimport {LibBonds} from \"../libraries/LibBonds.sol\";\r\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\r\nimport \"../storage/LibAppStorage.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\n\r\ncontract ThirdPartyFacet {\r\n event AccuseArchaeologist(\r\n bytes32 indexed sarcoId,\r\n address indexed accuser,\r\n uint256 totalSlashedBondDistributed,\r\n uint256 totalDiggingFeesDistributed,\r\n address[] accusedArchAddresses\r\n );\r\n\r\n event Clean(bytes32 indexed sarcoId, address indexed cleaner);\r\n\r\n /// @notice Clean has been called on a sarcophagus that has already been cleaned\r\n /// @param sarcoId ID of sarcophagus archaeologist has attempted to publish a private key on\r\n error SarcophagusAlreadyCleaned(bytes32 sarcoId);\r\n\r\n /// @notice Clean has been called before the deadline for archaeologists to publish private keys has passed\r\n /// @param currentTime Timestamp of the failed clean attempt\r\n /// @param publishDeadline Latest time an archaeologist may publish a private key on a sarcophagus: resurrectionTime + gracePeriod\r\n error TooEarlyForClean(uint256 currentTime, uint256 publishDeadline);\r\n\r\n /// @notice Clean has been called by someone other than the admin or embalmer of the sarcophagus\r\n /// @param senderAddress Address of sender\r\n error SenderNotEmbalmerOrAdmin(address senderAddress);\r\n\r\n /// @notice Embalmer has attempted to clean a sarcophagus after the embalmerClaimWindow has passed\r\n /// @param currentTime Timestamp of the failed clean attempt\r\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\r\n error EmbalmerClaimWindowPassed(uint256 currentTime, uint256 embalmerClaimWindowEnd);\r\n\r\n /// @notice Admin has attempted to clean a sarcophagus before the embalmerClaimWindow has passed\r\n /// @param currentTime Timestamp of the failed clean attempt\r\n /// @param embalmerClaimWindowEnd Latest time an embalmer may claim residual locked bonds the sarcophagus: resurrectionTime + gracePeriod + embalmerClaimWindow\r\n error TooEarlyForAdminClean(uint256 currentTime, uint256 embalmerClaimWindowEnd);\r\n\r\n /// @notice Emitted when a third party attempts to accuse an archaeologist on a sarcophagus where the resurrection time has already passed\r\n /// @param currentTime Timestamp of the failed accuse attempt\r\n /// @param resurrectionTime Resurrection timestamp which has already passed\r\n error ResurrectionTimeInPast(uint256 currentTime, uint256 resurrectionTime);\r\n\r\n /// @notice Emitted when accuse is called with an unequal numbers of public keys and signatures\r\n /// @param signatures the number of signatures passed into the accuse call\r\n /// @param publicKeys the number of public keys passed into the accuse call\r\n error DifferentNumberOfSignaturesAndPublicKeys(uint256 signatures, uint256 publicKeys);\r\n\r\n /// @notice Emitted when accuse is called with an invalid signature for the supplied sarcoId, paymentAddress, and publicKey\r\n /// @param sarcoId that should have been signed\r\n /// @param paymentAddress payment address that should have been signed\r\n /// @param publicKey publicKey that should be derived from signing key\r\n /// @param signature invalid signature\r\n error InvalidAccusalSignature(\r\n bytes32 sarcoId,\r\n address paymentAddress,\r\n bytes publicKey,\r\n LibTypes.Signature signature\r\n );\r\n\r\n /// @notice If archaeologists fail to publish their private keys on a sarcophagus before the end of the gracePeriod,\r\n /// their locked bonds and diggingFees may be claimed by either the embalmer or the admin\r\n /// embalmers may claim during a limited embalmerClaimWindow after the end of the gracePeriod, after that only the admin will\r\n /// be able to claim remaining locked bond and diggingFees\r\n /// @param sarcoId The identifier of the sarcophagus to clean\r\n function clean(bytes32 sarcoId) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // Confirm the sarcophagus exists\r\n if (sarcophagus.resurrectionTime == 0) {\r\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\r\n }\r\n\r\n // Confirm tx sender is embalmer or admin\r\n if (msg.sender != sarcophagus.embalmerAddress && msg.sender != LibDiamond.contractOwner()) {\r\n revert SenderNotEmbalmerOrAdmin(msg.sender);\r\n }\r\n\r\n // Confirm the sarcophagus has not been compromised\r\n if (sarcophagus.isCompromised) {\r\n revert LibErrors.SarcophagusCompromised(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus is not buried\r\n if (sarcophagus.resurrectionTime == type(uint256).max) {\r\n revert LibErrors.SarcophagusInactive(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus has not already been cleaned\r\n if (sarcophagus.isCleaned) {\r\n revert SarcophagusAlreadyCleaned(sarcoId);\r\n }\r\n\r\n // Confirm that the resurrectionTime + gracePeriod have passed\r\n if (block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod) {\r\n revert TooEarlyForClean(block.timestamp, sarcophagus.resurrectionTime + s.gracePeriod);\r\n }\r\n\r\n // if sender is embalmer, confirm current time is within embalmerClaimWindow\r\n if (\r\n msg.sender == sarcophagus.embalmerAddress &&\r\n block.timestamp > sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\r\n ) {\r\n revert EmbalmerClaimWindowPassed(\r\n block.timestamp,\r\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\r\n );\r\n }\r\n\r\n // if sender is admin, confirm embalmerClaimWindow has passed\r\n if (\r\n msg.sender == LibDiamond.contractOwner() &&\r\n block.timestamp <= sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\r\n ) {\r\n revert TooEarlyForAdminClean(\r\n block.timestamp,\r\n sarcophagus.resurrectionTime + s.gracePeriod + s.embalmerClaimWindow\r\n );\r\n }\r\n\r\n // sum of locked bonds and digging fees for all archaeologists that have failed to publish private keys before publish deadline and have not been accused\r\n uint256 totalDiggingFeesAndLockedBonds;\r\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\r\n\r\n for (uint256 i; i < nCursedArchs; ) {\r\n LibTypes.CursedArchaeologist storage cursedArchaeologist = sarcophagus\r\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]];\r\n\r\n // Punish archaeologists that failed to publish their private key in time\r\n if (!cursedArchaeologist.isAccused && cursedArchaeologist.privateKey == 0) {\r\n uint256 diggingFeesDue = cursedArchaeologist.diggingFeePerSecond *\r\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\r\n\r\n if (!sarcophagus.isRewrapped) {\r\n diggingFeesDue += cursedArchaeologist.curseFee;\r\n }\r\n\r\n uint256 cursedBondDue = (diggingFeesDue * sarcophagus.cursedBondPercentage) / 10000;\r\n totalDiggingFeesAndLockedBonds += diggingFeesDue + cursedBondDue;\r\n\r\n // slash the archaeologist's locked bond for the sarcophagus\r\n s.archaeologistProfiles[sarcophagus.cursedArchaeologistAddresses[i]].cursedBond -= cursedBondDue;\r\n }\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n // Transfer total slashed locked bonds plus digging fees to the embalmer if they are the caller, otherwise add\r\n // this to the contract's protocol fees\r\n if (msg.sender == sarcophagus.embalmerAddress) {\r\n s.sarcoToken.transfer(sarcophagus.embalmerAddress, totalDiggingFeesAndLockedBonds);\r\n } else {\r\n s.totalProtocolFees += totalDiggingFeesAndLockedBonds;\r\n }\r\n\r\n sarcophagus.isCleaned = true;\r\n emit Clean(sarcoId, msg.sender);\r\n }\r\n\r\n /**\r\n * @notice Accuse one or more archaeologists of leaking private keys by submitting signatures on the sarco id\r\n * and payment address generated with the leaked private keys\r\n * If the archaeologists responsible for those private keys haven't already been accused, their locked bond will be\r\n * split between the embalmer and the supplied payment address and digging fees allocated for those archaeologists will be refunded to the embalmer\r\n *\r\n * If k or more archaeologists are accused over the lifetime of a sarcophagus, the sarcophagus\r\n * state will be updated to Accused and bonds for all remaining unaccused archaeologists will be\r\n * returned\r\n *\r\n * @param sarcoId The identifier of the sarcophagus having leaked private keys\r\n * @param publicKeys an array of public keys corresponding to leaked private keys - order must match order of signatures\r\n * @param signatures an array of signatures of the sarcoId and payment address signed by the leaked private keys - order must match order of publicKeys\r\n * @param paymentAddress the address to which rewards should be sent if successful\r\n */\r\n function accuse(\r\n bytes32 sarcoId,\r\n bytes[] calldata publicKeys,\r\n LibTypes.Signature[] calldata signatures,\r\n address paymentAddress\r\n ) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // Confirm sarcophagus exists\r\n if (sarcophagus.resurrectionTime == 0) {\r\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\r\n }\r\n\r\n // verify that current time is not past resurrection time\r\n if (block.timestamp > sarcophagus.resurrectionTime) {\r\n revert ResurrectionTimeInPast(block.timestamp, sarcophagus.resurrectionTime);\r\n }\r\n\r\n // Confirm the sarcophagus has not been compromised\r\n if (sarcophagus.isCompromised) {\r\n revert LibErrors.SarcophagusCompromised(sarcoId);\r\n }\r\n\r\n // Confirm the sarcophagus is not buried\r\n if (sarcophagus.resurrectionTime == type(uint256).max) {\r\n revert LibErrors.SarcophagusInactive(sarcoId);\r\n }\r\n\r\n uint256 nSigs = signatures.length;\r\n\r\n if (nSigs != publicKeys.length) {\r\n revert DifferentNumberOfSignaturesAndPublicKeys(nSigs, publicKeys.length);\r\n }\r\n\r\n address[] memory accusedArchAddresses = new address[](nSigs);\r\n\r\n // track the combined locked bond across all archaeologists being accused in this call\r\n uint256 totalCursedBond;\r\n uint256 accusalCount;\r\n for (uint256 i; i < nSigs; ) {\r\n if (\r\n !LibUtils.verifyAccusalSignature(\r\n sarcoId,\r\n paymentAddress,\r\n publicKeys[i],\r\n signatures[i]\r\n )\r\n ) {\r\n revert InvalidAccusalSignature(\r\n sarcoId,\r\n paymentAddress,\r\n publicKeys[i],\r\n signatures[i]\r\n );\r\n }\r\n\r\n // look up the archaeologist responsible for the publicKey\r\n address accusedArchaeologistAddress = s.publicKeyToArchaeologistAddress[publicKeys[i]];\r\n LibTypes.CursedArchaeologist storage accusedArchaeologist = sarcophagus\r\n .cursedArchaeologists[accusedArchaeologistAddress];\r\n\r\n // verify the accused archaeologist is cursed on the sarcophagus\r\n if (accusedArchaeologist.publicKey.length == 0) {\r\n revert LibErrors.ArchaeologistNotOnSarcophagus(msg.sender);\r\n }\r\n\r\n // if the archaeologist has already been accused on this sarcophagus skip them without taking action\r\n if (accusedArchaeologist.isAccused) {\r\n unchecked {\r\n ++i;\r\n }\r\n continue;\r\n }\r\n\r\n // mark the archaeologist on the sarcophagus as having been accused\r\n accusedArchaeologist.isAccused = true;\r\n accusedArchAddresses[accusalCount++] = accusedArchaeologistAddress;\r\n\r\n uint256 cursedBondDue = ((accusedArchaeologist.diggingFeePerSecond *\r\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime)) *\r\n sarcophagus.cursedBondPercentage) / 10000;\r\n\r\n // If the sarcophagus has not been rewrapped, also slash the curse fee\r\n if (!sarcophagus.isRewrapped) {\r\n cursedBondDue += accusedArchaeologist.curseFee * sarcophagus.cursedBondPercentage / 10000;\r\n }\r\n\r\n totalCursedBond += cursedBondDue;\r\n\r\n // Slash the offending archaeologists bond\r\n s.archaeologistProfiles[accusedArchaeologistAddress].cursedBond -= cursedBondDue;\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n // if none of the accusals were valid because the archaeologists have all already been accused, return without taking action\r\n if (accusalCount == 0) {\r\n return;\r\n }\r\n\r\n {\r\n uint256 nCursedArchs = sarcophagus.cursedArchaeologistAddresses.length;\r\n\r\n // the sarcophagus is compromised if the current call has successfully accused the sss threshold of archaeologists\r\n if (accusalCount >= sarcophagus.threshold) {\r\n sarcophagus.isCompromised = true;\r\n } else {\r\n // if the current call hasn't resulted in at least sss threshold archaeologists being accused\r\n // check if total number of historical accusals on sarcophagus is greater than threshold\r\n uint256 totalAccusals;\r\n\r\n for (uint256 i; i < nCursedArchs; ) {\r\n if (\r\n sarcophagus\r\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\r\n .isAccused\r\n ) {\r\n ++totalAccusals;\r\n }\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n // the sarcophagus is compromised if k or more archaeologists have been accused over the lifetime of the sarcophagus\r\n if (totalAccusals >= sarcophagus.threshold) {\r\n sarcophagus.isCompromised = true;\r\n }\r\n }\r\n\r\n // if k or more archaeologists have been accused over the lifetime of the sarcophagus, funds should\r\n // be returned to the remaining well behaved archaeologists\r\n if (sarcophagus.isCompromised) {\r\n // iterate through all archaeologist addresses on the sarcophagus\r\n for (uint256 i; i < nCursedArchs; ) {\r\n // if the archaeologist has never been accused, release their locked bond back to them\r\n if (\r\n !sarcophagus\r\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\r\n .isAccused\r\n ) {\r\n LibBonds.freeArchaeologist(\r\n sarcoId,\r\n sarcophagus.cursedArchaeologistAddresses[i]\r\n );\r\n }\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n }\r\n }\r\n\r\n uint256 halfTotalCursedBond = totalCursedBond >> 1;\r\n uint256 totalDiggingFees = totalCursedBond / (sarcophagus.cursedBondPercentage / 10000);\r\n // transfer the cursed half, plus the current digging fees, to the embalmer\r\n s.sarcoToken.transfer(\r\n sarcophagus.embalmerAddress,\r\n totalDiggingFees + halfTotalCursedBond\r\n );\r\n\r\n // transfer the other half of the cursed bond to the transaction caller\r\n s.sarcoToken.transfer(paymentAddress, halfTotalCursedBond);\r\n\r\n emit AccuseArchaeologist(\r\n sarcoId,\r\n msg.sender,\r\n totalCursedBond,\r\n totalDiggingFees,\r\n accusedArchAddresses\r\n );\r\n }\r\n}\r\n" - }, - "contracts/facets/ViewStateFacet.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"../libraries/LibTypes.sol\";\r\nimport \"../libraries/LibUtils.sol\";\r\nimport \"../storage/LibAppStorage.sol\";\r\n\r\ncontract ViewStateFacet {\r\n /// @notice Get the admin address from diamond storage\r\n /// @return The admin address\r\n function getAdmin() external view returns (address) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.admin;\r\n }\r\n\r\n /// @notice Gets the total protocol fees from diamond storage\r\n /// @return The total protocol fees\r\n function getTotalProtocolFees() external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.totalProtocolFees;\r\n }\r\n\r\n /// @notice Get the protocol fee base percentage from diamond storage\r\n /// @return The protocol fee base percentage - protocolFeeBasePercentage\r\n function getProtocolFeeBasePercentage() external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.protocolFeeBasePercentage;\r\n }\r\n\r\n /// @notice Get the cursed bond percentage from diamond storage\r\n /// @return The cursed bond percentage - cursedBondPercentage\r\n function getCursedBondPercentage() external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.cursedBondPercentage;\r\n }\r\n\r\n /// @notice Gets archaeologist profiles given a list of archaeologist addresses.\r\n /// If an invalid address is included, simply leaves it out of the list.\r\n /// @param addresses The list of archaeologist addresses\r\n /// @return The list of archaeologist profiles\r\n function getArchaeologistProfiles(\r\n address[] memory addresses\r\n ) external view returns (LibTypes.ArchaeologistProfile[] memory) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n uint256 nAddresses = addresses.length;\r\n LibTypes.ArchaeologistProfile[] memory profiles = new LibTypes.ArchaeologistProfile[](\r\n nAddresses\r\n );\r\n\r\n for (uint256 i; i < nAddresses; ) {\r\n // Skip unregistered archaeologists\r\n if (s.archaeologistProfiles[addresses[i]].maximumRewrapInterval == 0) {\r\n continue;\r\n }\r\n profiles[i] = s.archaeologistProfiles[addresses[i]];\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n return profiles;\r\n }\r\n\r\n /// @notice Gets the grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time passes\r\n /// @return The resurrection grace period\r\n function getGracePeriod() external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.gracePeriod;\r\n }\r\n\r\n /// @notice Gets the window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys\r\n /// @return The embalmer claim window\r\n function getEmbalmerClaimWindow() external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.embalmerClaimWindow;\r\n }\r\n\r\n /// @notice Gets the expiration threshold after which a sarcophagus must be renegotiated\r\n /// @return The expiration threshold\r\n function getExpirationThreshold() external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.expirationThreshold;\r\n }\r\n\r\n /// @notice Given an archaeologist address, return that archaeologist's\r\n /// profile\r\n /// @param archaeologist The archaeologist account's address\r\n /// @return the Archaeologist object\r\n function getArchaeologistProfile(\r\n address archaeologist\r\n ) external view returns (LibTypes.ArchaeologistProfile memory) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibUtils.revertIfArchProfileDoesNotExist(archaeologist);\r\n return s.archaeologistProfiles[archaeologist];\r\n }\r\n\r\n /// @notice Return the list of registereed archaeologist addresses.\r\n /// @return addresses of registered archaeologists\r\n function getArchaeologistProfileAddresses() external view returns (address[] memory) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.archaeologistProfileAddresses;\r\n }\r\n\r\n /// @notice Given an index (of the full archaeologist array), return the\r\n /// archaeologist address at that index\r\n /// @param index The index of the registered archaeologist\r\n /// @return address of the archaeologist\r\n function getArchaeologistProfileAddressAtIndex(uint256 index) external view returns (address) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.archaeologistProfileAddresses[index];\r\n }\r\n\r\n /// @notice Returns the amount of free bond stored in the contract for an\r\n /// archaeologist.\r\n /// @param archaeologist The address of the archaeologist whose\r\n /// free bond is being returned\r\n function getFreeBond(address archaeologist) external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.archaeologistProfiles[archaeologist].freeBond;\r\n }\r\n\r\n /// @notice Returns the amount of rewards stored in the contract for an\r\n /// archaeologist.\r\n /// @param archaeologist The address of the archaeologist whose\r\n /// reward is being returned\r\n function getRewards(address archaeologist) external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.archaeologistRewards[archaeologist];\r\n }\r\n\r\n /// @notice Returns the amount of cursed bond stored in the contract for an\r\n /// archaeologist.\r\n /// @param archaeologist The address of the archaeologist whose\r\n /// cursed bond is being returned\r\n function getCursedBond(address archaeologist) external view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.archaeologistProfiles[archaeologist].cursedBond;\r\n }\r\n\r\n struct SarcophagusResponse {\r\n uint256 resurrectionTime;\r\n uint256 previousRewrapTime;\r\n bool isCompromised;\r\n bool isCleaned;\r\n string name;\r\n uint8 threshold;\r\n uint256 maximumRewrapInterval;\r\n uint256 maximumResurrectionTime;\r\n uint256 cursedBondPercentage;\r\n string arweaveTxId;\r\n address embalmerAddress;\r\n address recipientAddress;\r\n address[] archaeologistAddresses;\r\n uint8 publishedPrivateKeyCount;\r\n bool hasLockedBond;\r\n }\r\n\r\n /// @notice Returns data on the sarcophagus with the supplied id\r\n /// includes aggregate data on cursed archaeologists associated with the sarcophagus\r\n /// - publishedPrivateKeyCount - the total number of private keys published by archaeologists on the sarcophagus\r\n /// - hasLockedBond - true if archaeologists still have bond locked in the contract for this sarcophagus\r\n /// @param sarcoId The identifier of the sarcophagus being returned\r\n function getSarcophagus(bytes32 sarcoId) external view returns (SarcophagusResponse memory) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n // Confirm sarcophagus exists\r\n if (sarcophagus.resurrectionTime == 0) {\r\n revert LibErrors.SarcophagusDoesNotExist(sarcoId);\r\n }\r\n\r\n uint8 publishedPrivateKeyCount;\r\n bool hasLockedBond;\r\n uint256 archsLength = sarcophagus.cursedArchaeologistAddresses.length;\r\n for (uint256 i; i < archsLength; ) {\r\n // archaeologist has published a private key\r\n if (\r\n sarcophagus\r\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\r\n .privateKey != 0\r\n ) {\r\n ++publishedPrivateKeyCount;\r\n } else if (\r\n !sarcophagus\r\n .cursedArchaeologists[sarcophagus.cursedArchaeologistAddresses[i]]\r\n .isAccused &&\r\n !sarcophagus.isCompromised &&\r\n !sarcophagus.isCleaned &&\r\n sarcophagus.resurrectionTime != type(uint256).max\r\n ) {\r\n // if the sarcophagus is not compromised, buried, or cleaned and\r\n // one or more unaccused archaeologists hasn't published a private key there is locked bond on the sarcophagus\r\n hasLockedBond = true;\r\n }\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n return\r\n SarcophagusResponse({\r\n resurrectionTime: sarcophagus.resurrectionTime,\r\n previousRewrapTime: sarcophagus.previousRewrapTime,\r\n isCompromised: sarcophagus.isCompromised,\r\n isCleaned: sarcophagus.isCleaned,\r\n name: sarcophagus.name,\r\n threshold: sarcophagus.threshold,\r\n maximumRewrapInterval: sarcophagus.maximumRewrapInterval,\r\n maximumResurrectionTime: sarcophagus.maximumResurrectionTime,\r\n cursedBondPercentage: sarcophagus.cursedBondPercentage,\r\n arweaveTxId: sarcophagus.arweaveTxId,\r\n embalmerAddress: sarcophagus.embalmerAddress,\r\n recipientAddress: sarcophagus.recipientAddress,\r\n archaeologistAddresses: sarcophagus.cursedArchaeologistAddresses,\r\n publishedPrivateKeyCount: publishedPrivateKeyCount,\r\n hasLockedBond: hasLockedBond\r\n });\r\n }\r\n\r\n /// @notice Returns the data stored on a sarcophagus for an archaeologist.\r\n /// @param sarcoId The identifier of the sarcophagus whose data is being\r\n /// returned\r\n /// @param archaeologist The address of the archaeologist whose data is\r\n /// being returned\r\n function getSarcophagusArchaeologist(\r\n bytes32 sarcoId,\r\n address archaeologist\r\n ) external view returns (LibTypes.CursedArchaeologist memory) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n return s.sarcophagi[sarcoId].cursedArchaeologists[archaeologist];\r\n }\r\n}\r\n" - }, - "contracts/libraries/LibBonds.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"../storage/LibAppStorage.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\nimport {LibErrors} from \"./LibErrors.sol\";\r\n\r\nimport \"../facets/EmbalmerFacet.sol\";\r\n\r\nlibrary LibBonds {\r\n /// @notice Bonds the archaeologist to a sarcophagus.\r\n /// This does the following:\r\n /// - adds the archaeologist's curse params and address to the sarcophagus\r\n /// - calculates digging fees to be locked and later paid to archaeologist (includes curseFee)\r\n /// - locks this amount from archaeologist's free bond; increases cursedBond by same\r\n /// - Adds the sarcophagus' id to the archaeologist's record of bonded sarcophagi\r\n /// @param sarcoId Id of the sarcophagus with which to curse the archaeologist\r\n /// @param archaeologist The archaeologist to curse, with associated parameters of the curse\r\n ///\r\n /// @return the amount of digging fees due the embalmer for this curse\r\n function curseArchaeologist(\r\n bytes32 sarcoId,\r\n EmbalmerFacet.CurseParams calldata archaeologist,\r\n uint256 index\r\n ) internal returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n sarcophagus.cursedArchaeologists[archaeologist.archAddress] = LibTypes.CursedArchaeologist({\r\n publicKey: archaeologist.publicKey,\r\n privateKey: 0,\r\n isAccused: false,\r\n diggingFeePerSecond: archaeologist.diggingFeePerSecond,\r\n curseFee: archaeologist.curseFee\r\n });\r\n sarcophagus.cursedArchaeologistAddresses[index] = archaeologist.archAddress;\r\n\r\n // Calculate digging fees due for this time period (creationTime/previousRewrapTime -> resurrectionTime)\r\n uint256 diggingFeesDue = (archaeologist.diggingFeePerSecond *\r\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime))\r\n + archaeologist.curseFee;\r\n\r\n // Use cursed bond percentage to determine how much bond to lock up\r\n uint256 bondToCurse = (((diggingFeesDue) * s.cursedBondPercentage) / 10000);\r\n\r\n // Transfer bond to curse from free bond to cursed bond\r\n s.archaeologistProfiles[archaeologist.archAddress].freeBond -= bondToCurse;\r\n s.archaeologistProfiles[archaeologist.archAddress].cursedBond += bondToCurse;\r\n\r\n return diggingFeesDue;\r\n }\r\n\r\n /// @notice Calculates and unlocks an archaeologist's cursed bond. Pays due digging fees to the archaeologist.\r\n /// @param sarcoId the identifier of the sarcophagus to free the archaeologist from\r\n /// @param archaeologistAddress the address of the archaeologist to free\r\n function freeArchaeologist(bytes32 sarcoId, address archaeologistAddress) internal {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n LibTypes.Sarcophagus storage sarcophagus = s.sarcophagi[sarcoId];\r\n\r\n LibTypes.CursedArchaeologist storage cursedArchaeologist = s\r\n .sarcophagi[sarcoId]\r\n .cursedArchaeologists[archaeologistAddress];\r\n\r\n // Calculate the digging fees to be paid since the last rewrap (or creation)\r\n uint256 diggingFeeAmount = cursedArchaeologist.diggingFeePerSecond *\r\n (sarcophagus.resurrectionTime - sarcophagus.previousRewrapTime);\r\n\r\n // If sarcophagus has not be been rewrapped yet, pay out the curseFee\r\n if (!sarcophagus.isRewrapped) {\r\n diggingFeeAmount += cursedArchaeologist.curseFee;\r\n }\r\n\r\n uint256 cursedBondAmount = (diggingFeeAmount * sarcophagus.cursedBondPercentage) / 10000;\r\n\r\n s.archaeologistProfiles[archaeologistAddress].cursedBond -= cursedBondAmount;\r\n s.archaeologistProfiles[archaeologistAddress].freeBond += cursedBondAmount;\r\n\r\n s.archaeologistRewards[archaeologistAddress] += diggingFeeAmount;\r\n }\r\n}\r\n" - }, - "contracts/libraries/LibErrors.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\n/**\r\n * @title A collection of Errors\r\n * @notice This library defines all of the Errors that the Sarcophagus system\r\n * uses.\r\n */\r\nlibrary LibErrors {\r\n error ArchaeologistNotOnSarcophagus(address archaeologist);\r\n\r\n error NotEnoughCursedBond(uint256 cursedBond, uint256 amount);\r\n\r\n error NotEnoughFreeBond(uint256 freeBond, uint256 amount);\r\n\r\n error ArchaeologistProfileExistsShouldBe(bool exists, address archaeologist);\r\n\r\n error SarcophagusDoesNotExist(bytes32 sarcoId);\r\n\r\n error SarcophagusInactive(bytes32 sarcoId);\r\n\r\n error SarcophagusCompromised(bytes32 sarcoId);\r\n\r\n error SenderNotEmbalmer(address sender, address embalmer);\r\n\r\n error InvalidSignature(\r\n // address recovered from signature via ecrecover\r\n address recoveredAddress,\r\n // address we expected to have signed the data\r\n address expectedAddress\r\n );\r\n}\r\n" - }, - "contracts/libraries/LibPrivateKeys.sol": { - "content": "// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.18;\r\n\r\n/**\r\n * @title Private key verification\r\n * @notice Implements a private key -> public key checking function\r\n * @dev modified from https://github.com/1Address/ecsol, removes extra code\r\n * which isn't necessary for our Sarcophagus implementation\r\n */\r\nlibrary LibPrivateKeys {\r\n /**\r\n * @notice Given a private key and a public key, determines if that public\r\n * key was derived from the private key\r\n * @dev based on https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9\r\n * @param privKey an secp256k1 private key\r\n * @param pubKey an uncompressed 65 byte secp256k1 public key\r\n * @return bool indicating whether the public key is derived from the\r\n * private key\r\n */\r\n function isPublicKeyOfPrivateKey(\r\n bytes32 privKey,\r\n bytes storage pubKey\r\n ) internal view returns (bool) {\r\n // removes the 0x04 prefix from an uncompressed public key\r\n uint256 pubKeyLength = pubKey.length;\r\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\r\n for (uint256 i = 1; i < pubKeyLength; ) {\r\n truncatedPublicKey[i - 1] = pubKey[i];\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n\r\n // generator point coordinates and order of secp256k1\r\n uint256 gx = 0x79BE667EF9DCBBAC55A06295CE870B07029BFCDB2DCE28D959F2815B16F81798;\r\n uint256 gy = 0x483ADA7726A3C4655DA4FBFC0E1108A8FD17B448A68554199C47D08FFB10D4B8;\r\n uint256 m = 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;\r\n\r\n address signer = ecrecover(\r\n 0,\r\n gy % 2 != 0 ? 28 : 27,\r\n bytes32(gx),\r\n bytes32(mulmod(uint256(privKey), gx, m))\r\n );\r\n\r\n address xyAddress = address(\r\n uint160(\r\n uint256(keccak256(truncatedPublicKey)) &\r\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r\n )\r\n );\r\n return xyAddress == signer;\r\n }\r\n}\r\n" - }, - "contracts/libraries/LibTypes.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\n/**\r\n * @title Types shared across facets for the Sarcophagus diamond\r\n */\r\nlibrary LibTypes {\r\n struct Sarcophagus {\r\n // Also used for existence checks -- does not exist if 0\r\n uint256 resurrectionTime;\r\n uint256 previousRewrapTime;\r\n // todo: run gas cost evaluation on storing isCompromised vs looping through stored archaeologists and checking isAccused\r\n bool isCompromised;\r\n bool isCleaned;\r\n bool isRewrapped;\r\n uint8 threshold;\r\n string name;\r\n uint256 maximumRewrapInterval;\r\n uint256 maximumResurrectionTime;\r\n string arweaveTxId;\r\n address embalmerAddress;\r\n address recipientAddress;\r\n address[] cursedArchaeologistAddresses;\r\n mapping(address => CursedArchaeologist) cursedArchaeologists;\r\n uint256 cursedBondPercentage;\r\n }\r\n\r\n struct CursedArchaeologist {\r\n uint256 diggingFeePerSecond;\r\n // Also used for publish checks -- has not published if 0\r\n bytes32 privateKey;\r\n // Also used for curse checks -- is not bonded if length is 0\r\n bytes publicKey;\r\n bool isAccused;\r\n uint256 curseFee;\r\n }\r\n\r\n struct Signature {\r\n uint8 v;\r\n bytes32 r;\r\n bytes32 s;\r\n }\r\n\r\n struct ArchaeologistProfile {\r\n // Also used for existence checks -- does not exist if 0\r\n uint256 maximumRewrapInterval;\r\n uint256 maximumResurrectionTime;\r\n string peerId;\r\n uint256 minimumDiggingFeePerSecond;\r\n uint256 freeBond;\r\n uint256 cursedBond;\r\n uint256 curseFee;\r\n }\r\n}\r\n" - }, - "contracts/libraries/LibUtils.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"../storage/LibAppStorage.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\nimport {LibErrors} from \"../libraries/LibErrors.sol\";\r\nimport \"../facets/ThirdPartyFacet.sol\";\r\nimport \"./LibTypes.sol\";\r\nimport \"../facets/EmbalmerFacet.sol\";\r\n\r\n/**\r\n * @title Utility functions used within the Sarcophagus system\r\n * @notice This library implements various functions that are used throughout\r\n * Sarcophagus, mainly to DRY up the codebase\r\n * @dev these functions are all stateless, public, pure/view\r\n */\r\nlibrary LibUtils {\r\n /**\r\n * @notice The archaeologist needs to sign off on two pieces of data\r\n * to guarantee their unrwap will be successful\r\n *\r\n * @param agreedMaximumRewrapInterval that the archaeologist has agreed to for the sarcophagus\r\n * @param timestamp that the archaeologist has agreed to for the sarcophagus\r\n * @param curseParams parameters of curse signed by archaeologist\r\n */\r\n function verifyArchaeologistSignature(\r\n uint256 agreedMaximumRewrapInterval,\r\n uint256 maximumResurrectionTime,\r\n uint256 timestamp,\r\n EmbalmerFacet.CurseParams calldata curseParams\r\n ) internal pure {\r\n // Hash the hash of the data payload\r\n bytes32 messageHash = keccak256(\r\n abi.encodePacked(\r\n \"\\x19Ethereum Signed Message:\\n32\",\r\n keccak256(\r\n abi.encode(\r\n curseParams.publicKey,\r\n agreedMaximumRewrapInterval,\r\n maximumResurrectionTime,\r\n curseParams.diggingFeePerSecond,\r\n timestamp,\r\n curseParams.curseFee\r\n )\r\n )\r\n )\r\n );\r\n\r\n // Generate the address from the signature.\r\n // ecrecover should always return a valid address.\r\n address recoveredAddress = ecrecover(\r\n messageHash,\r\n curseParams.v,\r\n curseParams.r,\r\n curseParams.s\r\n );\r\n\r\n if (recoveredAddress != curseParams.archAddress) {\r\n revert LibErrors.InvalidSignature(recoveredAddress, curseParams.archAddress);\r\n }\r\n }\r\n\r\n /// @notice Verifies that a signature and public key were created from the same private key\r\n /// @param sarcoId the sarcoId that was signed\r\n /// @param paymentAddress the payment address that was signed\r\n /// @param publicKey an uncompressed 65 byte secp256k1 public key\r\n /// @param signature signature on the sarco id and payment address\r\n /// @return true if the signature was signed by the private key corresponding to the supplied public key\r\n function verifyAccusalSignature(\r\n bytes32 sarcoId,\r\n address paymentAddress,\r\n bytes calldata publicKey,\r\n LibTypes.Signature calldata signature\r\n ) internal pure returns (bool) {\r\n // removes the 0x04 prefix from an uncompressed public key\r\n uint256 pubKeyLength = publicKey.length;\r\n bytes memory truncatedPublicKey = new bytes(pubKeyLength - 1);\r\n for (uint256 i = 1; i < pubKeyLength; ) {\r\n truncatedPublicKey[i - 1] = publicKey[i];\r\n unchecked {\r\n ++i;\r\n }\r\n }\r\n bytes32 messageHash = keccak256(\r\n abi.encodePacked(\r\n \"\\x19Ethereum Signed Message:\\n32\",\r\n keccak256(abi.encode(sarcoId, paymentAddress))\r\n )\r\n );\r\n // Use ecrecover to get the address that signed the message\r\n address signingAddress = ecrecover(messageHash, signature.v, signature.r, signature.s);\r\n\r\n address publicKeyAddress = address(\r\n uint160(\r\n uint256(keccak256(truncatedPublicKey)) &\r\n 0x00FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\r\n )\r\n );\r\n\r\n return signingAddress == publicKeyAddress;\r\n }\r\n\r\n /// @notice Checks if an archaeologist profile exists and\r\n /// reverts if so\r\n ///\r\n /// @param archaeologist the archaeologist address to check existence of\r\n function revertIfArchProfileExists(address archaeologist) internal view {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n\r\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval != 0) {\r\n revert LibErrors.ArchaeologistProfileExistsShouldBe(false, archaeologist);\r\n }\r\n }\r\n\r\n /// @notice Checks if an archaeologist profile doesn't exist and reverts if so\r\n ///\r\n /// @param archaeologist the archaeologist address to check lack of existence of\r\n function revertIfArchProfileDoesNotExist(address archaeologist) internal view {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n\r\n if (s.archaeologistProfiles[archaeologist].maximumRewrapInterval == 0) {\r\n revert LibErrors.ArchaeologistProfileExistsShouldBe(true, archaeologist);\r\n }\r\n }\r\n\r\n /// @notice Calculates the protocol fees to be taken from the embalmer.\r\n /// @param totalDiggingFees to be paid. Protocol fee is a percentage of this\r\n /// @return The protocol fees amount\r\n function calculateProtocolFees(uint256 totalDiggingFees) internal view returns (uint256) {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n\r\n return (totalDiggingFees * s.protocolFeeBasePercentage) / 10000;\r\n }\r\n}\r\n" - }, - "contracts/mocks/SarcoTokenMock.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\r\n\r\ncontract SarcoTokenMock is ERC20 {\r\n constructor() ERC20(\"SARCOMock\", \"Sarcophagus Mock\") {\r\n _mint(msg.sender, 100 * 10 ** 6 * 10 ** 18);\r\n }\r\n}\r\n" - }, - "contracts/proxy/LibPrivateKeysProxy.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport {LibPrivateKeys} from \"../libraries/LibPrivateKeys.sol\";\r\n\r\ncontract LibPrivateKeysTest {\r\n bytes storedPublicKey;\r\n\r\n event True();\r\n event False();\r\n\r\n function keyVerification(bytes32 privKey, bytes calldata pubKey) public {\r\n storedPublicKey = pubKey;\r\n if (LibPrivateKeys.isPublicKeyOfPrivateKey(privKey, storedPublicKey)) {\r\n emit True();\r\n } else {\r\n emit False();\r\n }\r\n }\r\n}\r\n" - }, - "contracts/proxy/LibUtilsProxy.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport {LibUtils} from \"../libraries/LibUtils.sol\";\r\nimport {LibTypes} from \"../libraries/LibTypes.sol\";\r\n\r\ncontract LibUtilsTest {\r\n function verifySignature(\r\n bytes32 sarcoId,\r\n address paymentAddress,\r\n bytes calldata publicKey,\r\n LibTypes.Signature calldata signature\r\n ) external pure returns (bool) {\r\n return LibUtils.verifyAccusalSignature(sarcoId, paymentAddress, publicKey, signature);\r\n }\r\n}\r\n" - }, - "contracts/storage/AppStorageInit.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"./LibAppStorage.sol\";\r\n\r\ncontract AppStorageInit {\r\n /// @notice Initializes the app with default state values\r\n /// @dev Add any AppStorage struct properties here to initialize values\r\n function init(\r\n IERC20 sarcoToken,\r\n address admin,\r\n uint256 protocolFeeBasePercentage,\r\n uint256 cursedBondPercentage,\r\n uint256 gracePeriod,\r\n uint256 embalmerClaimWindow,\r\n uint256 expirationThreshold\r\n ) external {\r\n AppStorage storage s = LibAppStorage.getAppStorage();\r\n\r\n s.sarcoToken = sarcoToken;\r\n s.admin = admin;\r\n s.protocolFeeBasePercentage = protocolFeeBasePercentage;\r\n s.cursedBondPercentage = cursedBondPercentage;\r\n s.gracePeriod = gracePeriod;\r\n s.embalmerClaimWindow = embalmerClaimWindow;\r\n s.expirationThreshold = expirationThreshold;\r\n }\r\n}\r\n" - }, - "contracts/storage/LibAppStorage.sol": { - "content": "// SPDX-License-Identifier: Unlicense\r\npragma solidity 0.8.18;\r\n\r\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\r\nimport \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\r\nimport \"../libraries/LibTypes.sol\";\r\n\r\n/**\r\n * Global diamond storage struct to be shared across facets\r\n * TODO: Implement diamond storage pattern and consider splitting storage into facet specific structs\r\n */\r\nstruct AppStorage {\r\n // SARCO token contract\r\n IERC20 sarcoToken;\r\n // The Admin address allowed to call Admin Facet functions\r\n address admin;\r\n // total protocol fees available to be withdrawn by the admin\r\n uint256 totalProtocolFees;\r\n /**\r\n * Protocol level admin configurations\r\n */\r\n // % of total digging fees for sarcophagus to charge embalmer on create and rewrap. Denominator is 10000\r\n uint256 protocolFeeBasePercentage;\r\n // % of digging fees archaeologists must have locked up per curse in cursed bond. Denominator is 10000\r\n uint256 cursedBondPercentage;\r\n // grace period an archaeologist is given to resurrect a sarcophagus after the resurrection time. Specified in seconds\r\n uint256 gracePeriod;\r\n // threshold after which archaeologist signatures on sarcophagus params expire and the sarcophagus must be renegotiated. Specified in seconds\r\n uint256 expirationThreshold;\r\n // window after end of gracePeriod + resurrectionTime where embalmer can claim remaining bonds from archaeologists that have failed to publish private keys. Specified in seconds\r\n uint256 embalmerClaimWindow;\r\n // registered archaeologist addresses\r\n address[] archaeologistProfileAddresses;\r\n // public key => archaeologist address\r\n mapping(bytes => address) publicKeyToArchaeologistAddress;\r\n // sarcophagus id => sarcophagus object\r\n mapping(bytes32 => LibTypes.Sarcophagus) sarcophagi;\r\n // archaeologist address => profile\r\n mapping(address => LibTypes.ArchaeologistProfile) archaeologistProfiles;\r\n // current balance of rewards available for the archaeologist to withdraw\r\n mapping(address => uint256) archaeologistRewards;\r\n}\r\n\r\nlibrary LibAppStorage {\r\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\"sarcophagus.storage.1\");\r\n\r\n function getAppStorage() internal pure returns (AppStorage storage s) {\r\n bytes32 position = DIAMOND_STORAGE_POSITION;\r\n assembly {\r\n s.slot := position\r\n }\r\n }\r\n}\r\n" - }, - "hardhat-deploy/solc_0.8/diamond/interfaces/IDiamondCut.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\n\ninterface IDiamondCut {\n enum FacetCutAction {Add, Replace, Remove}\n // Add=0, Replace=1, Remove=2\n\n struct FacetCut {\n address facetAddress;\n FacetCutAction action;\n bytes4[] functionSelectors;\n }\n\n /// @notice Add/replace/remove any number of functions and optionally execute\n /// a function with delegatecall\n /// @param _diamondCut Contains the facet addresses and function selectors\n /// @param _init The address of the contract or facet to execute _calldata\n /// @param _calldata A function call, including function selector and arguments\n /// _calldata is executed with delegatecall on _init\n function diamondCut(\n FacetCut[] calldata _diamondCut,\n address _init,\n bytes calldata _calldata\n ) external;\n\n event DiamondCut(FacetCut[] _diamondCut, address _init, bytes _calldata);\n}\n" - }, - "hardhat-deploy/solc_0.8/diamond/libraries/LibDiamond.sol": { - "content": "// SPDX-License-Identifier: MIT\npragma solidity ^0.8.0;\n\n/******************************************************************************\\\n* Author: Nick Mudge (https://twitter.com/mudgen)\n* EIP-2535 Diamonds: https://eips.ethereum.org/EIPS/eip-2535\n/******************************************************************************/\nimport { IDiamondCut } from \"../interfaces/IDiamondCut.sol\";\n\nlibrary LibDiamond {\n bytes32 constant DIAMOND_STORAGE_POSITION = keccak256(\"diamond.standard.diamond.storage\");\n\n struct FacetAddressAndPosition {\n address facetAddress;\n uint96 functionSelectorPosition; // position in facetFunctionSelectors.functionSelectors array\n }\n\n struct FacetFunctionSelectors {\n bytes4[] functionSelectors;\n uint256 facetAddressPosition; // position of facetAddress in facetAddresses array\n }\n\n struct DiamondStorage {\n // maps function selector to the facet address and\n // the position of the selector in the facetFunctionSelectors.selectors array\n mapping(bytes4 => FacetAddressAndPosition) selectorToFacetAndPosition;\n // maps facet addresses to function selectors\n mapping(address => FacetFunctionSelectors) facetFunctionSelectors;\n // facet addresses\n address[] facetAddresses;\n // Used to query if a contract implements an interface.\n // Used to implement ERC-165.\n mapping(bytes4 => bool) supportedInterfaces;\n // owner of the contract\n address contractOwner;\n }\n\n function diamondStorage() internal pure returns (DiamondStorage storage ds) {\n bytes32 position = DIAMOND_STORAGE_POSITION;\n assembly {\n ds.slot := position\n }\n }\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n function setContractOwner(address _newOwner) internal {\n DiamondStorage storage ds = diamondStorage();\n address previousOwner = ds.contractOwner;\n ds.contractOwner = _newOwner;\n emit OwnershipTransferred(previousOwner, _newOwner);\n }\n\n function contractOwner() internal view returns (address contractOwner_) {\n contractOwner_ = diamondStorage().contractOwner;\n }\n\n function enforceIsContractOwner() internal view {\n require(msg.sender == diamondStorage().contractOwner, \"LibDiamond: Must be contract owner\");\n }\n\n event DiamondCut(IDiamondCut.FacetCut[] _diamondCut, address _init, bytes _calldata);\n\n // Internal function version of diamondCut\n function diamondCut(\n IDiamondCut.FacetCut[] memory _diamondCut,\n address _init,\n bytes memory _calldata\n ) internal {\n for (uint256 facetIndex; facetIndex < _diamondCut.length; facetIndex++) {\n IDiamondCut.FacetCutAction action = _diamondCut[facetIndex].action;\n if (action == IDiamondCut.FacetCutAction.Add) {\n addFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Replace) {\n replaceFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else if (action == IDiamondCut.FacetCutAction.Remove) {\n removeFunctions(_diamondCut[facetIndex].facetAddress, _diamondCut[facetIndex].functionSelectors);\n } else {\n revert(\"LibDiamondCut: Incorrect FacetCutAction\");\n }\n }\n emit DiamondCut(_diamondCut, _init, _calldata);\n initializeDiamondCut(_init, _calldata);\n }\n\n function addFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n require(_functionSelectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n DiamondStorage storage ds = diamondStorage(); \n require(_facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress); \n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress == address(0), \"LibDiamondCut: Can't add function that already exists\");\n addFunction(ds, selector, selectorPosition, _facetAddress);\n selectorPosition++;\n }\n }\n\n function replaceFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n require(_functionSelectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n DiamondStorage storage ds = diamondStorage();\n require(_facetAddress != address(0), \"LibDiamondCut: Add facet can't be address(0)\");\n uint96 selectorPosition = uint96(ds.facetFunctionSelectors[_facetAddress].functionSelectors.length);\n // add new facet address if it does not exist\n if (selectorPosition == 0) {\n addFacet(ds, _facetAddress);\n }\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n require(oldFacetAddress != _facetAddress, \"LibDiamondCut: Can't replace function with same function\");\n removeFunction(ds, oldFacetAddress, selector);\n addFunction(ds, selector, selectorPosition, _facetAddress);\n selectorPosition++;\n }\n }\n\n function removeFunctions(address _facetAddress, bytes4[] memory _functionSelectors) internal {\n require(_functionSelectors.length > 0, \"LibDiamondCut: No selectors in facet to cut\");\n DiamondStorage storage ds = diamondStorage();\n // if function does not exist then do nothing and return\n require(_facetAddress == address(0), \"LibDiamondCut: Remove facet address must be address(0)\");\n for (uint256 selectorIndex; selectorIndex < _functionSelectors.length; selectorIndex++) {\n bytes4 selector = _functionSelectors[selectorIndex];\n address oldFacetAddress = ds.selectorToFacetAndPosition[selector].facetAddress;\n removeFunction(ds, oldFacetAddress, selector);\n }\n }\n\n function addFacet(DiamondStorage storage ds, address _facetAddress) internal {\n enforceHasContractCode(_facetAddress, \"LibDiamondCut: New facet has no code\");\n ds.facetFunctionSelectors[_facetAddress].facetAddressPosition = ds.facetAddresses.length;\n ds.facetAddresses.push(_facetAddress);\n } \n\n\n function addFunction(DiamondStorage storage ds, bytes4 _selector, uint96 _selectorPosition, address _facetAddress) internal {\n ds.selectorToFacetAndPosition[_selector].functionSelectorPosition = _selectorPosition;\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.push(_selector);\n ds.selectorToFacetAndPosition[_selector].facetAddress = _facetAddress;\n }\n\n function removeFunction(DiamondStorage storage ds, address _facetAddress, bytes4 _selector) internal { \n require(_facetAddress != address(0), \"LibDiamondCut: Can't remove function that doesn't exist\");\n // an immutable function is a function defined directly in a diamond\n require(_facetAddress != address(this), \"LibDiamondCut: Can't remove immutable function\");\n // replace selector with last selector, then delete last selector\n uint256 selectorPosition = ds.selectorToFacetAndPosition[_selector].functionSelectorPosition;\n uint256 lastSelectorPosition = ds.facetFunctionSelectors[_facetAddress].functionSelectors.length - 1;\n // if not the same then replace _selector with lastSelector\n if (selectorPosition != lastSelectorPosition) {\n bytes4 lastSelector = ds.facetFunctionSelectors[_facetAddress].functionSelectors[lastSelectorPosition];\n ds.facetFunctionSelectors[_facetAddress].functionSelectors[selectorPosition] = lastSelector;\n ds.selectorToFacetAndPosition[lastSelector].functionSelectorPosition = uint96(selectorPosition);\n }\n // delete the last selector\n ds.facetFunctionSelectors[_facetAddress].functionSelectors.pop();\n delete ds.selectorToFacetAndPosition[_selector];\n\n // if no more selectors for facet address then delete the facet address\n if (lastSelectorPosition == 0) {\n // replace facet address with last facet address and delete last facet address\n uint256 lastFacetAddressPosition = ds.facetAddresses.length - 1;\n uint256 facetAddressPosition = ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\n if (facetAddressPosition != lastFacetAddressPosition) {\n address lastFacetAddress = ds.facetAddresses[lastFacetAddressPosition];\n ds.facetAddresses[facetAddressPosition] = lastFacetAddress;\n ds.facetFunctionSelectors[lastFacetAddress].facetAddressPosition = facetAddressPosition;\n }\n ds.facetAddresses.pop();\n delete ds.facetFunctionSelectors[_facetAddress].facetAddressPosition;\n }\n }\n\n function initializeDiamondCut(address _init, bytes memory _calldata) internal {\n if (_init == address(0)) {\n require(_calldata.length == 0, \"LibDiamondCut: _init is address(0) but_calldata is not empty\");\n } else {\n require(_calldata.length > 0, \"LibDiamondCut: _calldata is empty but _init is not address(0)\");\n if (_init != address(this)) {\n enforceHasContractCode(_init, \"LibDiamondCut: _init address has no code\");\n }\n (bool success, bytes memory error) = _init.delegatecall(_calldata);\n if (!success) {\n if (error.length > 0) {\n // bubble up the error\n revert(string(error));\n } else {\n revert(\"LibDiamondCut: _init function reverted\");\n }\n }\n }\n }\n\n function enforceHasContractCode(address _contract, string memory _errorMessage) internal view {\n uint256 contractSize;\n assembly {\n contractSize := extcodesize(_contract)\n }\n require(contractSize > 0, _errorMessage);\n }\n}\n" - } - }, - "settings": { - "optimizer": { - "enabled": false, - "runs": 200 - }, - "outputSelection": { - "*": { - "*": [ - "abi", - "evm.bytecode", - "evm.deployedBytecode", - "evm.methodIdentifiers", - "metadata", - "devdoc", - "userdoc", - "storageLayout", - "evm.gasEstimates" - ], - "": [ - "ast" - ] - } - }, - "metadata": { - "useLiteralContent": true - } - } -} \ No newline at end of file diff --git a/hardhat.config.ts b/hardhat.config.ts index 00f4f3b..8be92d4 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -83,6 +83,13 @@ const config: HardhatUserConfig = { ? [process.env.MAINNET_DEPLOYER_PRIVATE_KEY] : [], }, + arbitrum: { + chainId: 42161, + url: process.env.ARBITRUM_PROVIDER || "", + accounts: process.env.ARBITRUM_DEPLOYER_PRIVATE_KEY + ? [process.env.ARBITRUM_DEPLOYER_PRIVATE_KEY] + : [], + }, polygon: { chainId: 137, url: process.env.POLYGON_PROVIDER || "", @@ -90,20 +97,6 @@ const config: HardhatUserConfig = { ? [process.env.POLYGON_DEPLOYER_PRIVATE_KEY] : [], }, - base: { - chainId: 8453, - url: process.env.BASE_PROVIDER || "", - accounts: process.env.BASE_DEPLOYER_PRIVATE_KEY - ? [process.env.BASE_DEPLOYER_PRIVATE_KEY] - : [], - }, - baseGoerli: { - chainId: 84531, - url: process.env.BASE_GOERLI_PROVIDER || "", - accounts: process.env.BASE_GOERLI_DEPLOYER_PRIVATE_KEY - ? [process.env.BASE_GOERLI_DEPLOYER_PRIVATE_KEY] - : [], - }, polygonMumbai: { chainId: 80001, url: process.env.POLYGON_MUMBAI_PROVIDER || "", @@ -111,13 +104,6 @@ const config: HardhatUserConfig = { ? [process.env.POLYGON_MUMBAI_DEPLOYER_PRIVATE_KEY] : [], }, - goerli: { - chainId: 5, - url: process.env.GOERLI_PROVIDER || "", - accounts: process.env.GOERLI_DEPLOYER_PRIVATE_KEY - ? [process.env.GOERLI_DEPLOYER_PRIVATE_KEY] - : [], - }, sepolia: { chainId: 11155111, url: process.env.SEPOLIA_PROVIDER || "", @@ -143,13 +129,19 @@ const config: HardhatUserConfig = { apiKey: { mainnet: process.env.ETHERSCAN_API_KEY || "", polygon: process.env.POLYGONSCAN_API_KEY || "", - base: process.env.BASESCAN_API_KEY || "", - baseGoerli: process.env.BASESCAN_API_KEY || "", polygonMumbai: process.env.POLYGONSCAN_API_KEY || "", - goerli: process.env.ETHERSCAN_API_KEY || "", sepolia: process.env.ETHERSCAN_API_KEY || "", + arbitrumOne: process.env.ARBISCAN_API_KEY || "", }, customChains: [ + { + network: "arbitrum", + chainId: 8453, + urls: { + apiURL: "https://api.arbiscan.io/", + browserURL: "https://arbiscan.io/", + }, + }, { network: "base", chainId: 8453,