diff --git a/deployments/arbitrumMainnet/TicketBrokerTarget.json b/deployments/arbitrumMainnet/TicketBrokerTarget.json index 4aa8be12..76d07a33 100644 --- a/deployments/arbitrumMainnet/TicketBrokerTarget.json +++ b/deployments/arbitrumMainnet/TicketBrokerTarget.json @@ -1,5 +1,5 @@ { - "address": "0xD906D192e2503Aafd1BC5F5fc4163E842D5B1d6e", + "address": "0xea1b0F6c8D158328a6e3D3F924B86A759F41465c", "abi": [ { "inputs": [ @@ -747,30 +747,30 @@ "type": "function" } ], - "transactionHash": "0xdaa64809811cf7427e116b6d2c3e9d71dd5650f0ae9dbae0eacb322630b58a98", + "transactionHash": "0xfd6b4731d09764128962b4526758f8b6bba0233a905462a9c22b5d08048eb132", "receipt": { "to": null, - "from": "0xB5Af4138f0f33be0D6414Eb25271B9C2Dc245fb5", - "contractAddress": "0xD906D192e2503Aafd1BC5F5fc4163E842D5B1d6e", - "transactionIndex": 0, - "gasUsed": "41659775", + "from": "0xd94387c220385bFE4bf599d95E199f3823Da593F", + "contractAddress": "0xea1b0F6c8D158328a6e3D3F924B86A759F41465c", + "transactionIndex": 3, + "gasUsed": "21920678", "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "blockHash": "0x2c23ebffff682f52172db7346104edaaf9408eff20f43135ecd05f5f81ad5498", - "transactionHash": "0xdaa64809811cf7427e116b6d2c3e9d71dd5650f0ae9dbae0eacb322630b58a98", + "blockHash": "0x21795c654aef1e8427c75fe1479ae4388b8cb69b02f66867bd3a68a8d6f9c752", + "transactionHash": "0xfd6b4731d09764128962b4526758f8b6bba0233a905462a9c22b5d08048eb132", "logs": [], - "blockNumber": 7371809, - "cumulativeGasUsed": "19241215", + "blockNumber": 128664470, + "cumulativeGasUsed": "26205529", "status": 1, "byzantium": true }, "args": [ "0xD8E8328501E9645d16Cf49539efC04f734606ee4" ], - "numDeployments": 2, - "solcInputHash": "27d66ea2a888a79c7ec1cad8a29cd53d", - "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DepositFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"param\",\"type\":\"string\"}],\"name\":\"ParameterUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reserveHolder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"claimant\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReserveClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reserveHolder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReserveFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"}],\"name\":\"SetController\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startRound\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endRound\",\"type\":\"uint256\"}],\"name\":\"Unlock\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnlockCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"recipientRand\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"name\":\"WinningTicketRedeemed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WinningTicketTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deposit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reserve\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientRandHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"internalType\":\"struct MTicketBrokerCore.Ticket[]\",\"name\":\"_tickets\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"_sigs\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_recipientRands\",\"type\":\"uint256[]\"}],\"name\":\"batchRedeemWinningTickets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelUnlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_reserveHolder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_claimant\",\"type\":\"address\"}],\"name\":\"claimableReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_reserveHolder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_claimant\",\"type\":\"address\"}],\"name\":\"claimedReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"contract IController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundDeposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_reserveAmount\",\"type\":\"uint256\"}],\"name\":\"fundDepositAndReserve\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_reserveAmount\",\"type\":\"uint256\"}],\"name\":\"fundDepositAndReserveFor\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundReserve\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_reserveHolder\",\"type\":\"address\"}],\"name\":\"getReserveInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"fundsRemaining\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"claimedInCurrentRound\",\"type\":\"uint256\"}],\"internalType\":\"struct MReserve.ReserveInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"}],\"name\":\"getSenderInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"deposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"withdrawRound\",\"type\":\"uint256\"}],\"internalType\":\"struct MixinTicketBrokerCore.Sender\",\"name\":\"sender\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"fundsRemaining\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"claimedInCurrentRound\",\"type\":\"uint256\"}],\"internalType\":\"struct MReserve.ReserveInfo\",\"name\":\"reserve\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientRandHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"internalType\":\"struct MTicketBrokerCore.Ticket\",\"name\":\"_ticket\",\"type\":\"tuple\"}],\"name\":\"getTicketHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"}],\"name\":\"isUnlockInProgress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientRandHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"internalType\":\"struct MTicketBrokerCore.Ticket\",\"name\":\"_ticket\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_sig\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_recipientRand\",\"type\":\"uint256\"}],\"name\":\"redeemWinningTicket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"}],\"name\":\"setController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ticketValidityPeriod\",\"type\":\"uint256\"}],\"name\":\"setTicketValidityPeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_unlockPeriod\",\"type\":\"uint256\"}],\"name\":\"setUnlockPeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"targetContractId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ticketValidityPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"usedTickets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"batchRedeemWinningTickets((address,address,uint256,uint256,uint256,bytes32,bytes)[],bytes[],uint256[])\":{\"params\":{\"_recipientRands\":\"Array of preimages for the recipientRandHash included in each ticket (`_recipientRands[i]` corresponds to `_tickets[i]`)\",\"_sigs\":\"Array of sender signatures over the hash of tickets (`_sigs[i]` corresponds to `_tickets[i]`)\",\"_tickets\":\"Array of winning tickets to be redeemed in order to claim payment\"}},\"claimableReserve(address,address)\":{\"details\":\"Returns the amount of funds claimable by a claimant from a reserve in the current round\",\"params\":{\"_claimant\":\"Address of claimant\",\"_reserveHolder\":\"Address of reserve holder\"},\"returns\":{\"_0\":\"Amount of funds claimable by `_claimant` from the reserve for `_reserveHolder` in the current round\"}},\"claimedReserve(address,address)\":{\"details\":\"Returns the amount of funds claimed by a claimant from a reserve in the current round\",\"params\":{\"_claimant\":\"Address of claimant\",\"_reserveHolder\":\"Address of reserve holder\"},\"returns\":{\"_0\":\"Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder` in the current round\"}},\"constructor\":{\"details\":\"This constructor will not initialize any state variables besides `controller`. The following setter functions should be used to initialize state variables post-deployment: - setUnlockPeriod() - setTicketValidityPeriod()\",\"params\":{\"_controller\":\"Address of Controller that this contract will be registered with\"}},\"fundDepositAndReserve(uint256,uint256)\":{\"params\":{\"_depositAmount\":\"Amount of ETH to add to the caller's deposit\",\"_reserveAmount\":\"Amount of ETH to add to the caller's reserve\"}},\"fundDepositAndReserveFor(address,uint256,uint256)\":{\"params\":{\"_depositAmount\":\"Amount of ETH to add to the address' deposit\",\"_reserveAmount\":\"Amount of ETH to add to the address' reserve\"}},\"getReserveInfo(address)\":{\"details\":\"Returns info about a reserve\",\"params\":{\"_reserveHolder\":\"Address of reserve holder\"},\"returns\":{\"info\":\"Info about the reserve for `_reserveHolder`\"}},\"getSenderInfo(address)\":{\"params\":{\"_sender\":\"Address of sender\"},\"returns\":{\"reserve\":\"Info about the reserve for `_sender`\",\"sender\":\"Info about the sender for `_sender`\"}},\"getTicketHash((address,address,uint256,uint256,uint256,bytes32,bytes))\":{\"details\":\"Returns the hash of a ticket\",\"params\":{\"_ticket\":\"Ticket to be hashed\"},\"returns\":{\"_0\":\"keccak256 hash of `_ticket`\"}},\"isUnlockInProgress(address)\":{\"params\":{\"_sender\":\"Address of sender\"},\"returns\":{\"_0\":\"Boolean indicating whether `_sender` has an unlock in progress\"}},\"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\":{\"params\":{\"_recipientRand\":\"The preimage for the recipientRandHash included in `_ticket`\",\"_sig\":\"Sender's signature over the hash of `_ticket`\",\"_ticket\":\"Winning ticket to be redeemed in order to claim payment\"}},\"setController(address)\":{\"params\":{\"_controller\":\"Controller contract address\"}},\"setTicketValidityPeriod(uint256)\":{\"params\":{\"_ticketValidityPeriod\":\"Value for ticketValidityPeriod\"}},\"setUnlockPeriod(uint256)\":{\"params\":{\"_unlockPeriod\":\"Value for unlockPeriod\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"batchRedeemWinningTickets((address,address,uint256,uint256,uint256,bytes32,bytes)[],bytes[],uint256[])\":{\"notice\":\"Redeems multiple winning tickets. The function will redeem all of the provided tickets and handle any failures gracefully without reverting the entire function\"},\"cancelUnlock()\":{\"notice\":\"Cancels the unlock period for the caller\"},\"constructor\":{\"notice\":\"TicketBroker constructor. Only invokes constructor of base Manager contract with provided Controller address\"},\"fundDeposit()\":{\"notice\":\"Adds ETH to the caller's deposit\"},\"fundDepositAndReserve(uint256,uint256)\":{\"notice\":\"Adds ETH to the caller's deposit and reserve\"},\"fundDepositAndReserveFor(address,uint256,uint256)\":{\"notice\":\"Adds ETH to the address' deposit and reserve\"},\"fundReserve()\":{\"notice\":\"Adds ETH to the caller's reserve\"},\"getSenderInfo(address)\":{\"notice\":\"Returns info about a sender\"},\"isUnlockInProgress(address)\":{\"notice\":\"Returns whether a sender is currently in the unlock period\"},\"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\":{\"notice\":\"Redeems a winning ticket that has been signed by a sender and reveals the recipient recipientRand that corresponds to the recipientRandHash included in the ticket\"},\"setController(address)\":{\"notice\":\"Set controller. Only callable by current controller\"},\"setTicketValidityPeriod(uint256)\":{\"notice\":\"Sets ticketValidityPeriod value. Only callable by the Controller owner\"},\"setUnlockPeriod(uint256)\":{\"notice\":\"Sets unlockPeriod value. Only callable by the Controller owner\"},\"unlock()\":{\"notice\":\"Initiates the unlock period for the caller\"},\"withdraw()\":{\"notice\":\"Withdraws all ETH from the caller's deposit and reserve\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/pm/TicketBroker.sol\":\"TicketBroker\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n } else if (error == RecoverError.InvalidSignatureV) {\\n revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n // Check the signature length\\n // - case 65: r,s,v signature (standard)\\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else if (signature.length == 64) {\\n bytes32 r;\\n bytes32 vs;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n vs := mload(add(signature, 0x40))\\n }\\n return tryRecover(hash, r, vs);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address, RecoverError) {\\n bytes32 s;\\n uint8 v;\\n assembly {\\n s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n v := add(shr(255, vs), 27)\\n }\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n if (v != 27 && v != 28) {\\n return (address(0), RecoverError.InvalidSignatureV);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0xe9e291de7ffe06e66503c6700b1bb84ff6e0989cbb974653628d8994e7c97f03\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator.\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa2f576be637946f767aa56601c26d717f48a0aff44f82e46f13807eea1009a21\",\"license\":\"MIT\"},\"contracts/IController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./zeppelin/Pausable.sol\\\";\\n\\nabstract contract IController is Pausable {\\n event SetContractInfo(bytes32 id, address contractAddress, bytes20 gitCommitHash);\\n\\n function setContractInfo(\\n bytes32 _id,\\n address _contractAddress,\\n bytes20 _gitCommitHash\\n ) external virtual;\\n\\n function updateController(bytes32 _id, address _controller) external virtual;\\n\\n function getContract(bytes32 _id) public view virtual returns (address);\\n}\\n\",\"keccak256\":\"0x34ea30a2b44d0cbec58fc1d703476ff0085b0fdadab0cd65c35c00b8867f7546\",\"license\":\"MIT\"},\"contracts/IManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\ninterface IManager {\\n event SetController(address controller);\\n event ParameterUpdate(string param);\\n\\n function setController(address _controller) external;\\n}\\n\",\"keccak256\":\"0xc179e4cecc593741514237d5194b4aaac6b829789629fa19ed04f572a8530481\",\"license\":\"MIT\"},\"contracts/Manager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./IManager.sol\\\";\\nimport \\\"./IController.sol\\\";\\n\\ncontract Manager is IManager {\\n // Controller that contract is registered with\\n IController public controller;\\n\\n // Check if sender is controller\\n modifier onlyController() {\\n _onlyController();\\n _;\\n }\\n\\n // Check if sender is controller owner\\n modifier onlyControllerOwner() {\\n _onlyControllerOwner();\\n _;\\n }\\n\\n // Check if controller is not paused\\n modifier whenSystemNotPaused() {\\n _whenSystemNotPaused();\\n _;\\n }\\n\\n // Check if controller is paused\\n modifier whenSystemPaused() {\\n _whenSystemPaused();\\n _;\\n }\\n\\n constructor(address _controller) {\\n controller = IController(_controller);\\n }\\n\\n /**\\n * @notice Set controller. Only callable by current controller\\n * @param _controller Controller contract address\\n */\\n function setController(address _controller) external onlyController {\\n controller = IController(_controller);\\n\\n emit SetController(_controller);\\n }\\n\\n function _onlyController() private view {\\n require(msg.sender == address(controller), \\\"caller must be Controller\\\");\\n }\\n\\n function _onlyControllerOwner() private view {\\n require(msg.sender == controller.owner(), \\\"caller must be Controller owner\\\");\\n }\\n\\n function _whenSystemNotPaused() private view {\\n require(!controller.paused(), \\\"system is paused\\\");\\n }\\n\\n function _whenSystemPaused() private view {\\n require(controller.paused(), \\\"system is not paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0xc415e3f42da9f82ddd5953031f3f26aed824368fcc34d3b8a17015bfe80dc109\",\"license\":\"MIT\"},\"contracts/ManagerProxyTarget.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./Manager.sol\\\";\\n\\n/**\\n * @title ManagerProxyTarget\\n * @notice The base contract that target contracts used by a proxy contract should inherit from\\n * @dev Both the target contract and the proxy contract (implemented as ManagerProxy) MUST inherit from ManagerProxyTarget in order to guarantee\\n that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can\\n potentially break the delegate proxy upgradeability mechanism\\n */\\nabstract contract ManagerProxyTarget is Manager {\\n // Used to look up target contract address in controller's registry\\n bytes32 public targetContractId;\\n}\\n\",\"keccak256\":\"0x920bcc2def240e06272dc06cbcb9f12976f1698cd4f1020c165af25ee837e553\",\"license\":\"MIT\"},\"contracts/bonding/IBondingManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n/**\\n * @title Interface for BondingManager\\n * TODO: switch to interface type\\n */\\ninterface IBondingManager {\\n event TranscoderUpdate(address indexed transcoder, uint256 rewardCut, uint256 feeShare);\\n event TranscoderActivated(address indexed transcoder, uint256 activationRound);\\n event TranscoderDeactivated(address indexed transcoder, uint256 deactivationRound);\\n event TranscoderSlashed(address indexed transcoder, address finder, uint256 penalty, uint256 finderReward);\\n event Reward(address indexed transcoder, uint256 amount);\\n event Bond(\\n address indexed newDelegate,\\n address indexed oldDelegate,\\n address indexed delegator,\\n uint256 additionalAmount,\\n uint256 bondedAmount\\n );\\n event Unbond(\\n address indexed delegate,\\n address indexed delegator,\\n uint256 unbondingLockId,\\n uint256 amount,\\n uint256 withdrawRound\\n );\\n event Rebond(address indexed delegate, address indexed delegator, uint256 unbondingLockId, uint256 amount);\\n event TransferBond(\\n address indexed oldDelegator,\\n address indexed newDelegator,\\n uint256 oldUnbondingLockId,\\n uint256 newUnbondingLockId,\\n uint256 amount\\n );\\n event WithdrawStake(address indexed delegator, uint256 unbondingLockId, uint256 amount, uint256 withdrawRound);\\n event WithdrawFees(address indexed delegator, address recipient, uint256 amount);\\n event EarningsClaimed(\\n address indexed delegate,\\n address indexed delegator,\\n uint256 rewards,\\n uint256 fees,\\n uint256 startRound,\\n uint256 endRound\\n );\\n\\n // Deprecated events\\n // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding\\n // to these deprecated events.\\n // event Bond(address indexed delegate, address indexed delegator);\\n // event Unbond(address indexed delegate, address indexed delegator);\\n // event WithdrawStake(address indexed delegator);\\n // event TranscoderUpdate(address indexed transcoder, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment, bool registered);\\n // event TranscoderEvicted(address indexed transcoder);\\n // event TranscoderResigned(address indexed transcoder);\\n\\n // External functions\\n function updateTranscoderWithFees(\\n address _transcoder,\\n uint256 _fees,\\n uint256 _round\\n ) external;\\n\\n function slashTranscoder(\\n address _transcoder,\\n address _finder,\\n uint256 _slashAmount,\\n uint256 _finderFee\\n ) external;\\n\\n function setCurrentRoundTotalActiveStake() external;\\n\\n // Public functions\\n function getTranscoderPoolSize() external view returns (uint256);\\n\\n function transcoderTotalStake(address _transcoder) external view returns (uint256);\\n\\n function isActiveTranscoder(address _transcoder) external view returns (bool);\\n\\n function getTotalBonded() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x6406378868b556ca91b1ab6cccd036695c8984d30a225f75a5979cb9aa7c1df2\",\"license\":\"MIT\"},\"contracts/pm/TicketBroker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./mixins/MixinContractRegistry.sol\\\";\\nimport \\\"./mixins/MixinReserve.sol\\\";\\nimport \\\"./mixins/MixinTicketBrokerCore.sol\\\";\\nimport \\\"./mixins/MixinTicketProcessor.sol\\\";\\nimport \\\"./mixins/MixinWrappers.sol\\\";\\n\\ncontract TicketBroker is\\n MixinContractRegistry,\\n MixinReserve,\\n MixinTicketBrokerCore,\\n MixinTicketProcessor,\\n MixinWrappers\\n{\\n /**\\n * @notice TicketBroker constructor. Only invokes constructor of base Manager contract with provided Controller address\\n * @dev This constructor will not initialize any state variables besides `controller`. The following setter functions\\n * should be used to initialize state variables post-deployment:\\n * - setUnlockPeriod()\\n * - setTicketValidityPeriod()\\n * @param _controller Address of Controller that this contract will be registered with\\n */\\n constructor(address _controller)\\n MixinContractRegistry(_controller)\\n MixinReserve()\\n MixinTicketBrokerCore()\\n MixinTicketProcessor()\\n {}\\n\\n /**\\n * @notice Sets unlockPeriod value. Only callable by the Controller owner\\n * @param _unlockPeriod Value for unlockPeriod\\n */\\n function setUnlockPeriod(uint256 _unlockPeriod) external onlyControllerOwner {\\n unlockPeriod = _unlockPeriod;\\n\\n emit ParameterUpdate(\\\"unlockPeriod\\\");\\n }\\n\\n /**\\n * @notice Sets ticketValidityPeriod value. Only callable by the Controller owner\\n * @param _ticketValidityPeriod Value for ticketValidityPeriod\\n */\\n function setTicketValidityPeriod(uint256 _ticketValidityPeriod) external onlyControllerOwner {\\n require(_ticketValidityPeriod > 0, \\\"ticketValidityPeriod must be greater than 0\\\");\\n\\n ticketValidityPeriod = _ticketValidityPeriod;\\n\\n emit ParameterUpdate(\\\"ticketValidityPeriod\\\");\\n }\\n}\\n\",\"keccak256\":\"0x3e1b4458d61a3c20e23707bde667f936af006668f1ec4a69b2322ff7e79336e7\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinContractRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"../../ManagerProxyTarget.sol\\\";\\nimport \\\"./interfaces/MContractRegistry.sol\\\";\\n\\nabstract contract MixinContractRegistry is MContractRegistry, ManagerProxyTarget {\\n /**\\n * @dev Checks if the current round has been initialized\\n */\\n modifier currentRoundInitialized() override {\\n require(roundsManager().currentRoundInitialized(), \\\"current round is not initialized\\\");\\n _;\\n }\\n\\n constructor(address _controller) Manager(_controller) {}\\n\\n /**\\n * @dev Returns an instance of the IBondingManager interface\\n */\\n function bondingManager() internal view override returns (IBondingManager) {\\n return IBondingManager(controller.getContract(keccak256(\\\"BondingManager\\\")));\\n }\\n\\n /**\\n * @dev Returns an instance of the IMinter interface\\n */\\n function minter() internal view override returns (IMinter) {\\n return IMinter(controller.getContract(keccak256(\\\"Minter\\\")));\\n }\\n\\n /**\\n * @dev Returns an instance of the IRoundsManager interface\\n */\\n function roundsManager() internal view override returns (IRoundsManager) {\\n return IRoundsManager(controller.getContract(keccak256(\\\"RoundsManager\\\")));\\n }\\n}\\n\",\"keccak256\":\"0xaf3b21d532c7fdcd02606045c66646b035a257a27dea374b8c8487339778ee2a\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinReserve.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MReserve.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\nabstract contract MixinReserve is MixinContractRegistry, MReserve {\\n using SafeMath for uint256;\\n\\n struct Reserve {\\n uint256 funds; // Amount of funds in the reserve\\n mapping(uint256 => uint256) claimedForRound; // Mapping of round => total amount claimed\\n mapping(uint256 => mapping(address => uint256)) claimedByAddress; // Mapping of round => claimant address => amount claimed\\n }\\n\\n // Mapping of address => reserve\\n mapping(address => Reserve) internal reserves;\\n\\n /**\\n * @dev Returns info about a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return info Info about the reserve for `_reserveHolder`\\n */\\n function getReserveInfo(address _reserveHolder) public view override returns (ReserveInfo memory info) {\\n info.fundsRemaining = remainingReserve(_reserveHolder);\\n info.claimedInCurrentRound = reserves[_reserveHolder].claimedForRound[roundsManager().currentRound()];\\n }\\n\\n /**\\n * @dev Returns the amount of funds claimable by a claimant from a reserve in the current round\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @return Amount of funds claimable by `_claimant` from the reserve for `_reserveHolder` in the current round\\n */\\n function claimableReserve(address _reserveHolder, address _claimant) public view returns (uint256) {\\n Reserve storage reserve = reserves[_reserveHolder];\\n\\n uint256 currentRound = roundsManager().currentRound();\\n\\n if (!bondingManager().isActiveTranscoder(_claimant)) {\\n return 0;\\n }\\n\\n uint256 poolSize = bondingManager().getTranscoderPoolSize();\\n if (poolSize == 0) {\\n return 0;\\n }\\n\\n // Total claimable funds = remaining funds + amount claimed for the round\\n uint256 totalClaimable = reserve.funds.add(reserve.claimedForRound[currentRound]);\\n return totalClaimable.div(poolSize).sub(reserve.claimedByAddress[currentRound][_claimant]);\\n }\\n\\n /**\\n * @dev Returns the amount of funds claimed by a claimant from a reserve in the current round\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @return Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder` in the current round\\n */\\n function claimedReserve(address _reserveHolder, address _claimant) public view override returns (uint256) {\\n Reserve storage reserve = reserves[_reserveHolder];\\n uint256 currentRound = roundsManager().currentRound();\\n return reserve.claimedByAddress[currentRound][_claimant];\\n }\\n\\n /**\\n * @dev Adds funds to a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _amount Amount of funds to add to reserve\\n */\\n function addReserve(address _reserveHolder, uint256 _amount) internal override {\\n reserves[_reserveHolder].funds = reserves[_reserveHolder].funds.add(_amount);\\n\\n emit ReserveFunded(_reserveHolder, _amount);\\n }\\n\\n /**\\n * @dev Clears contract storage used for a reserve\\n * @param _reserveHolder Address of reserve holder\\n */\\n function clearReserve(address _reserveHolder) internal override {\\n // This delete operation will only clear reserve.funds and will not clear the storage for reserve.claimedForRound\\n // reserve.claimedByAddress because these fields are mappings and the Solidity `delete` keyword will not modify mappings.\\n // This *could* be a problem in the following scenario:\\n //\\n // 1) In round N, for address A, reserve.claimedForRound[N] > 0 and reserve.claimedByAddress[N][r_i] > 0 where r_i is\\n // a member of the active set in round N\\n // 2) This function is called by MixinTicketBrokerCore.withdraw() in round N\\n // 3) Address A funds its reserve again\\n //\\n // After step 3, A has reserve.funds > 0, reserve.claimedForRound[N] > 0 and reserve.claimedByAddress[N][r_i] > 0\\n // despite having funded a fresh reserve after previously withdrawing all of its funds in the same round.\\n // We prevent this scenario by disallowing reserve claims starting at an address' withdraw round in\\n // MixinTicketBrokerCore.redeemWinningTicket()\\n delete reserves[_reserveHolder];\\n }\\n\\n /**\\n * @dev Claims funds from a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @param _amount Amount of funds to claim from the reserve\\n * @return Amount of funds (<= `_amount`) claimed by `_claimant` from the reserve for `_reserveHolder`\\n */\\n function claimFromReserve(\\n address _reserveHolder,\\n address _claimant,\\n uint256 _amount\\n ) internal override returns (uint256) {\\n uint256 claimableFunds = claimableReserve(_reserveHolder, _claimant);\\n // If the given amount > claimableFunds then claim claimableFunds\\n // If the given amount <= claimableFunds then claim the given amount\\n uint256 claimAmount = _amount > claimableFunds ? claimableFunds : _amount;\\n\\n if (claimAmount > 0) {\\n uint256 currentRound = roundsManager().currentRound();\\n Reserve storage reserve = reserves[_reserveHolder];\\n // Increase total amount claimed for the round\\n reserve.claimedForRound[currentRound] = reserve.claimedForRound[currentRound].add(claimAmount);\\n // Increase amount claimed by claimant for the round\\n reserve.claimedByAddress[currentRound][_claimant] = reserve.claimedByAddress[currentRound][_claimant].add(\\n claimAmount\\n );\\n // Decrease remaining reserve\\n reserve.funds = reserve.funds.sub(claimAmount);\\n\\n emit ReserveClaimed(_reserveHolder, _claimant, claimAmount);\\n }\\n\\n return claimAmount;\\n }\\n\\n /**\\n * @dev Returns the amount of funds remaining in a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return Amount of funds remaining in the reserve for `_reserveHolder`\\n */\\n function remainingReserve(address _reserveHolder) internal view override returns (uint256) {\\n return reserves[_reserveHolder].funds;\\n }\\n}\\n\",\"keccak256\":\"0x1b1d7694fe606eb1c0ba2e203889b416804bd1547ee63ed572c1c628f219c775\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinTicketBrokerCore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MReserve.sol\\\";\\nimport \\\"./interfaces/MTicketProcessor.sol\\\";\\nimport \\\"./interfaces/MTicketBrokerCore.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\nabstract contract MixinTicketBrokerCore is MixinContractRegistry, MReserve, MTicketProcessor, MTicketBrokerCore {\\n using SafeMath for uint256;\\n\\n struct Sender {\\n uint256 deposit; // Amount of funds deposited\\n uint256 withdrawRound; // Round that sender can withdraw deposit & reserve\\n }\\n\\n // Mapping of address => Sender\\n mapping(address => Sender) internal senders;\\n\\n // Number of rounds before a sender can withdraw after requesting an unlock\\n uint256 public unlockPeriod;\\n\\n // Mapping of ticket hashes => boolean indicating if ticket was redeemed\\n mapping(bytes32 => bool) public usedTickets;\\n\\n // Checks if msg.value is equal to the given deposit and reserve amounts\\n modifier checkDepositReserveETHValueSplit(uint256 _depositAmount, uint256 _reserveAmount) {\\n require(\\n msg.value == _depositAmount.add(_reserveAmount),\\n \\\"msg.value does not equal sum of deposit amount and reserve amount\\\"\\n );\\n\\n _;\\n }\\n\\n // Process deposit funding\\n modifier processDeposit(address _sender, uint256 _amount) {\\n Sender storage sender = senders[_sender];\\n sender.deposit = sender.deposit.add(_amount);\\n if (_isUnlockInProgress(sender)) {\\n _cancelUnlock(sender, _sender);\\n }\\n\\n _;\\n\\n emit DepositFunded(_sender, _amount);\\n }\\n\\n // Process reserve funding\\n modifier processReserve(address _sender, uint256 _amount) {\\n Sender storage sender = senders[_sender];\\n addReserve(_sender, _amount);\\n if (_isUnlockInProgress(sender)) {\\n _cancelUnlock(sender, _sender);\\n }\\n\\n _;\\n }\\n\\n /**\\n * @notice Adds ETH to the caller's deposit\\n */\\n function fundDeposit() external payable whenSystemNotPaused processDeposit(msg.sender, msg.value) {\\n processFunding(msg.value);\\n }\\n\\n /**\\n * @notice Adds ETH to the caller's reserve\\n */\\n function fundReserve() external payable whenSystemNotPaused processReserve(msg.sender, msg.value) {\\n processFunding(msg.value);\\n }\\n\\n /**\\n * @notice Adds ETH to the caller's deposit and reserve\\n * @param _depositAmount Amount of ETH to add to the caller's deposit\\n * @param _reserveAmount Amount of ETH to add to the caller's reserve\\n */\\n function fundDepositAndReserve(uint256 _depositAmount, uint256 _reserveAmount) external payable {\\n fundDepositAndReserveFor(msg.sender, _depositAmount, _reserveAmount);\\n }\\n\\n /**\\n * @notice Adds ETH to the address' deposit and reserve\\n * @param _depositAmount Amount of ETH to add to the address' deposit\\n * @param _reserveAmount Amount of ETH to add to the address' reserve\\n */\\n function fundDepositAndReserveFor(\\n address _addr,\\n uint256 _depositAmount,\\n uint256 _reserveAmount\\n )\\n public\\n payable\\n whenSystemNotPaused\\n checkDepositReserveETHValueSplit(_depositAmount, _reserveAmount)\\n processDeposit(_addr, _depositAmount)\\n processReserve(_addr, _reserveAmount)\\n {\\n processFunding(msg.value);\\n }\\n\\n /**\\n * @notice Redeems a winning ticket that has been signed by a sender and reveals the\\n recipient recipientRand that corresponds to the recipientRandHash included in the ticket\\n * @param _ticket Winning ticket to be redeemed in order to claim payment\\n * @param _sig Sender's signature over the hash of `_ticket`\\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\\n */\\n function redeemWinningTicket(\\n Ticket memory _ticket,\\n bytes memory _sig,\\n uint256 _recipientRand\\n ) public whenSystemNotPaused currentRoundInitialized {\\n bytes32 ticketHash = getTicketHash(_ticket);\\n\\n // Require a valid winning ticket for redemption\\n requireValidWinningTicket(_ticket, ticketHash, _sig, _recipientRand);\\n\\n Sender storage sender = senders[_ticket.sender];\\n\\n // Require sender to be locked\\n require(isLocked(sender), \\\"sender is unlocked\\\");\\n // Require either a non-zero deposit or non-zero reserve for the sender\\n require(sender.deposit > 0 || remainingReserve(_ticket.sender) > 0, \\\"sender deposit and reserve are zero\\\");\\n\\n // Mark ticket as used to prevent replay attacks involving redeeming\\n // the same winning ticket multiple times\\n usedTickets[ticketHash] = true;\\n\\n uint256 amountToTransfer;\\n\\n if (_ticket.faceValue > sender.deposit) {\\n // If ticket face value > sender's deposit then claim from\\n // the sender's reserve\\n\\n amountToTransfer = sender.deposit.add(\\n claimFromReserve(_ticket.sender, _ticket.recipient, _ticket.faceValue.sub(sender.deposit))\\n );\\n\\n sender.deposit = 0;\\n } else {\\n // If ticket face value <= sender's deposit then only deduct\\n // from sender's deposit\\n\\n amountToTransfer = _ticket.faceValue;\\n sender.deposit = sender.deposit.sub(_ticket.faceValue);\\n }\\n\\n if (amountToTransfer > 0) {\\n winningTicketTransfer(_ticket.recipient, amountToTransfer, _ticket.auxData);\\n\\n emit WinningTicketTransfer(_ticket.sender, _ticket.recipient, amountToTransfer);\\n }\\n\\n emit WinningTicketRedeemed(\\n _ticket.sender,\\n _ticket.recipient,\\n _ticket.faceValue,\\n _ticket.winProb,\\n _ticket.senderNonce,\\n _recipientRand,\\n _ticket.auxData\\n );\\n }\\n\\n /**\\n * @notice Initiates the unlock period for the caller\\n */\\n function unlock() public whenSystemNotPaused {\\n Sender storage sender = senders[msg.sender];\\n\\n require(sender.deposit > 0 || remainingReserve(msg.sender) > 0, \\\"sender deposit and reserve are zero\\\");\\n require(!_isUnlockInProgress(sender), \\\"unlock already initiated\\\");\\n\\n uint256 currentRound = roundsManager().currentRound();\\n sender.withdrawRound = currentRound.add(unlockPeriod);\\n\\n emit Unlock(msg.sender, currentRound, sender.withdrawRound);\\n }\\n\\n /**\\n * @notice Cancels the unlock period for the caller\\n */\\n function cancelUnlock() public whenSystemNotPaused {\\n Sender storage sender = senders[msg.sender];\\n\\n _cancelUnlock(sender, msg.sender);\\n }\\n\\n /**\\n * @notice Withdraws all ETH from the caller's deposit and reserve\\n */\\n function withdraw() public whenSystemNotPaused {\\n Sender storage sender = senders[msg.sender];\\n\\n uint256 deposit = sender.deposit;\\n uint256 reserve = remainingReserve(msg.sender);\\n\\n require(deposit > 0 || reserve > 0, \\\"sender deposit and reserve are zero\\\");\\n require(_isUnlockInProgress(sender), \\\"no unlock request in progress\\\");\\n require(!isLocked(sender), \\\"account is locked\\\");\\n\\n sender.deposit = 0;\\n clearReserve(msg.sender);\\n\\n withdrawTransfer(payable(msg.sender), deposit.add(reserve));\\n\\n emit Withdrawal(msg.sender, deposit, reserve);\\n }\\n\\n /**\\n * @notice Returns whether a sender is currently in the unlock period\\n * @param _sender Address of sender\\n * @return Boolean indicating whether `_sender` has an unlock in progress\\n */\\n function isUnlockInProgress(address _sender) public view returns (bool) {\\n Sender memory sender = senders[_sender];\\n return _isUnlockInProgress(sender);\\n }\\n\\n /**\\n * @notice Returns info about a sender\\n * @param _sender Address of sender\\n * @return sender Info about the sender for `_sender`\\n * @return reserve Info about the reserve for `_sender`\\n */\\n function getSenderInfo(address _sender) public view returns (Sender memory sender, ReserveInfo memory reserve) {\\n sender = senders[_sender];\\n reserve = getReserveInfo(_sender);\\n }\\n\\n /**\\n * @dev Returns the hash of a ticket\\n * @param _ticket Ticket to be hashed\\n * @return keccak256 hash of `_ticket`\\n */\\n function getTicketHash(Ticket memory _ticket) public pure returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(\\n _ticket.recipient,\\n _ticket.sender,\\n _ticket.faceValue,\\n _ticket.winProb,\\n _ticket.senderNonce,\\n _ticket.recipientRandHash,\\n _ticket.auxData\\n )\\n );\\n }\\n\\n /**\\n * @dev Helper to cancel an unlock\\n * @param _sender Sender that is cancelling an unlock\\n * @param _senderAddress Address of sender\\n */\\n function _cancelUnlock(Sender storage _sender, address _senderAddress) internal {\\n require(_isUnlockInProgress(_sender), \\\"no unlock request in progress\\\");\\n\\n _sender.withdrawRound = 0;\\n\\n emit UnlockCancelled(_senderAddress);\\n }\\n\\n /**\\n * @dev Validates a winning ticket, succeeds or reverts\\n * @param _ticket Winning ticket to be validated\\n * @param _ticketHash Hash of `_ticket`\\n * @param _sig Sender's signature over `_ticketHash`\\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\\n */\\n function requireValidWinningTicket(\\n Ticket memory _ticket,\\n bytes32 _ticketHash,\\n bytes memory _sig,\\n uint256 _recipientRand\\n ) internal view {\\n require(_ticket.recipient != address(0), \\\"ticket recipient is null address\\\");\\n require(_ticket.sender != address(0), \\\"ticket sender is null address\\\");\\n\\n requireValidTicketAuxData(_ticket.auxData);\\n\\n require(\\n keccak256(abi.encodePacked(_recipientRand)) == _ticket.recipientRandHash,\\n \\\"recipientRand does not match recipientRandHash\\\"\\n );\\n\\n require(!usedTickets[_ticketHash], \\\"ticket is used\\\");\\n\\n require(isValidTicketSig(_ticket.sender, _sig, _ticketHash), \\\"invalid signature over ticket hash\\\");\\n\\n require(isWinningTicket(_sig, _recipientRand, _ticket.winProb), \\\"ticket did not win\\\");\\n }\\n\\n /**\\n * @dev Returns whether a sender is locked\\n * @param _sender Sender to check for locked status\\n * @return Boolean indicating whether sender is currently locked\\n */\\n function isLocked(Sender memory _sender) internal view returns (bool) {\\n return _sender.withdrawRound == 0 || roundsManager().currentRound() < _sender.withdrawRound;\\n }\\n\\n /**\\n * @dev Returns whether a signature over a ticket hash is valid for a sender\\n * @param _sender Address of sender\\n * @param _sig Signature over `_ticketHash`\\n * @param _ticketHash Hash of the ticket\\n * @return Boolean indicating whether `_sig` is valid signature over `_ticketHash` for `_sender`\\n */\\n function isValidTicketSig(\\n address _sender,\\n bytes memory _sig,\\n bytes32 _ticketHash\\n ) internal pure returns (bool) {\\n require(_sig.length == 65, \\\"INVALID_SIGNATURE_LENGTH\\\");\\n address signer = ECDSA.recover(ECDSA.toEthSignedMessageHash(_ticketHash), _sig);\\n return signer != address(0) && _sender == signer;\\n }\\n\\n /**\\n * @dev Returns whether a ticket won\\n * @param _sig Sender's signature over the ticket\\n * @param _recipientRand The preimage for the recipientRandHash included in the ticket\\n * @param _winProb The winning probability of the ticket\\n * @return Boolean indicating whether the ticket won\\n */\\n function isWinningTicket(\\n bytes memory _sig,\\n uint256 _recipientRand,\\n uint256 _winProb\\n ) internal pure returns (bool) {\\n return uint256(keccak256(abi.encodePacked(_sig, _recipientRand))) < _winProb;\\n }\\n\\n /**\\n * @dev Helper to check if a sender is currently in the unlock period\\n * @param _sender Sender to check for an unlock\\n * @return Boolean indicating whether the sender is currently in the unlock period\\n */\\n function _isUnlockInProgress(Sender memory _sender) internal pure returns (bool) {\\n return _sender.withdrawRound > 0;\\n }\\n}\\n\",\"keccak256\":\"0x30e254d952edd27c76c0bef439e871a2fff1ee93cdac4e31cfb091168a66684d\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinTicketProcessor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MTicketProcessor.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\nabstract contract MixinTicketProcessor is MixinContractRegistry, MTicketProcessor {\\n using SafeMath for uint256;\\n\\n // Number of rounds that a ticket is valid for starting from\\n // its creationRound\\n uint256 public ticketValidityPeriod;\\n\\n /**\\n * @dev Process sent funds.\\n * @param _amount Amount of funds sent\\n */\\n function processFunding(uint256 _amount) internal override {\\n // Send funds to Minter\\n minter().depositETH{ value: _amount }();\\n }\\n\\n /**\\n * @dev Transfer withdrawal funds for a ticket sender\\n * @param _amount Amount of withdrawal funds\\n */\\n function withdrawTransfer(address payable _sender, uint256 _amount) internal override {\\n // Ask Minter to send withdrawal funds to the ticket sender\\n minter().trustedWithdrawETH(_sender, _amount);\\n }\\n\\n /**\\n * @dev Transfer funds for a recipient's winning ticket\\n * @param _recipient Address of recipient\\n * @param _amount Amount of funds for the winning ticket\\n * @param _auxData Auxilary data for the winning ticket\\n */\\n function winningTicketTransfer(\\n address _recipient,\\n uint256 _amount,\\n bytes memory _auxData\\n ) internal override {\\n (uint256 creationRound, ) = getCreationRoundAndBlockHash(_auxData);\\n\\n // Ask BondingManager to update fee pool for recipient with\\n // winning ticket funds\\n bondingManager().updateTranscoderWithFees(_recipient, _amount, creationRound);\\n }\\n\\n /**\\n * @dev Validates a ticket's auxilary data (succeeds or reverts)\\n * @param _auxData Auxilary data inclueded in a ticket\\n */\\n function requireValidTicketAuxData(bytes memory _auxData) internal view override {\\n (uint256 creationRound, bytes32 creationRoundBlockHash) = getCreationRoundAndBlockHash(_auxData);\\n bytes32 blockHash = roundsManager().blockHashForRound(creationRound);\\n\\n require(blockHash != bytes32(0), \\\"ticket creationRound does not have a block hash\\\");\\n require(creationRoundBlockHash == blockHash, \\\"ticket creationRoundBlockHash invalid for creationRound\\\");\\n\\n uint256 currRound = roundsManager().currentRound();\\n\\n require(creationRound.add(ticketValidityPeriod) > currRound, \\\"ticket is expired\\\");\\n }\\n\\n /**\\n * @dev Returns a ticket's creationRound and creationRoundBlockHash parsed from ticket auxilary data\\n * @param _auxData Auxilary data for a ticket\\n * @return creationRound and creationRoundBlockHash parsed from `_auxData`\\n */\\n function getCreationRoundAndBlockHash(bytes memory _auxData)\\n internal\\n pure\\n returns (uint256 creationRound, bytes32 creationRoundBlockHash)\\n {\\n require(_auxData.length == 64, \\\"invalid length for ticket auxData: must be 64 bytes\\\");\\n\\n // _auxData format:\\n // Bytes [0:31] = creationRound\\n // Bytes [32:63] = creationRoundBlockHash\\n assembly {\\n creationRound := mload(add(_auxData, 32))\\n creationRoundBlockHash := mload(add(_auxData, 64))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x38a3a855f30ebce7af979a0876f11943b6064bc652908c47572f93a202989c41\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinWrappers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MTicketBrokerCore.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\n\\nabstract contract MixinWrappers is MixinContractRegistry, MTicketBrokerCore {\\n /**\\n * @notice Redeems multiple winning tickets. The function will redeem all of the provided tickets and handle any failures gracefully without reverting the entire function\\n * @param _tickets Array of winning tickets to be redeemed in order to claim payment\\n * @param _sigs Array of sender signatures over the hash of tickets (`_sigs[i]` corresponds to `_tickets[i]`)\\n * @param _recipientRands Array of preimages for the recipientRandHash included in each ticket (`_recipientRands[i]` corresponds to `_tickets[i]`)\\n */\\n function batchRedeemWinningTickets(\\n Ticket[] memory _tickets,\\n bytes[] memory _sigs,\\n uint256[] memory _recipientRands\\n ) public whenSystemNotPaused currentRoundInitialized {\\n for (uint256 i = 0; i < _tickets.length; i++) {\\n redeemWinningTicketNoRevert(_tickets[i], _sigs[i], _recipientRands[i]);\\n }\\n }\\n\\n /**\\n * @dev Redeems a winning ticket that has been signed by a sender and reveals the\\n recipient recipientRand that corresponds to the recipientRandHash included in the ticket\\n This function wraps `redeemWinningTicket()` and returns false if the underlying call reverts\\n * @param _ticket Winning ticket to be redeemed in order to claim payment\\n * @param _sig Sender's signature over the hash of `_ticket`\\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\\n * @return success Boolean indicating whether the underlying `redeemWinningTicket()` call succeeded\\n */\\n function redeemWinningTicketNoRevert(\\n Ticket memory _ticket,\\n bytes memory _sig,\\n uint256 _recipientRand\\n ) internal returns (bool success) {\\n // ABI encode calldata for `redeemWinningTicket()`\\n // A tuple type is used to represent the Ticket struct in the function signature\\n bytes memory redeemWinningTicketCalldata = abi.encodeWithSignature(\\n \\\"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\\\",\\n _ticket,\\n _sig,\\n _recipientRand\\n );\\n\\n // Call `redeemWinningTicket()`\\n // solium-disable-next-line\\n (success, ) = address(this).call(redeemWinningTicketCalldata);\\n }\\n}\\n\",\"keccak256\":\"0xf0831bba68089167c5cc9ed9a04564d0a68e1454bd65cf91083103197d047b1d\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MContractRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"../../../bonding/IBondingManager.sol\\\";\\nimport \\\"../../../token/IMinter.sol\\\";\\nimport \\\"../../../rounds/IRoundsManager.sol\\\";\\n\\nabstract contract MContractRegistry {\\n /**\\n * @notice Checks if the current round has been initialized\\n * @dev Executes the 'currentRoundInitialized' modifier in 'MixinContractRegistry'\\n */\\n modifier currentRoundInitialized() virtual {\\n _;\\n }\\n\\n /**\\n * @dev Returns an instance of the IBondingManager interface\\n */\\n function bondingManager() internal view virtual returns (IBondingManager);\\n\\n /**\\n * @dev Returns an instance of the IMinter interface\\n */\\n function minter() internal view virtual returns (IMinter);\\n\\n /**\\n * @dev Returns an instance of the IRoundsManager interface\\n */\\n function roundsManager() internal view virtual returns (IRoundsManager);\\n}\\n\",\"keccak256\":\"0xc58fb56b6ccfe36e5e09322ca1793a805668c84877cf6856403da51e2e35a359\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MReserve.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nabstract contract MReserve {\\n struct ReserveInfo {\\n uint256 fundsRemaining; // Funds remaining in reserve\\n uint256 claimedInCurrentRound; // Funds claimed from reserve in current round\\n }\\n\\n // Emitted when funds are added to a reserve\\n event ReserveFunded(address indexed reserveHolder, uint256 amount);\\n // Emitted when funds are claimed from a reserve\\n event ReserveClaimed(address indexed reserveHolder, address claimant, uint256 amount);\\n\\n /**\\n * @notice Returns info about a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return info Info about the reserve for `_reserveHolder`\\n */\\n function getReserveInfo(address _reserveHolder) public view virtual returns (ReserveInfo memory info);\\n\\n /**\\n * @notice Returns the amount of funds claimed by a claimant from a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @return Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder`\\n */\\n function claimedReserve(address _reserveHolder, address _claimant) public view virtual returns (uint256);\\n\\n /**\\n * @dev Adds funds to a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _amount Amount of funds to add to reserve\\n */\\n function addReserve(address _reserveHolder, uint256 _amount) internal virtual;\\n\\n /**\\n * @dev Clears contract storage used for a reserve\\n * @param _reserveHolder Address of reserve holder\\n */\\n function clearReserve(address _reserveHolder) internal virtual;\\n\\n /**\\n * @dev Claims funds from a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @param _amount Amount of funds to claim from the reserve\\n * @return Amount of funds (<= `_amount`) claimed by `_claimant` from the reserve for `_reserveHolder`\\n */\\n function claimFromReserve(\\n address _reserveHolder,\\n address _claimant,\\n uint256 _amount\\n ) internal virtual returns (uint256);\\n\\n /**\\n * @dev Returns the amount of funds remaining in a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return Amount of funds remaining in the reserve for `_reserveHolder`\\n */\\n function remainingReserve(address _reserveHolder) internal view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x01229dd7088e23db674d032c239d90a14e8922532a82c7d46a3e7fe5fa234827\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MTicketBrokerCore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nabstract contract MTicketBrokerCore {\\n struct Ticket {\\n address recipient; // Address of ticket recipient\\n address sender; // Address of ticket sender\\n uint256 faceValue; // Face value of ticket paid to recipient if ticket wins\\n uint256 winProb; // Probability ticket will win represented as winProb / (2^256 - 1)\\n uint256 senderNonce; // Sender's monotonically increasing counter for each ticket\\n bytes32 recipientRandHash; // keccak256 hash commitment to recipient's random value\\n bytes auxData; // Auxilary data included in ticket used for additional validation\\n }\\n\\n // Emitted when funds are added to a sender's deposit\\n event DepositFunded(address indexed sender, uint256 amount);\\n // Emitted when a winning ticket is redeemed\\n event WinningTicketRedeemed(\\n address indexed sender,\\n address indexed recipient,\\n uint256 faceValue,\\n uint256 winProb,\\n uint256 senderNonce,\\n uint256 recipientRand,\\n bytes auxData\\n );\\n // Emitted when a funds transfer for a winning ticket redemption is executed\\n event WinningTicketTransfer(address indexed sender, address indexed recipient, uint256 amount);\\n // Emitted when a sender requests an unlock\\n event Unlock(address indexed sender, uint256 startRound, uint256 endRound);\\n // Emitted when a sender cancels an unlock\\n event UnlockCancelled(address indexed sender);\\n // Emitted when a sender withdraws its deposit & reserve\\n event Withdrawal(address indexed sender, uint256 deposit, uint256 reserve);\\n}\\n\",\"keccak256\":\"0x80c3b528a357a1895fc5e3d6a7b935db89ab1ba10a0af677d677b7a66434bc0f\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MTicketProcessor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nabstract contract MTicketProcessor {\\n /**\\n * @dev Process sent funds.\\n * @param _amount Amount of funds sent\\n */\\n function processFunding(uint256 _amount) internal virtual;\\n\\n /**\\n * @dev Transfer withdrawal funds for a ticket sender\\n * @param _amount Amount of withdrawal funds\\n */\\n function withdrawTransfer(address payable _sender, uint256 _amount) internal virtual;\\n\\n /**\\n * @dev Transfer funds for a recipient's winning ticket\\n * @param _recipient Address of recipient\\n * @param _amount Amount of funds for the winning ticket\\n * @param _auxData Auxilary data for the winning ticket\\n */\\n function winningTicketTransfer(\\n address _recipient,\\n uint256 _amount,\\n bytes memory _auxData\\n ) internal virtual;\\n\\n /**\\n * @dev Validates a ticket's auxilary data (succeeds or reverts)\\n * @param _auxData Auxilary data inclueded in a ticket\\n */\\n function requireValidTicketAuxData(bytes memory _auxData) internal view virtual;\\n}\\n\",\"keccak256\":\"0xe026045f70ec840465b6d146cd4ddc5ea8b9a8e8ee0c6288f44649dd3c4a12e9\",\"license\":\"MIT\"},\"contracts/rounds/IRoundsManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n/**\\n * @title RoundsManager interface\\n */\\ninterface IRoundsManager {\\n // Events\\n event NewRound(uint256 indexed round, bytes32 blockHash);\\n\\n // Deprecated events\\n // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding\\n // to these deprecated events.\\n // event NewRound(uint256 round)\\n\\n // External functions\\n function initializeRound() external;\\n\\n function lipUpgradeRound(uint256 _lip) external view returns (uint256);\\n\\n // Public functions\\n function blockNum() external view returns (uint256);\\n\\n function blockHash(uint256 _block) external view returns (bytes32);\\n\\n function blockHashForRound(uint256 _round) external view returns (bytes32);\\n\\n function currentRound() external view returns (uint256);\\n\\n function currentRoundStartBlock() external view returns (uint256);\\n\\n function currentRoundInitialized() external view returns (bool);\\n\\n function currentRoundLocked() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xfc453a476bb68b874c21678a128b46ffcad0af69008e0e3e857d46499214f75f\",\"license\":\"MIT\"},\"contracts/token/IMinter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"../IController.sol\\\";\\n\\n/**\\n * @title Minter interface\\n */\\ninterface IMinter {\\n // Events\\n event SetCurrentRewardTokens(uint256 currentMintableTokens, uint256 currentInflation);\\n\\n // External functions\\n function createReward(uint256 _fracNum, uint256 _fracDenom) external returns (uint256);\\n\\n function trustedTransferTokens(address _to, uint256 _amount) external;\\n\\n function trustedBurnTokens(uint256 _amount) external;\\n\\n function trustedWithdrawETH(address payable _to, uint256 _amount) external;\\n\\n function depositETH() external payable returns (bool);\\n\\n function setCurrentRewardTokens() external;\\n\\n function currentMintableTokens() external view returns (uint256);\\n\\n function currentMintedTokens() external view returns (uint256);\\n\\n // Public functions\\n function getController() external view returns (IController);\\n}\\n\",\"keccak256\":\"0x3fbb7a4239a8b5979fb4c45a41495e9694a9f454de82dca3cf6a14dfe71255c7\",\"license\":\"MIT\"},\"contracts/zeppelin/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n/**\\n * @title Ownable\\n * @dev The Ownable contract has an owner address, and provides basic authorization control\\n * functions, this simplifies the implementation of \\\"user permissions\\\".\\n */\\ncontract Ownable {\\n address public owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev The Ownable constructor sets the original `owner` of the contract to the sender\\n * account.\\n */\\n constructor() {\\n owner = msg.sender;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(msg.sender == owner);\\n _;\\n }\\n\\n /**\\n * @dev Allows the current owner to transfer control of the contract to a newOwner.\\n * @param newOwner The address to transfer ownership to.\\n */\\n function transferOwnership(address newOwner) public onlyOwner {\\n require(newOwner != address(0));\\n emit OwnershipTransferred(owner, newOwner);\\n owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x64f114689f2f161c4a4b8fc8442ab914436a33e6021bf17401eaeac73319a419\",\"license\":\"MIT\"},\"contracts/zeppelin/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./Ownable.sol\\\";\\n\\n/**\\n * @title Pausable\\n * @dev Base contract which allows children to implement an emergency stop mechanism.\\n */\\ncontract Pausable is Ownable {\\n event Pause();\\n event Unpause();\\n\\n bool public paused;\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused);\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n */\\n modifier whenPaused() {\\n require(paused);\\n _;\\n }\\n\\n /**\\n * @dev called by the owner to pause, triggers stopped state\\n */\\n function pause() public onlyOwner whenNotPaused {\\n paused = true;\\n emit Pause();\\n }\\n\\n /**\\n * @dev called by the owner to unpause, returns to normal state\\n */\\n function unpause() public onlyOwner whenPaused {\\n paused = false;\\n emit Unpause();\\n }\\n}\\n\",\"keccak256\":\"0xe9635fcac46c22547a08f6977a8c75e7341411f1201f60bdd4c79c26e6c286ef\",\"license\":\"MIT\"}},\"version\":1}", - "bytecode": "0x60806040523480156200001157600080fd5b5060405162002fb038038062002fb083398101604081905262000034916200005a565b600080546001600160a01b0319166001600160a01b03929092169190911790556200008c565b6000602082840312156200006d57600080fd5b81516001600160a01b03811681146200008557600080fd5b9392505050565b612f14806200009c6000396000f3fe6080604052600436106101405760003560e01c806381779f38116100b6578063c2c4c2c81161006f578063c2c4c2c814610329578063c92978081461033e578063d01b808e1461035e578063e1a589da1461037e578063ec8b3cb6146103ac578063f77c4791146103cc57600080fd5b806381779f381461028b578063856a2cf8146102ab57806392eefe9b146102c1578063989f789c146102e1578063a69df4b5146102f4578063b03fa8641461030957600080fd5b8063511f407311610108578063511f4073146101f557806351720b411461020857806359a515ba1461021e5780635b6333eb1461024e5780636caa736b1461027b5780636f9c3c8f1461028357600080fd5b8063121cdcc21461014557806320d3a0b41461017a5780633ccfd60b1461019e5780633d0ddf84146101b55780634ac826da146101d5575b600080fd5b34801561015157600080fd5b506101656101603660046126c0565b610404565b60405190151581526020015b60405180910390f35b34801561018657600080fd5b5061019060045481565b604051908152602001610171565b3480156101aa57600080fd5b506101b3610440565b005b3480156101c157600080fd5b506101b36101d03660046126dd565b6105c6565b3480156101e157600080fd5b506101906101f03660046126f6565b61062d565b6101b361020336600461272f565b6106ef565b34801561021457600080fd5b5061019060015481565b34801561022a57600080fd5b506101656102393660046126dd565b60056020526000908152604090205460ff1681565b34801561025a57600080fd5b5061026e6102693660046126c0565b6106fe565b6040516101719190612751565b6101b36107cc565b6101b3610862565b34801561029757600080fd5b506101906102a63660046126f6565b6108bd565b3480156102b757600080fd5b5061019060065481565b3480156102cd57600080fd5b506101b36102dc3660046126c0565b610ad2565b6101b36102ef366004612768565b610b28565b34801561030057600080fd5b506101b3610cb7565b34801561031557600080fd5b5061019061032436600461290f565b610e4b565b34801561033557600080fd5b506101b3610e9d565b34801561034a57600080fd5b506101b36103593660046126dd565b610ec3565b34801561036a57600080fd5b506101b3610379366004612a5b565b610f8b565b34801561038a57600080fd5b5061039e6103993660046126c0565b6110d2565b604051610171929190612b53565b3480156103b857600080fd5b506101b36103c7366004612b79565b611133565b3480156103d857600080fd5b506000546103ec906001600160a01b031681565b6040516001600160a01b039091168152602001610171565b6001600160a01b0381166000908152600360209081526040808320815180830190925280548252600101549181018290529015155b9392505050565b610448611445565b33600090815260036020908152604080832080546002909352922054811515806104725750600081115b6104975760405162461bcd60e51b815260040161048e90612be6565b60405180910390fd5b6040805180820190915283548152600184015460209091018190526104fe5760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b60408051808201909152835481526001840154602082015261051f9061150b565b156105605760405162461bcd60e51b81526020600482015260116024820152701858d8dbdd5b9d081a5cc81b1bd8dad959607a1b604482015260640161048e565b60008084553381526002602052604081205561058533610580848461159f565b6115ab565b604080518381526020810183905233917fdf273cb619d95419a9cd0ec88123a0538c85064229baa6363788f743fff90deb91015b60405180910390a2505050565b6105ce61161b565b60048190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252600c908201526b1d5b9b1bd8dad4195c9a5bd960a21b604082015260600190565b60405180910390a150565b6001600160a01b03821660009081526002602052604081208161064e6116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561068657600080fd5b505afa15801561069a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106be9190612c29565b60009081526002909201602090815260408084206001600160a01b0387168552909152909120549150505b92915050565b6106fa338383610b28565b5050565b604080518082018252600080825260208083018290526001600160a01b0385168083526002808352948320805485529083529390529091600101906107416116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561077957600080fd5b505afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b19190612c29565b81526020808201929092526040016000205490820152919050565b6107d4611445565b33600081815260036020526040902080543491906107f2908361159f565b80825560408051808201909152908152600182015460209091018190521561081e5761081e81846117a1565b61082734611846565b826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f836040516105b991815260200190565b61086a611445565b336000818152600360205260409020349061088583836118c1565b604080518082019091528154815260018201546020909101819052156108af576108af81846117a1565b6108b834611846565b505050565b6001600160a01b0382166000908152600260205260408120816108de6116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561091657600080fd5b505afa15801561092a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094e9190612c29565b9050610958611933565b60405163022008dd60e21b81526001600160a01b038681166004830152919091169063088023749060240160206040518083038186803b15801561099b57600080fd5b505afa1580156109af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d39190612c42565b6109e2576000925050506106e9565b60006109ec611933565b6001600160a01b0316632a4e0d556040518163ffffffff1660e01b815260040160206040518083038186803b158015610a2457600080fd5b505afa158015610a38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5c9190612c29565b905080610a6f57600093505050506106e9565b60008281526001840160205260408120548454610a8b9161159f565b600084815260028601602090815260408083206001600160a01b038b168452909152902054909150610ac790610ac18385611984565b90611990565b979650505050505050565b610ada61199c565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7090602001610622565b610b30611445565b8181610b3c828261159f565b3414610bba5760405162461bcd60e51b815260206004820152604160248201527f6d73672e76616c756520646f6573206e6f7420657175616c2073756d206f662060448201527f6465706f73697420616d6f756e7420616e64207265736572766520616d6f756e6064820152601d60fa1b608482015260a40161048e565b6001600160a01b0385166000908152600360205260409020805486918691610be2908361159f565b808255604080518082019091529081526001820154602090910181905215610c0e57610c0e81846117a1565b6001600160a01b038816600090815260036020526040902088908790610c3483836118c1565b60408051808201909152815481526001820154602090910181905215610c5e57610c5e81846117a1565b610c6734611846565b505050826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f83604051610ca591815260200190565b60405180910390a25050505050505050565b610cbf611445565b3360009081526003602052604090208054151580610cea575033600090815260026020526040812054115b610d065760405162461bcd60e51b815260040161048e90612be6565b60408051808201909152815481526001820154602090910181905215610d6e5760405162461bcd60e51b815260206004820152601860248201527f756e6c6f636b20616c726561647920696e697469617465640000000000000000604482015260640161048e565b6000610d786116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610db057600080fd5b505afa158015610dc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de89190612c29565b9050610dff6004548261159f90919063ffffffff16565b6001830181905560405133917ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c200491610e3f91858252602082015260400190565b60405180910390a25050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098610e80989097969101612c90565b604051602081830303815290604052805190602001209050919050565b610ea5611445565b33600081815260036020526040902090610ec09082906117a1565b50565b610ecb61161b565b60008111610f2f5760405162461bcd60e51b815260206004820152602b60248201527f7469636b657456616c6964697479506572696f64206d7573742062652067726560448201526a061746572207468616e20360ac1b606482015260840161048e565b60068190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252601490820152731d1a58dad95d15985b1a591a5d1e54195c9a5bd960621b604082015260600190565b610f93611445565b610f9b6116ff565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fd357600080fd5b505afa158015610fe7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100b9190612c42565b6110575760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b60005b83518110156110cc576110b984828151811061107857611078612cf2565b602002602001015184838151811061109257611092612cf2565b60200260200101518484815181106110ac576110ac612cf2565b60200260200101516119f6565b50806110c481612d1e565b91505061105a565b50505050565b60408051808201825260008082526020918201819052825180840184528181528083018290526001600160a01b03851682526003835290839020835180850190945280548452600101549183019190915261112c836106fe565b9050915091565b61113b611445565b6111436116ff565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117b57600080fd5b505afa15801561118f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b39190612c42565b6111ff5760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b600061120a84610e4b565b905061121884828585611a97565b6020808501516001600160a01b03166000908152600382526040908190208151808301909252805482526001810154928201929092526112579061150b565b6112985760405162461bcd60e51b81526020600482015260126024820152711cd95b99195c881a5cc81d5b9b1bd8dad95960721b604482015260640161048e565b80541515806112c9575060006112c786602001516001600160a01b031660009081526002602052604090205490565b115b6112e55760405162461bcd60e51b815260040161048e90612be6565b600082815260056020526040808220805460ff19166001179055825490870151111561134e5761134361133b8760200151886000015161133686600001548b6040015161199090919063ffffffff16565b611ce6565b83549061159f565b600083559050611363565b50604085015181546113609082611990565b82555b80156113d25761137c8660000151828860c00151611e7e565b85600001516001600160a01b031686602001516001600160a01b03167f8b87351a208c06e3ceee59d80725fd77a23b4129e1b51ca231fc89b40712649c836040516113c991815260200190565b60405180910390a35b85600001516001600160a01b031686602001516001600160a01b03167fc389eb51ed006dbf2528507f010efdf5225ea596e1e1741d74f550dab1925ee7886040015189606001518a60800151898c60c00151604051611435959493929190612d65565b60405180910390a3505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561149157600080fd5b505afa1580156114a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c99190612c42565b156115095760405162461bcd60e51b815260206004820152601060248201526f1cde5cdd195b481a5cc81c185d5cd95960821b604482015260640161048e565b565b60008160200151600014806106e9575081602001516115286116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561156057600080fd5b505afa158015611574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115989190612c29565b1092915050565b60006104398284612d90565b6115b3611f05565b6040516320283da960e01b81526001600160a01b0384811660048301526024820184905291909116906320283da990604401600060405180830381600087803b1580156115ff57600080fd5b505af1158015611613573d6000803e3d6000fd5b505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166757600080fd5b505afa15801561167b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169f9190612da8565b6001600160a01b0316336001600160a01b0316146115095760405162461bcd60e51b815260206004820152601f60248201527f63616c6c6572206d75737420626520436f6e74726f6c6c6572206f776e657200604482015260640161048e565b60008054604051631c2d8fb360e31b81527fe8438ea868df48e3fc21f2f087b993c9b1837dc0f6135064161ce7d7a1701fe860048201526001600160a01b039091169063e16c7d98906024015b60206040518083038186803b15801561176457600080fd5b505afa158015611778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179c9190612da8565b905090565b6040805180820190915282548152600183015460209091018190526118085760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b6000600183018190556040516001600160a01b038316917ffa044b7b93a40365dc68049797c2eb06918523d694e5d56e406cac3eb35578e591a25050565b61184e611f05565b6001600160a01b031663f6326fb3826040518263ffffffff1660e01b81526004016020604051808303818588803b15801561188857600080fd5b505af115801561189c573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106fa9190612c42565b6001600160a01b0382166000908152600260205260409020546118e4908261159f565b6001600160a01b038316600081815260026020526040908190209290925590517fb52b99b9e83551fcbd069b559cc3e823e2a1a3bad8ece46561ea77524394c85090610e3f9084815260200190565b60008054604051631c2d8fb360e31b81527f2517d59a36a86548e38734e8ab416f42afff4bca78706a66ad65750dae7f9e3760048201526001600160a01b039091169063e16c7d989060240161174c565b60006104398284612dc5565b60006104398284612de7565b6000546001600160a01b031633146115095760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015260640161048e565b600080848484604051602401611a0e93929190612dfe565b60408051601f198184030181529181526020820180516001600160e01b03166376459e5b60e11b179052519091503090611a49908390612e8a565b6000604051808303816000865af19150503d8060008114611a86576040519150601f19603f3d011682016040523d82523d6000602084013e611a8b565b606091505b50909695505050505050565b83516001600160a01b0316611aee5760405162461bcd60e51b815260206004820181905260248201527f7469636b657420726563697069656e74206973206e756c6c2061646472657373604482015260640161048e565b60208401516001600160a01b0316611b485760405162461bcd60e51b815260206004820152601d60248201527f7469636b65742073656e646572206973206e756c6c2061646472657373000000604482015260640161048e565b611b558460c00151611f56565b60a08401516040805160208101849052016040516020818303038152906040528051906020012014611be05760405162461bcd60e51b815260206004820152602e60248201527f726563697069656e7452616e6420646f6573206e6f74206d617463682072656360448201526d0d2e0d2cadce8a4c2dcc890c2e6d60931b606482015260840161048e565b60008381526005602052604090205460ff1615611c305760405162461bcd60e51b815260206004820152600e60248201526d1d1a58dad95d081a5cc81d5cd95960921b604482015260640161048e565b611c3f846020015183856121a3565b611c965760405162461bcd60e51b815260206004820152602260248201527f696e76616c6964207369676e6174757265206f766572207469636b65742068616044820152610e6d60f31b606482015260840161048e565b611ca58282866060015161223d565b6110cc5760405162461bcd60e51b81526020600482015260126024820152713a34b1b5b2ba103234b2103737ba103bb4b760711b604482015260640161048e565b600080611cf385856108bd565b90506000818411611d045783611d06565b815b90508015611e75576000611d186116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d5057600080fd5b505afa158015611d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d889190612c29565b6001600160a01b0388166000908152600260209081526040808320848452600181019092529091205491925090611dbf908461159f565b60008381526001830160209081526040808320939093556002840181528282206001600160a01b038b16835290522054611df9908461159f565b600083815260028301602090815260408083206001600160a01b038c1684529091529020558054611e2a9084611990565b8155604080516001600160a01b038981168252602082018690528a16917f5c2b394723f408a40a60335e24b71829642e35f350cebe2036a96a66e895ea98910160405180910390a250505b95945050505050565b6000611e8982612274565b509050611e94611933565b604051630ebad44b60e21b81526001600160a01b03868116600483015260248201869052604482018490529190911690633aeb512c90606401600060405180830381600087803b158015611ee757600080fd5b505af1158015611efb573d6000803e3d6000fd5b5050505050505050565b60008054604051631c2d8fb360e31b81527f6e58ad548d72b425ea94c15f453bf26caddb061d82b2551db7fdd3cefe0e994060048201526001600160a01b039091169063e16c7d989060240161174c565b600080611f6283612274565b915091506000611f706116ff565b6001600160a01b0316633aa4add4846040518263ffffffff1660e01b8152600401611f9d91815260200190565b60206040518083038186803b158015611fb557600080fd5b505afa158015611fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fed9190612c29565b9050806120545760405162461bcd60e51b815260206004820152602f60248201527f7469636b6574206372656174696f6e526f756e6420646f6573206e6f7420686160448201526e0ecca40c240c4d8dec6d640d0c2e6d608b1b606482015260840161048e565b8082146120c95760405162461bcd60e51b815260206004820152603760248201527f7469636b6574206372656174696f6e526f756e64426c6f636b4861736820696e60448201527f76616c696420666f72206372656174696f6e526f756e64000000000000000000606482015260840161048e565b60006120d36116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561210b57600080fd5b505afa15801561211f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121439190612c29565b90508061215b6006548661159f90919063ffffffff16565b1161219c5760405162461bcd60e51b81526020600482015260116024820152701d1a58dad95d081a5cc8195e1c1a5c9959607a1b604482015260640161048e565b5050505050565b600082516041146121f65760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5349474e41545552455f4c454e4754480000000000000000604482015260640161048e565b600061220a612204846122f5565b85612330565b90506001600160a01b03811615801590611e755750806001600160a01b0316856001600160a01b03161495945050505050565b6000818484604051602001612253929190612ea6565b60408051601f19818403018152919052805160209091012010949350505050565b60008082516040146122e45760405162461bcd60e51b815260206004820152603360248201527f696e76616c6964206c656e67746820666f72207469636b657420617578446174604482015272613a206d75737420626520363420627974657360681b606482015260840161048e565b505060208101516040909101519091565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01610e80565b600080600061233f8585612354565b9150915061234c816123c4565b509392505050565b60008082516041141561238b5760208301516040840151606085015160001a61237f8782858561257f565b945094505050506123bd565b8251604014156123b557602083015160408401516123aa86838361266c565b9350935050506123bd565b506000905060025b9250929050565b60008160048111156123d8576123d8612ec8565b14156123e15750565b60018160048111156123f5576123f5612ec8565b14156124435760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161048e565b600281600481111561245757612457612ec8565b14156124a55760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161048e565b60038160048111156124b9576124b9612ec8565b14156125125760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161048e565b600481600481111561252657612526612ec8565b1415610ec05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161048e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156125b65750600090506003612663565b8460ff16601b141580156125ce57508460ff16601c14155b156125df5750600090506004612663565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612633573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661265c57600060019250925050612663565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161268d8782888561257f565b935093505050935093915050565b6001600160a01b0381168114610ec057600080fd5b80356126bb8161269b565b919050565b6000602082840312156126d257600080fd5b81356104398161269b565b6000602082840312156126ef57600080fd5b5035919050565b6000806040838503121561270957600080fd5b82356127148161269b565b915060208301356127248161269b565b809150509250929050565b6000806040838503121561274257600080fd5b50508035926020909101359150565b8151815260208083015190820152604081016106e9565b60008060006060848603121561277d57600080fd5b83356127888161269b565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156127d6576127d661279d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156128055761280561279d565b604052919050565b600082601f83011261281e57600080fd5b813567ffffffffffffffff8111156128385761283861279d565b61284b601f8201601f19166020016127dc565b81815284602083860101111561286057600080fd5b816020850160208301376000918101602001919091529392505050565b600060e0828403121561288f57600080fd5b6128976127b3565b90506128a2826126b0565b81526128b0602083016126b0565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013567ffffffffffffffff8111156128f757600080fd5b6129038482850161280d565b60c08301525092915050565b60006020828403121561292157600080fd5b813567ffffffffffffffff81111561293857600080fd5b6129448482850161287d565b949350505050565b600067ffffffffffffffff8211156129665761296661279d565b5060051b60200190565b600082601f83011261298157600080fd5b813560206129966129918361294c565b6127dc565b82815260059290921b840181019181810190868411156129b557600080fd5b8286015b848110156129f557803567ffffffffffffffff8111156129d95760008081fd5b6129e78986838b010161280d565b8452509183019183016129b9565b509695505050505050565b600082601f830112612a1157600080fd5b81356020612a216129918361294c565b82815260059290921b84018101918181019086841115612a4057600080fd5b8286015b848110156129f55780358352918301918301612a44565b600080600060608486031215612a7057600080fd5b833567ffffffffffffffff80821115612a8857600080fd5b818601915086601f830112612a9c57600080fd5b81356020612aac6129918361294c565b82815260059290921b8401810191818101908a841115612acb57600080fd5b8286015b84811015612b0357803586811115612ae75760008081fd5b612af58d86838b010161287d565b845250918301918301612acf565b5097505087013592505080821115612b1a57600080fd5b612b2687838801612970565b93506040860135915080821115612b3c57600080fd5b50612b4986828701612a00565b9150509250925092565b825181526020808401518183015282516040830152820151606082015260808101610439565b600080600060608486031215612b8e57600080fd5b833567ffffffffffffffff80821115612ba657600080fd5b612bb28783880161287d565b94506020860135915080821115612bc857600080fd5b50612bd58682870161280d565b925050604084013590509250925092565b60208082526023908201527f73656e646572206465706f73697420616e64207265736572766520617265207a60408201526265726f60e81b606082015260800190565b600060208284031215612c3b57600080fd5b5051919050565b600060208284031215612c5457600080fd5b8151801515811461043957600080fd5b60005b83811015612c7f578181015183820152602001612c67565b838111156110cc5750506000910152565b60006bffffffffffffffffffffffff19808a60601b168352808960601b166014840152508660288301528560488301528460688301528360888301528251612cdf8160a8850160208701612c64565b9190910160a80198975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612d3257612d32612d08565b5060010190565b60008151808452612d51816020860160208601612c64565b601f01601f19169290920160200192915050565b85815284602082015283604082015282606082015260a060808201526000610ac760a0830184612d39565b60008219821115612da357612da3612d08565b500190565b600060208284031215612dba57600080fd5b81516104398161269b565b600082612de257634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612df957612df9612d08565b500390565b60608152600060018060a01b0380865116606084015280602087015116608084015250604085015160a0830152606085015160c0830152608085015160e083015260a085015161010083015260c085015160e0610120840152612e65610140840182612d39565b90508281036020840152612e798186612d39565b915050826040830152949350505050565b60008251612e9c818460208701612c64565b9190910192915050565b60008351612eb8818460208801612c64565b9190910191825250602001919050565b634e487b7160e01b600052602160045260246000fdfea26469706673582212208c3e7caca484083884d0cfaede3b1bd63bef066a92632853811fd1321dbe68cd64736f6c63430008090033", - "deployedBytecode": "0x6080604052600436106101405760003560e01c806381779f38116100b6578063c2c4c2c81161006f578063c2c4c2c814610329578063c92978081461033e578063d01b808e1461035e578063e1a589da1461037e578063ec8b3cb6146103ac578063f77c4791146103cc57600080fd5b806381779f381461028b578063856a2cf8146102ab57806392eefe9b146102c1578063989f789c146102e1578063a69df4b5146102f4578063b03fa8641461030957600080fd5b8063511f407311610108578063511f4073146101f557806351720b411461020857806359a515ba1461021e5780635b6333eb1461024e5780636caa736b1461027b5780636f9c3c8f1461028357600080fd5b8063121cdcc21461014557806320d3a0b41461017a5780633ccfd60b1461019e5780633d0ddf84146101b55780634ac826da146101d5575b600080fd5b34801561015157600080fd5b506101656101603660046126c0565b610404565b60405190151581526020015b60405180910390f35b34801561018657600080fd5b5061019060045481565b604051908152602001610171565b3480156101aa57600080fd5b506101b3610440565b005b3480156101c157600080fd5b506101b36101d03660046126dd565b6105c6565b3480156101e157600080fd5b506101906101f03660046126f6565b61062d565b6101b361020336600461272f565b6106ef565b34801561021457600080fd5b5061019060015481565b34801561022a57600080fd5b506101656102393660046126dd565b60056020526000908152604090205460ff1681565b34801561025a57600080fd5b5061026e6102693660046126c0565b6106fe565b6040516101719190612751565b6101b36107cc565b6101b3610862565b34801561029757600080fd5b506101906102a63660046126f6565b6108bd565b3480156102b757600080fd5b5061019060065481565b3480156102cd57600080fd5b506101b36102dc3660046126c0565b610ad2565b6101b36102ef366004612768565b610b28565b34801561030057600080fd5b506101b3610cb7565b34801561031557600080fd5b5061019061032436600461290f565b610e4b565b34801561033557600080fd5b506101b3610e9d565b34801561034a57600080fd5b506101b36103593660046126dd565b610ec3565b34801561036a57600080fd5b506101b3610379366004612a5b565b610f8b565b34801561038a57600080fd5b5061039e6103993660046126c0565b6110d2565b604051610171929190612b53565b3480156103b857600080fd5b506101b36103c7366004612b79565b611133565b3480156103d857600080fd5b506000546103ec906001600160a01b031681565b6040516001600160a01b039091168152602001610171565b6001600160a01b0381166000908152600360209081526040808320815180830190925280548252600101549181018290529015155b9392505050565b610448611445565b33600090815260036020908152604080832080546002909352922054811515806104725750600081115b6104975760405162461bcd60e51b815260040161048e90612be6565b60405180910390fd5b6040805180820190915283548152600184015460209091018190526104fe5760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b60408051808201909152835481526001840154602082015261051f9061150b565b156105605760405162461bcd60e51b81526020600482015260116024820152701858d8dbdd5b9d081a5cc81b1bd8dad959607a1b604482015260640161048e565b60008084553381526002602052604081205561058533610580848461159f565b6115ab565b604080518381526020810183905233917fdf273cb619d95419a9cd0ec88123a0538c85064229baa6363788f743fff90deb91015b60405180910390a2505050565b6105ce61161b565b60048190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252600c908201526b1d5b9b1bd8dad4195c9a5bd960a21b604082015260600190565b60405180910390a150565b6001600160a01b03821660009081526002602052604081208161064e6116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561068657600080fd5b505afa15801561069a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106be9190612c29565b60009081526002909201602090815260408084206001600160a01b0387168552909152909120549150505b92915050565b6106fa338383610b28565b5050565b604080518082018252600080825260208083018290526001600160a01b0385168083526002808352948320805485529083529390529091600101906107416116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561077957600080fd5b505afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b19190612c29565b81526020808201929092526040016000205490820152919050565b6107d4611445565b33600081815260036020526040902080543491906107f2908361159f565b80825560408051808201909152908152600182015460209091018190521561081e5761081e81846117a1565b61082734611846565b826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f836040516105b991815260200190565b61086a611445565b336000818152600360205260409020349061088583836118c1565b604080518082019091528154815260018201546020909101819052156108af576108af81846117a1565b6108b834611846565b505050565b6001600160a01b0382166000908152600260205260408120816108de6116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561091657600080fd5b505afa15801561092a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061094e9190612c29565b9050610958611933565b60405163022008dd60e21b81526001600160a01b038681166004830152919091169063088023749060240160206040518083038186803b15801561099b57600080fd5b505afa1580156109af573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109d39190612c42565b6109e2576000925050506106e9565b60006109ec611933565b6001600160a01b0316632a4e0d556040518163ffffffff1660e01b815260040160206040518083038186803b158015610a2457600080fd5b505afa158015610a38573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a5c9190612c29565b905080610a6f57600093505050506106e9565b60008281526001840160205260408120548454610a8b9161159f565b600084815260028601602090815260408083206001600160a01b038b168452909152902054909150610ac790610ac18385611984565b90611990565b979650505050505050565b610ada61199c565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7090602001610622565b610b30611445565b8181610b3c828261159f565b3414610bba5760405162461bcd60e51b815260206004820152604160248201527f6d73672e76616c756520646f6573206e6f7420657175616c2073756d206f662060448201527f6465706f73697420616d6f756e7420616e64207265736572766520616d6f756e6064820152601d60fa1b608482015260a40161048e565b6001600160a01b0385166000908152600360205260409020805486918691610be2908361159f565b808255604080518082019091529081526001820154602090910181905215610c0e57610c0e81846117a1565b6001600160a01b038816600090815260036020526040902088908790610c3483836118c1565b60408051808201909152815481526001820154602090910181905215610c5e57610c5e81846117a1565b610c6734611846565b505050826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f83604051610ca591815260200190565b60405180910390a25050505050505050565b610cbf611445565b3360009081526003602052604090208054151580610cea575033600090815260026020526040812054115b610d065760405162461bcd60e51b815260040161048e90612be6565b60408051808201909152815481526001820154602090910181905215610d6e5760405162461bcd60e51b815260206004820152601860248201527f756e6c6f636b20616c726561647920696e697469617465640000000000000000604482015260640161048e565b6000610d786116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610db057600080fd5b505afa158015610dc4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610de89190612c29565b9050610dff6004548261159f90919063ffffffff16565b6001830181905560405133917ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c200491610e3f91858252602082015260400190565b60405180910390a25050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098610e80989097969101612c90565b604051602081830303815290604052805190602001209050919050565b610ea5611445565b33600081815260036020526040902090610ec09082906117a1565b50565b610ecb61161b565b60008111610f2f5760405162461bcd60e51b815260206004820152602b60248201527f7469636b657456616c6964697479506572696f64206d7573742062652067726560448201526a061746572207468616e20360ac1b606482015260840161048e565b60068190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252601490820152731d1a58dad95d15985b1a591a5d1e54195c9a5bd960621b604082015260600190565b610f93611445565b610f9b6116ff565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b158015610fd357600080fd5b505afa158015610fe7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061100b9190612c42565b6110575760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b60005b83518110156110cc576110b984828151811061107857611078612cf2565b602002602001015184838151811061109257611092612cf2565b60200260200101518484815181106110ac576110ac612cf2565b60200260200101516119f6565b50806110c481612d1e565b91505061105a565b50505050565b60408051808201825260008082526020918201819052825180840184528181528083018290526001600160a01b03851682526003835290839020835180850190945280548452600101549183019190915261112c836106fe565b9050915091565b61113b611445565b6111436116ff565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561117b57600080fd5b505afa15801561118f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111b39190612c42565b6111ff5760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b600061120a84610e4b565b905061121884828585611a97565b6020808501516001600160a01b03166000908152600382526040908190208151808301909252805482526001810154928201929092526112579061150b565b6112985760405162461bcd60e51b81526020600482015260126024820152711cd95b99195c881a5cc81d5b9b1bd8dad95960721b604482015260640161048e565b80541515806112c9575060006112c786602001516001600160a01b031660009081526002602052604090205490565b115b6112e55760405162461bcd60e51b815260040161048e90612be6565b600082815260056020526040808220805460ff19166001179055825490870151111561134e5761134361133b8760200151886000015161133686600001548b6040015161199090919063ffffffff16565b611ce6565b83549061159f565b600083559050611363565b50604085015181546113609082611990565b82555b80156113d25761137c8660000151828860c00151611e7e565b85600001516001600160a01b031686602001516001600160a01b03167f8b87351a208c06e3ceee59d80725fd77a23b4129e1b51ca231fc89b40712649c836040516113c991815260200190565b60405180910390a35b85600001516001600160a01b031686602001516001600160a01b03167fc389eb51ed006dbf2528507f010efdf5225ea596e1e1741d74f550dab1925ee7886040015189606001518a60800151898c60c00151604051611435959493929190612d65565b60405180910390a3505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b15801561149157600080fd5b505afa1580156114a5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114c99190612c42565b156115095760405162461bcd60e51b815260206004820152601060248201526f1cde5cdd195b481a5cc81c185d5cd95960821b604482015260640161048e565b565b60008160200151600014806106e9575081602001516115286116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561156057600080fd5b505afa158015611574573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115989190612c29565b1092915050565b60006104398284612d90565b6115b3611f05565b6040516320283da960e01b81526001600160a01b0384811660048301526024820184905291909116906320283da990604401600060405180830381600087803b1580156115ff57600080fd5b505af1158015611613573d6000803e3d6000fd5b505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b15801561166757600080fd5b505afa15801561167b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061169f9190612da8565b6001600160a01b0316336001600160a01b0316146115095760405162461bcd60e51b815260206004820152601f60248201527f63616c6c6572206d75737420626520436f6e74726f6c6c6572206f776e657200604482015260640161048e565b60008054604051631c2d8fb360e31b81527fe8438ea868df48e3fc21f2f087b993c9b1837dc0f6135064161ce7d7a1701fe860048201526001600160a01b039091169063e16c7d98906024015b60206040518083038186803b15801561176457600080fd5b505afa158015611778573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061179c9190612da8565b905090565b6040805180820190915282548152600183015460209091018190526118085760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b6000600183018190556040516001600160a01b038316917ffa044b7b93a40365dc68049797c2eb06918523d694e5d56e406cac3eb35578e591a25050565b61184e611f05565b6001600160a01b031663f6326fb3826040518263ffffffff1660e01b81526004016020604051808303818588803b15801561188857600080fd5b505af115801561189c573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106fa9190612c42565b6001600160a01b0382166000908152600260205260409020546118e4908261159f565b6001600160a01b038316600081815260026020526040908190209290925590517fb52b99b9e83551fcbd069b559cc3e823e2a1a3bad8ece46561ea77524394c85090610e3f9084815260200190565b60008054604051631c2d8fb360e31b81527f2517d59a36a86548e38734e8ab416f42afff4bca78706a66ad65750dae7f9e3760048201526001600160a01b039091169063e16c7d989060240161174c565b60006104398284612dc5565b60006104398284612de7565b6000546001600160a01b031633146115095760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015260640161048e565b600080848484604051602401611a0e93929190612dfe565b60408051601f198184030181529181526020820180516001600160e01b03166376459e5b60e11b179052519091503090611a49908390612e8a565b6000604051808303816000865af19150503d8060008114611a86576040519150601f19603f3d011682016040523d82523d6000602084013e611a8b565b606091505b50909695505050505050565b83516001600160a01b0316611aee5760405162461bcd60e51b815260206004820181905260248201527f7469636b657420726563697069656e74206973206e756c6c2061646472657373604482015260640161048e565b60208401516001600160a01b0316611b485760405162461bcd60e51b815260206004820152601d60248201527f7469636b65742073656e646572206973206e756c6c2061646472657373000000604482015260640161048e565b611b558460c00151611f56565b60a08401516040805160208101849052016040516020818303038152906040528051906020012014611be05760405162461bcd60e51b815260206004820152602e60248201527f726563697069656e7452616e6420646f6573206e6f74206d617463682072656360448201526d0d2e0d2cadce8a4c2dcc890c2e6d60931b606482015260840161048e565b60008381526005602052604090205460ff1615611c305760405162461bcd60e51b815260206004820152600e60248201526d1d1a58dad95d081a5cc81d5cd95960921b604482015260640161048e565b611c3f846020015183856121a3565b611c965760405162461bcd60e51b815260206004820152602260248201527f696e76616c6964207369676e6174757265206f766572207469636b65742068616044820152610e6d60f31b606482015260840161048e565b611ca58282866060015161223d565b6110cc5760405162461bcd60e51b81526020600482015260126024820152713a34b1b5b2ba103234b2103737ba103bb4b760711b604482015260640161048e565b600080611cf385856108bd565b90506000818411611d045783611d06565b815b90508015611e75576000611d186116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611d5057600080fd5b505afa158015611d64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d889190612c29565b6001600160a01b0388166000908152600260209081526040808320848452600181019092529091205491925090611dbf908461159f565b60008381526001830160209081526040808320939093556002840181528282206001600160a01b038b16835290522054611df9908461159f565b600083815260028301602090815260408083206001600160a01b038c1684529091529020558054611e2a9084611990565b8155604080516001600160a01b038981168252602082018690528a16917f5c2b394723f408a40a60335e24b71829642e35f350cebe2036a96a66e895ea98910160405180910390a250505b95945050505050565b6000611e8982612274565b509050611e94611933565b604051630ebad44b60e21b81526001600160a01b03868116600483015260248201869052604482018490529190911690633aeb512c90606401600060405180830381600087803b158015611ee757600080fd5b505af1158015611efb573d6000803e3d6000fd5b5050505050505050565b60008054604051631c2d8fb360e31b81527f6e58ad548d72b425ea94c15f453bf26caddb061d82b2551db7fdd3cefe0e994060048201526001600160a01b039091169063e16c7d989060240161174c565b600080611f6283612274565b915091506000611f706116ff565b6001600160a01b0316633aa4add4846040518263ffffffff1660e01b8152600401611f9d91815260200190565b60206040518083038186803b158015611fb557600080fd5b505afa158015611fc9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611fed9190612c29565b9050806120545760405162461bcd60e51b815260206004820152602f60248201527f7469636b6574206372656174696f6e526f756e6420646f6573206e6f7420686160448201526e0ecca40c240c4d8dec6d640d0c2e6d608b1b606482015260840161048e565b8082146120c95760405162461bcd60e51b815260206004820152603760248201527f7469636b6574206372656174696f6e526f756e64426c6f636b4861736820696e60448201527f76616c696420666f72206372656174696f6e526f756e64000000000000000000606482015260840161048e565b60006120d36116ff565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561210b57600080fd5b505afa15801561211f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121439190612c29565b90508061215b6006548661159f90919063ffffffff16565b1161219c5760405162461bcd60e51b81526020600482015260116024820152701d1a58dad95d081a5cc8195e1c1a5c9959607a1b604482015260640161048e565b5050505050565b600082516041146121f65760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5349474e41545552455f4c454e4754480000000000000000604482015260640161048e565b600061220a612204846122f5565b85612330565b90506001600160a01b03811615801590611e755750806001600160a01b0316856001600160a01b03161495945050505050565b6000818484604051602001612253929190612ea6565b60408051601f19818403018152919052805160209091012010949350505050565b60008082516040146122e45760405162461bcd60e51b815260206004820152603360248201527f696e76616c6964206c656e67746820666f72207469636b657420617578446174604482015272613a206d75737420626520363420627974657360681b606482015260840161048e565b505060208101516040909101519091565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01610e80565b600080600061233f8585612354565b9150915061234c816123c4565b509392505050565b60008082516041141561238b5760208301516040840151606085015160001a61237f8782858561257f565b945094505050506123bd565b8251604014156123b557602083015160408401516123aa86838361266c565b9350935050506123bd565b506000905060025b9250929050565b60008160048111156123d8576123d8612ec8565b14156123e15750565b60018160048111156123f5576123f5612ec8565b14156124435760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161048e565b600281600481111561245757612457612ec8565b14156124a55760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161048e565b60038160048111156124b9576124b9612ec8565b14156125125760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161048e565b600481600481111561252657612526612ec8565b1415610ec05760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161048e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08311156125b65750600090506003612663565b8460ff16601b141580156125ce57508460ff16601c14155b156125df5750600090506004612663565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa158015612633573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b03811661265c57600060019250925050612663565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b0161268d8782888561257f565b935093505050935093915050565b6001600160a01b0381168114610ec057600080fd5b80356126bb8161269b565b919050565b6000602082840312156126d257600080fd5b81356104398161269b565b6000602082840312156126ef57600080fd5b5035919050565b6000806040838503121561270957600080fd5b82356127148161269b565b915060208301356127248161269b565b809150509250929050565b6000806040838503121561274257600080fd5b50508035926020909101359150565b8151815260208083015190820152604081016106e9565b60008060006060848603121561277d57600080fd5b83356127888161269b565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff811182821017156127d6576127d661279d565b60405290565b604051601f8201601f1916810167ffffffffffffffff811182821017156128055761280561279d565b604052919050565b600082601f83011261281e57600080fd5b813567ffffffffffffffff8111156128385761283861279d565b61284b601f8201601f19166020016127dc565b81815284602083860101111561286057600080fd5b816020850160208301376000918101602001919091529392505050565b600060e0828403121561288f57600080fd5b6128976127b3565b90506128a2826126b0565b81526128b0602083016126b0565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013567ffffffffffffffff8111156128f757600080fd5b6129038482850161280d565b60c08301525092915050565b60006020828403121561292157600080fd5b813567ffffffffffffffff81111561293857600080fd5b6129448482850161287d565b949350505050565b600067ffffffffffffffff8211156129665761296661279d565b5060051b60200190565b600082601f83011261298157600080fd5b813560206129966129918361294c565b6127dc565b82815260059290921b840181019181810190868411156129b557600080fd5b8286015b848110156129f557803567ffffffffffffffff8111156129d95760008081fd5b6129e78986838b010161280d565b8452509183019183016129b9565b509695505050505050565b600082601f830112612a1157600080fd5b81356020612a216129918361294c565b82815260059290921b84018101918181019086841115612a4057600080fd5b8286015b848110156129f55780358352918301918301612a44565b600080600060608486031215612a7057600080fd5b833567ffffffffffffffff80821115612a8857600080fd5b818601915086601f830112612a9c57600080fd5b81356020612aac6129918361294c565b82815260059290921b8401810191818101908a841115612acb57600080fd5b8286015b84811015612b0357803586811115612ae75760008081fd5b612af58d86838b010161287d565b845250918301918301612acf565b5097505087013592505080821115612b1a57600080fd5b612b2687838801612970565b93506040860135915080821115612b3c57600080fd5b50612b4986828701612a00565b9150509250925092565b825181526020808401518183015282516040830152820151606082015260808101610439565b600080600060608486031215612b8e57600080fd5b833567ffffffffffffffff80821115612ba657600080fd5b612bb28783880161287d565b94506020860135915080821115612bc857600080fd5b50612bd58682870161280d565b925050604084013590509250925092565b60208082526023908201527f73656e646572206465706f73697420616e64207265736572766520617265207a60408201526265726f60e81b606082015260800190565b600060208284031215612c3b57600080fd5b5051919050565b600060208284031215612c5457600080fd5b8151801515811461043957600080fd5b60005b83811015612c7f578181015183820152602001612c67565b838111156110cc5750506000910152565b60006bffffffffffffffffffffffff19808a60601b168352808960601b166014840152508660288301528560488301528460688301528360888301528251612cdf8160a8850160208701612c64565b9190910160a80198975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612d3257612d32612d08565b5060010190565b60008151808452612d51816020860160208601612c64565b601f01601f19169290920160200192915050565b85815284602082015283604082015282606082015260a060808201526000610ac760a0830184612d39565b60008219821115612da357612da3612d08565b500190565b600060208284031215612dba57600080fd5b81516104398161269b565b600082612de257634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612df957612df9612d08565b500390565b60608152600060018060a01b0380865116606084015280602087015116608084015250604085015160a0830152606085015160c0830152608085015160e083015260a085015161010083015260c085015160e0610120840152612e65610140840182612d39565b90508281036020840152612e798186612d39565b915050826040830152949350505050565b60008251612e9c818460208701612c64565b9190910192915050565b60008351612eb8818460208801612c64565b9190910191825250602001919050565b634e487b7160e01b600052602160045260246000fdfea26469706673582212208c3e7caca484083884d0cfaede3b1bd63bef066a92632853811fd1321dbe68cd64736f6c63430008090033", + "numDeployments": 3, + "solcInputHash": "13bbf81b78bf748dd89a83d5a98b32f5", + "metadata": "{\"compiler\":{\"version\":\"0.8.9+commit.e5eed63a\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"DepositFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"string\",\"name\":\"param\",\"type\":\"string\"}],\"name\":\"ParameterUpdate\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reserveHolder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"address\",\"name\":\"claimant\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReserveClaimed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"reserveHolder\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"ReserveFunded\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"controller\",\"type\":\"address\"}],\"name\":\"SetController\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"startRound\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"endRound\",\"type\":\"uint256\"}],\"name\":\"Unlock\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"UnlockCancelled\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"recipientRand\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"name\":\"WinningTicketRedeemed\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"WinningTicketTransfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"deposit\",\"type\":\"uint256\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"reserve\",\"type\":\"uint256\"}],\"name\":\"Withdrawal\",\"type\":\"event\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientRandHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"internalType\":\"struct MTicketBrokerCore.Ticket[]\",\"name\":\"_tickets\",\"type\":\"tuple[]\"},{\"internalType\":\"bytes[]\",\"name\":\"_sigs\",\"type\":\"bytes[]\"},{\"internalType\":\"uint256[]\",\"name\":\"_recipientRands\",\"type\":\"uint256[]\"}],\"name\":\"batchRedeemWinningTickets\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"cancelUnlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_reserveHolder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_claimant\",\"type\":\"address\"}],\"name\":\"claimableReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_reserveHolder\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_claimant\",\"type\":\"address\"}],\"name\":\"claimedReserve\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"controller\",\"outputs\":[{\"internalType\":\"contract IController\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundDeposit\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_reserveAmount\",\"type\":\"uint256\"}],\"name\":\"fundDepositAndReserve\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_addr\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"_depositAmount\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"_reserveAmount\",\"type\":\"uint256\"}],\"name\":\"fundDepositAndReserveFor\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"fundReserve\",\"outputs\":[],\"stateMutability\":\"payable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_reserveHolder\",\"type\":\"address\"}],\"name\":\"getReserveInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"fundsRemaining\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"claimedInCurrentRound\",\"type\":\"uint256\"}],\"internalType\":\"struct MReserve.ReserveInfo\",\"name\":\"info\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"}],\"name\":\"getSenderInfo\",\"outputs\":[{\"components\":[{\"internalType\":\"uint256\",\"name\":\"deposit\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"withdrawRound\",\"type\":\"uint256\"}],\"internalType\":\"struct MixinTicketBrokerCore.Sender\",\"name\":\"sender\",\"type\":\"tuple\"},{\"components\":[{\"internalType\":\"uint256\",\"name\":\"fundsRemaining\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"claimedInCurrentRound\",\"type\":\"uint256\"}],\"internalType\":\"struct MReserve.ReserveInfo\",\"name\":\"reserve\",\"type\":\"tuple\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientRandHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"internalType\":\"struct MTicketBrokerCore.Ticket\",\"name\":\"_ticket\",\"type\":\"tuple\"}],\"name\":\"getTicketHash\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_sender\",\"type\":\"address\"}],\"name\":\"isUnlockInProgress\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"components\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"faceValue\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"winProb\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"senderNonce\",\"type\":\"uint256\"},{\"internalType\":\"bytes32\",\"name\":\"recipientRandHash\",\"type\":\"bytes32\"},{\"internalType\":\"bytes\",\"name\":\"auxData\",\"type\":\"bytes\"}],\"internalType\":\"struct MTicketBrokerCore.Ticket\",\"name\":\"_ticket\",\"type\":\"tuple\"},{\"internalType\":\"bytes\",\"name\":\"_sig\",\"type\":\"bytes\"},{\"internalType\":\"uint256\",\"name\":\"_recipientRand\",\"type\":\"uint256\"}],\"name\":\"redeemWinningTicket\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"_controller\",\"type\":\"address\"}],\"name\":\"setController\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_ticketValidityPeriod\",\"type\":\"uint256\"}],\"name\":\"setTicketValidityPeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_unlockPeriod\",\"type\":\"uint256\"}],\"name\":\"setUnlockPeriod\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"targetContractId\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"ticketValidityPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlock\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"unlockPeriod\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"name\":\"usedTickets\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"withdraw\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}],\"devdoc\":{\"kind\":\"dev\",\"methods\":{\"batchRedeemWinningTickets((address,address,uint256,uint256,uint256,bytes32,bytes)[],bytes[],uint256[])\":{\"params\":{\"_recipientRands\":\"Array of preimages for the recipientRandHash included in each ticket (`_recipientRands[i]` corresponds to `_tickets[i]`)\",\"_sigs\":\"Array of sender signatures over the hash of tickets (`_sigs[i]` corresponds to `_tickets[i]`)\",\"_tickets\":\"Array of winning tickets to be redeemed in order to claim payment\"}},\"claimableReserve(address,address)\":{\"details\":\"Returns the amount of funds claimable by a claimant from a reserve in the current round\",\"params\":{\"_claimant\":\"Address of claimant\",\"_reserveHolder\":\"Address of reserve holder\"},\"returns\":{\"_0\":\"Amount of funds claimable by `_claimant` from the reserve for `_reserveHolder` in the current round\"}},\"claimedReserve(address,address)\":{\"details\":\"Returns the amount of funds claimed by a claimant from a reserve in the current round\",\"params\":{\"_claimant\":\"Address of claimant\",\"_reserveHolder\":\"Address of reserve holder\"},\"returns\":{\"_0\":\"Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder` in the current round\"}},\"constructor\":{\"details\":\"This constructor will not initialize any state variables besides `controller`. The following setter functions should be used to initialize state variables post-deployment: - setUnlockPeriod() - setTicketValidityPeriod()\",\"params\":{\"_controller\":\"Address of Controller that this contract will be registered with\"}},\"fundDepositAndReserve(uint256,uint256)\":{\"params\":{\"_depositAmount\":\"Amount of ETH to add to the caller's deposit\",\"_reserveAmount\":\"Amount of ETH to add to the caller's reserve\"}},\"fundDepositAndReserveFor(address,uint256,uint256)\":{\"params\":{\"_depositAmount\":\"Amount of ETH to add to the address' deposit\",\"_reserveAmount\":\"Amount of ETH to add to the address' reserve\"}},\"getReserveInfo(address)\":{\"details\":\"Returns info about a reserve\",\"params\":{\"_reserveHolder\":\"Address of reserve holder\"},\"returns\":{\"info\":\"Info about the reserve for `_reserveHolder`\"}},\"getSenderInfo(address)\":{\"params\":{\"_sender\":\"Address of sender\"},\"returns\":{\"reserve\":\"Info about the reserve for `_sender`\",\"sender\":\"Info about the sender for `_sender`\"}},\"getTicketHash((address,address,uint256,uint256,uint256,bytes32,bytes))\":{\"details\":\"Returns the hash of a ticket\",\"params\":{\"_ticket\":\"Ticket to be hashed\"},\"returns\":{\"_0\":\"keccak256 hash of `_ticket`\"}},\"isUnlockInProgress(address)\":{\"params\":{\"_sender\":\"Address of sender\"},\"returns\":{\"_0\":\"Boolean indicating whether `_sender` has an unlock in progress\"}},\"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\":{\"params\":{\"_recipientRand\":\"The preimage for the recipientRandHash included in `_ticket`\",\"_sig\":\"Sender's signature over the hash of `_ticket`\",\"_ticket\":\"Winning ticket to be redeemed in order to claim payment\"}},\"setController(address)\":{\"params\":{\"_controller\":\"Controller contract address\"}},\"setTicketValidityPeriod(uint256)\":{\"params\":{\"_ticketValidityPeriod\":\"Value for ticketValidityPeriod\"}},\"setUnlockPeriod(uint256)\":{\"params\":{\"_unlockPeriod\":\"Value for unlockPeriod\"}}},\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{\"batchRedeemWinningTickets((address,address,uint256,uint256,uint256,bytes32,bytes)[],bytes[],uint256[])\":{\"notice\":\"Redeems multiple winning tickets. The function will redeem all of the provided tickets and handle any failures gracefully without reverting the entire function\"},\"cancelUnlock()\":{\"notice\":\"Cancels the unlock period for the caller\"},\"constructor\":{\"notice\":\"TicketBroker constructor. Only invokes constructor of base Manager contract with provided Controller address\"},\"fundDeposit()\":{\"notice\":\"Adds ETH to the caller's deposit\"},\"fundDepositAndReserve(uint256,uint256)\":{\"notice\":\"Adds ETH to the caller's deposit and reserve\"},\"fundDepositAndReserveFor(address,uint256,uint256)\":{\"notice\":\"Adds ETH to the address' deposit and reserve\"},\"fundReserve()\":{\"notice\":\"Adds ETH to the caller's reserve\"},\"getSenderInfo(address)\":{\"notice\":\"Returns info about a sender\"},\"isUnlockInProgress(address)\":{\"notice\":\"Returns whether a sender is currently in the unlock period\"},\"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\":{\"notice\":\"Redeems a winning ticket that has been signed by a sender and reveals the recipient recipientRand that corresponds to the recipientRandHash included in the ticket\"},\"setController(address)\":{\"notice\":\"Set controller. Only callable by current controller\"},\"setTicketValidityPeriod(uint256)\":{\"notice\":\"Sets ticketValidityPeriod value. Only callable by the Controller owner\"},\"setUnlockPeriod(uint256)\":{\"notice\":\"Sets unlockPeriod value. Only callable by the Controller owner\"},\"unlock()\":{\"notice\":\"Initiates the unlock period for the caller\"},\"withdraw()\":{\"notice\":\"Withdraws all ETH from the caller's deposit and reserve\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/pm/TicketBroker.sol\":\"TicketBroker\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/utils/Strings.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev String operations.\\n */\\nlibrary Strings {\\n bytes16 private constant _HEX_SYMBOLS = \\\"0123456789abcdef\\\";\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\\n */\\n function toString(uint256 value) internal pure returns (string memory) {\\n // Inspired by OraclizeAPI's implementation - MIT licence\\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\\n\\n if (value == 0) {\\n return \\\"0\\\";\\n }\\n uint256 temp = value;\\n uint256 digits;\\n while (temp != 0) {\\n digits++;\\n temp /= 10;\\n }\\n bytes memory buffer = new bytes(digits);\\n while (value != 0) {\\n digits -= 1;\\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\\n value /= 10;\\n }\\n return string(buffer);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\\n */\\n function toHexString(uint256 value) internal pure returns (string memory) {\\n if (value == 0) {\\n return \\\"0x00\\\";\\n }\\n uint256 temp = value;\\n uint256 length = 0;\\n while (temp != 0) {\\n length++;\\n temp >>= 8;\\n }\\n return toHexString(value, length);\\n }\\n\\n /**\\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\\n */\\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\\n bytes memory buffer = new bytes(2 * length + 2);\\n buffer[0] = \\\"0\\\";\\n buffer[1] = \\\"x\\\";\\n for (uint256 i = 2 * length + 1; i > 1; --i) {\\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\\n value >>= 4;\\n }\\n require(value == 0, \\\"Strings: hex length insufficient\\\");\\n return string(buffer);\\n }\\n}\\n\",\"keccak256\":\"0x32c202bd28995dd20c4347b7c6467a6d3241c74c8ad3edcbb610cd9205916c45\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"../Strings.sol\\\";\\n\\n/**\\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\\n *\\n * These functions can be used to verify that a message was signed by the holder\\n * of the private keys of a given address.\\n */\\nlibrary ECDSA {\\n enum RecoverError {\\n NoError,\\n InvalidSignature,\\n InvalidSignatureLength,\\n InvalidSignatureS,\\n InvalidSignatureV\\n }\\n\\n function _throwError(RecoverError error) private pure {\\n if (error == RecoverError.NoError) {\\n return; // no error: do nothing\\n } else if (error == RecoverError.InvalidSignature) {\\n revert(\\\"ECDSA: invalid signature\\\");\\n } else if (error == RecoverError.InvalidSignatureLength) {\\n revert(\\\"ECDSA: invalid signature length\\\");\\n } else if (error == RecoverError.InvalidSignatureS) {\\n revert(\\\"ECDSA: invalid signature 's' value\\\");\\n } else if (error == RecoverError.InvalidSignatureV) {\\n revert(\\\"ECDSA: invalid signature 'v' value\\\");\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature` or error string. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n *\\n * Documentation for signature generation:\\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\\n // Check the signature length\\n // - case 65: r,s,v signature (standard)\\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\\n if (signature.length == 65) {\\n bytes32 r;\\n bytes32 s;\\n uint8 v;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n s := mload(add(signature, 0x40))\\n v := byte(0, mload(add(signature, 0x60)))\\n }\\n return tryRecover(hash, v, r, s);\\n } else if (signature.length == 64) {\\n bytes32 r;\\n bytes32 vs;\\n // ecrecover takes the signature parameters, and the only way to get them\\n // currently is to use assembly.\\n assembly {\\n r := mload(add(signature, 0x20))\\n vs := mload(add(signature, 0x40))\\n }\\n return tryRecover(hash, r, vs);\\n } else {\\n return (address(0), RecoverError.InvalidSignatureLength);\\n }\\n }\\n\\n /**\\n * @dev Returns the address that signed a hashed message (`hash`) with\\n * `signature`. This address can then be used for verification purposes.\\n *\\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\\n * this function rejects them by requiring the `s` value to be in the lower\\n * half order, and the `v` value to be either 27 or 28.\\n *\\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\\n * verification to be secure: it is possible to craft signatures that\\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\\n * this is by receiving a hash of the original message (which may otherwise\\n * be too long), and then calling {toEthSignedMessageHash} on it.\\n */\\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, signature);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\\n *\\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address, RecoverError) {\\n bytes32 s;\\n uint8 v;\\n assembly {\\n s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\\n v := add(shr(255, vs), 27)\\n }\\n return tryRecover(hash, v, r, s);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\\n *\\n * _Available since v4.2._\\n */\\n function recover(\\n bytes32 hash,\\n bytes32 r,\\n bytes32 vs\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n *\\n * _Available since v4.3._\\n */\\n function tryRecover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address, RecoverError) {\\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\\n // the valid range for s in (301): 0 < s < secp256k1n \\u00f7 2 + 1, and for v in (302): v \\u2208 {27, 28}. Most\\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\\n //\\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\\n // these malleable signatures as well.\\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\\n return (address(0), RecoverError.InvalidSignatureS);\\n }\\n if (v != 27 && v != 28) {\\n return (address(0), RecoverError.InvalidSignatureV);\\n }\\n\\n // If the signature is valid (and not malleable), return the signer address\\n address signer = ecrecover(hash, v, r, s);\\n if (signer == address(0)) {\\n return (address(0), RecoverError.InvalidSignature);\\n }\\n\\n return (signer, RecoverError.NoError);\\n }\\n\\n /**\\n * @dev Overload of {ECDSA-recover} that receives the `v`,\\n * `r` and `s` signature fields separately.\\n */\\n function recover(\\n bytes32 hash,\\n uint8 v,\\n bytes32 r,\\n bytes32 s\\n ) internal pure returns (address) {\\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\\n _throwError(error);\\n return recovered;\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\\n // 32 is the length in bytes of hash,\\n // enforced by the type signature above\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n32\\\", hash));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Message, created from `s`. This\\n * produces hash corresponding to the one signed with the\\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\\n * JSON-RPC method as part of EIP-191.\\n *\\n * See {recover}.\\n */\\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19Ethereum Signed Message:\\\\n\\\", Strings.toString(s.length), s));\\n }\\n\\n /**\\n * @dev Returns an Ethereum Signed Typed Data, created from a\\n * `domainSeparator` and a `structHash`. This produces hash corresponding\\n * to the one signed with the\\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\\n * JSON-RPC method as part of EIP-712.\\n *\\n * See {recover}.\\n */\\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\\n return keccak256(abi.encodePacked(\\\"\\\\x19\\\\x01\\\", domainSeparator, structHash));\\n }\\n}\\n\",\"keccak256\":\"0xe9e291de7ffe06e66503c6700b1bb84ff6e0989cbb974653628d8994e7c97f03\",\"license\":\"MIT\"},\"@openzeppelin/contracts/utils/math/SafeMath.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)\\n\\npragma solidity ^0.8.0;\\n\\n// CAUTION\\n// This version of SafeMath should only be used with Solidity 0.8 or later,\\n// because it relies on the compiler's built in overflow checks.\\n\\n/**\\n * @dev Wrappers over Solidity's arithmetic operations.\\n *\\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\\n * now has built in overflow checking.\\n */\\nlibrary SafeMath {\\n /**\\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n uint256 c = a + b;\\n if (c < a) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b > a) return (false, 0);\\n return (true, a - b);\\n }\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\\n // benefit is lost if 'b' is also tested.\\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\\n if (a == 0) return (true, 0);\\n uint256 c = a * b;\\n if (c / a != b) return (false, 0);\\n return (true, c);\\n }\\n }\\n\\n /**\\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a / b);\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\\n *\\n * _Available since v3.4._\\n */\\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\\n unchecked {\\n if (b == 0) return (false, 0);\\n return (true, a % b);\\n }\\n }\\n\\n /**\\n * @dev Returns the addition of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `+` operator.\\n *\\n * Requirements:\\n *\\n * - Addition cannot overflow.\\n */\\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a + b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting on\\n * overflow (when the result is negative).\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a - b;\\n }\\n\\n /**\\n * @dev Returns the multiplication of two unsigned integers, reverting on\\n * overflow.\\n *\\n * Counterpart to Solidity's `*` operator.\\n *\\n * Requirements:\\n *\\n * - Multiplication cannot overflow.\\n */\\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a * b;\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator.\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a / b;\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting when dividing by zero.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\\n return a % b;\\n }\\n\\n /**\\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\\n * overflow (when the result is negative).\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {trySub}.\\n *\\n * Counterpart to Solidity's `-` operator.\\n *\\n * Requirements:\\n *\\n * - Subtraction cannot overflow.\\n */\\n function sub(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b <= a, errorMessage);\\n return a - b;\\n }\\n }\\n\\n /**\\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\\n * division by zero. The result is rounded towards zero.\\n *\\n * Counterpart to Solidity's `/` operator. Note: this function uses a\\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\\n * uses an invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function div(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a / b;\\n }\\n }\\n\\n /**\\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\\n * reverting with custom message when dividing by zero.\\n *\\n * CAUTION: This function is deprecated because it requires allocating memory for the error\\n * message unnecessarily. For custom revert reasons use {tryMod}.\\n *\\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\\n * opcode (which leaves remaining gas untouched) while Solidity uses an\\n * invalid opcode to revert (consuming all remaining gas).\\n *\\n * Requirements:\\n *\\n * - The divisor cannot be zero.\\n */\\n function mod(\\n uint256 a,\\n uint256 b,\\n string memory errorMessage\\n ) internal pure returns (uint256) {\\n unchecked {\\n require(b > 0, errorMessage);\\n return a % b;\\n }\\n }\\n}\\n\",\"keccak256\":\"0xa2f576be637946f767aa56601c26d717f48a0aff44f82e46f13807eea1009a21\",\"license\":\"MIT\"},\"contracts/IController.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./zeppelin/Pausable.sol\\\";\\n\\nabstract contract IController is Pausable {\\n event SetContractInfo(bytes32 id, address contractAddress, bytes20 gitCommitHash);\\n\\n function setContractInfo(\\n bytes32 _id,\\n address _contractAddress,\\n bytes20 _gitCommitHash\\n ) external virtual;\\n\\n function updateController(bytes32 _id, address _controller) external virtual;\\n\\n function getContract(bytes32 _id) public view virtual returns (address);\\n}\\n\",\"keccak256\":\"0x34ea30a2b44d0cbec58fc1d703476ff0085b0fdadab0cd65c35c00b8867f7546\",\"license\":\"MIT\"},\"contracts/IManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\ninterface IManager {\\n event SetController(address controller);\\n event ParameterUpdate(string param);\\n\\n function setController(address _controller) external;\\n}\\n\",\"keccak256\":\"0xc179e4cecc593741514237d5194b4aaac6b829789629fa19ed04f572a8530481\",\"license\":\"MIT\"},\"contracts/Manager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./IManager.sol\\\";\\nimport \\\"./IController.sol\\\";\\n\\ncontract Manager is IManager {\\n // Controller that contract is registered with\\n IController public controller;\\n\\n // Check if sender is controller\\n modifier onlyController() {\\n _onlyController();\\n _;\\n }\\n\\n // Check if sender is controller owner\\n modifier onlyControllerOwner() {\\n _onlyControllerOwner();\\n _;\\n }\\n\\n // Check if controller is not paused\\n modifier whenSystemNotPaused() {\\n _whenSystemNotPaused();\\n _;\\n }\\n\\n // Check if controller is paused\\n modifier whenSystemPaused() {\\n _whenSystemPaused();\\n _;\\n }\\n\\n constructor(address _controller) {\\n controller = IController(_controller);\\n }\\n\\n /**\\n * @notice Set controller. Only callable by current controller\\n * @param _controller Controller contract address\\n */\\n function setController(address _controller) external onlyController {\\n controller = IController(_controller);\\n\\n emit SetController(_controller);\\n }\\n\\n function _onlyController() private view {\\n require(msg.sender == address(controller), \\\"caller must be Controller\\\");\\n }\\n\\n function _onlyControllerOwner() private view {\\n require(msg.sender == controller.owner(), \\\"caller must be Controller owner\\\");\\n }\\n\\n function _whenSystemNotPaused() private view {\\n require(!controller.paused(), \\\"system is paused\\\");\\n }\\n\\n function _whenSystemPaused() private view {\\n require(controller.paused(), \\\"system is not paused\\\");\\n }\\n}\\n\",\"keccak256\":\"0xc415e3f42da9f82ddd5953031f3f26aed824368fcc34d3b8a17015bfe80dc109\",\"license\":\"MIT\"},\"contracts/ManagerProxyTarget.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./Manager.sol\\\";\\n\\n/**\\n * @title ManagerProxyTarget\\n * @notice The base contract that target contracts used by a proxy contract should inherit from\\n * @dev Both the target contract and the proxy contract (implemented as ManagerProxy) MUST inherit from ManagerProxyTarget in order to guarantee\\n that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can\\n potentially break the delegate proxy upgradeability mechanism\\n */\\nabstract contract ManagerProxyTarget is Manager {\\n // Used to look up target contract address in controller's registry\\n bytes32 public targetContractId;\\n}\\n\",\"keccak256\":\"0x920bcc2def240e06272dc06cbcb9f12976f1698cd4f1020c165af25ee837e553\",\"license\":\"MIT\"},\"contracts/bonding/IBondingManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n/**\\n * @title Interface for BondingManager\\n * TODO: switch to interface type\\n */\\ninterface IBondingManager {\\n event TranscoderUpdate(address indexed transcoder, uint256 rewardCut, uint256 feeShare);\\n event TranscoderActivated(address indexed transcoder, uint256 activationRound);\\n event TranscoderDeactivated(address indexed transcoder, uint256 deactivationRound);\\n event TranscoderSlashed(address indexed transcoder, address finder, uint256 penalty, uint256 finderReward);\\n event Reward(address indexed transcoder, uint256 amount);\\n event Bond(\\n address indexed newDelegate,\\n address indexed oldDelegate,\\n address indexed delegator,\\n uint256 additionalAmount,\\n uint256 bondedAmount\\n );\\n event Unbond(\\n address indexed delegate,\\n address indexed delegator,\\n uint256 unbondingLockId,\\n uint256 amount,\\n uint256 withdrawRound\\n );\\n event Rebond(address indexed delegate, address indexed delegator, uint256 unbondingLockId, uint256 amount);\\n event TransferBond(\\n address indexed oldDelegator,\\n address indexed newDelegator,\\n uint256 oldUnbondingLockId,\\n uint256 newUnbondingLockId,\\n uint256 amount\\n );\\n event WithdrawStake(address indexed delegator, uint256 unbondingLockId, uint256 amount, uint256 withdrawRound);\\n event WithdrawFees(address indexed delegator, address recipient, uint256 amount);\\n event EarningsClaimed(\\n address indexed delegate,\\n address indexed delegator,\\n uint256 rewards,\\n uint256 fees,\\n uint256 startRound,\\n uint256 endRound\\n );\\n\\n // Deprecated events\\n // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding\\n // to these deprecated events.\\n // event Bond(address indexed delegate, address indexed delegator);\\n // event Unbond(address indexed delegate, address indexed delegator);\\n // event WithdrawStake(address indexed delegator);\\n // event TranscoderUpdate(address indexed transcoder, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment, bool registered);\\n // event TranscoderEvicted(address indexed transcoder);\\n // event TranscoderResigned(address indexed transcoder);\\n\\n // External functions\\n function updateTranscoderWithFees(\\n address _transcoder,\\n uint256 _fees,\\n uint256 _round\\n ) external;\\n\\n function slashTranscoder(\\n address _transcoder,\\n address _finder,\\n uint256 _slashAmount,\\n uint256 _finderFee\\n ) external;\\n\\n function setCurrentRoundTotalActiveStake() external;\\n\\n // Public functions\\n function getTranscoderPoolSize() external view returns (uint256);\\n\\n function transcoderTotalStake(address _transcoder) external view returns (uint256);\\n\\n function isActiveTranscoder(address _transcoder) external view returns (bool);\\n\\n function getTotalBonded() external view returns (uint256);\\n}\\n\",\"keccak256\":\"0x6406378868b556ca91b1ab6cccd036695c8984d30a225f75a5979cb9aa7c1df2\",\"license\":\"MIT\"},\"contracts/pm/TicketBroker.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./mixins/MixinContractRegistry.sol\\\";\\nimport \\\"./mixins/MixinReserve.sol\\\";\\nimport \\\"./mixins/MixinTicketBrokerCore.sol\\\";\\nimport \\\"./mixins/MixinTicketProcessor.sol\\\";\\nimport \\\"./mixins/MixinWrappers.sol\\\";\\n\\ncontract TicketBroker is\\n MixinContractRegistry,\\n MixinReserve,\\n MixinTicketBrokerCore,\\n MixinTicketProcessor,\\n MixinWrappers\\n{\\n /**\\n * @notice TicketBroker constructor. Only invokes constructor of base Manager contract with provided Controller address\\n * @dev This constructor will not initialize any state variables besides `controller`. The following setter functions\\n * should be used to initialize state variables post-deployment:\\n * - setUnlockPeriod()\\n * - setTicketValidityPeriod()\\n * @param _controller Address of Controller that this contract will be registered with\\n */\\n constructor(address _controller)\\n MixinContractRegistry(_controller)\\n MixinReserve()\\n MixinTicketBrokerCore()\\n MixinTicketProcessor()\\n {}\\n\\n /**\\n * @notice Sets unlockPeriod value. Only callable by the Controller owner\\n * @param _unlockPeriod Value for unlockPeriod\\n */\\n function setUnlockPeriod(uint256 _unlockPeriod) external onlyControllerOwner {\\n unlockPeriod = _unlockPeriod;\\n\\n emit ParameterUpdate(\\\"unlockPeriod\\\");\\n }\\n\\n /**\\n * @notice Sets ticketValidityPeriod value. Only callable by the Controller owner\\n * @param _ticketValidityPeriod Value for ticketValidityPeriod\\n */\\n function setTicketValidityPeriod(uint256 _ticketValidityPeriod) external onlyControllerOwner {\\n require(_ticketValidityPeriod > 0, \\\"ticketValidityPeriod must be greater than 0\\\");\\n\\n ticketValidityPeriod = _ticketValidityPeriod;\\n\\n emit ParameterUpdate(\\\"ticketValidityPeriod\\\");\\n }\\n}\\n\",\"keccak256\":\"0x3e1b4458d61a3c20e23707bde667f936af006668f1ec4a69b2322ff7e79336e7\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinContractRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"../../ManagerProxyTarget.sol\\\";\\nimport \\\"./interfaces/MContractRegistry.sol\\\";\\n\\nabstract contract MixinContractRegistry is MContractRegistry, ManagerProxyTarget {\\n /**\\n * @dev Checks if the current round has been initialized\\n */\\n modifier currentRoundInitialized() override {\\n require(roundsManager().currentRoundInitialized(), \\\"current round is not initialized\\\");\\n _;\\n }\\n\\n constructor(address _controller) Manager(_controller) {}\\n\\n /**\\n * @dev Returns an instance of the IBondingManager interface\\n */\\n function bondingManager() internal view override returns (IBondingManager) {\\n return IBondingManager(controller.getContract(keccak256(\\\"BondingManager\\\")));\\n }\\n\\n /**\\n * @dev Returns an instance of the IMinter interface\\n */\\n function minter() internal view override returns (IMinter) {\\n return IMinter(controller.getContract(keccak256(\\\"Minter\\\")));\\n }\\n\\n /**\\n * @dev Returns an instance of the IRoundsManager interface\\n */\\n function roundsManager() internal view override returns (IRoundsManager) {\\n return IRoundsManager(controller.getContract(keccak256(\\\"RoundsManager\\\")));\\n }\\n}\\n\",\"keccak256\":\"0xaf3b21d532c7fdcd02606045c66646b035a257a27dea374b8c8487339778ee2a\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinReserve.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MReserve.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\nabstract contract MixinReserve is MixinContractRegistry, MReserve {\\n using SafeMath for uint256;\\n\\n struct Reserve {\\n uint256 funds; // Amount of funds in the reserve\\n mapping(uint256 => uint256) claimedForRound; // Mapping of round => total amount claimed\\n mapping(uint256 => mapping(address => uint256)) claimedByAddress; // Mapping of round => claimant address => amount claimed\\n }\\n\\n // Mapping of address => reserve\\n mapping(address => Reserve) internal reserves;\\n\\n /**\\n * @dev Returns info about a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return info Info about the reserve for `_reserveHolder`\\n */\\n function getReserveInfo(address _reserveHolder) public view override returns (ReserveInfo memory info) {\\n info.fundsRemaining = remainingReserve(_reserveHolder);\\n info.claimedInCurrentRound = reserves[_reserveHolder].claimedForRound[roundsManager().currentRound()];\\n }\\n\\n /**\\n * @dev Returns the amount of funds claimable by a claimant from a reserve in the current round\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @return Amount of funds claimable by `_claimant` from the reserve for `_reserveHolder` in the current round\\n */\\n function claimableReserve(address _reserveHolder, address _claimant) public view returns (uint256) {\\n Reserve storage reserve = reserves[_reserveHolder];\\n\\n uint256 currentRound = roundsManager().currentRound();\\n\\n if (!bondingManager().isActiveTranscoder(_claimant)) {\\n return 0;\\n }\\n\\n uint256 poolSize = bondingManager().getTranscoderPoolSize();\\n if (poolSize == 0) {\\n return 0;\\n }\\n\\n // Total claimable funds = remaining funds + amount claimed for the round\\n uint256 totalClaimable = reserve.funds.add(reserve.claimedForRound[currentRound]);\\n return totalClaimable.div(poolSize).sub(reserve.claimedByAddress[currentRound][_claimant]);\\n }\\n\\n /**\\n * @dev Returns the amount of funds claimed by a claimant from a reserve in the current round\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @return Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder` in the current round\\n */\\n function claimedReserve(address _reserveHolder, address _claimant) public view override returns (uint256) {\\n Reserve storage reserve = reserves[_reserveHolder];\\n uint256 currentRound = roundsManager().currentRound();\\n return reserve.claimedByAddress[currentRound][_claimant];\\n }\\n\\n /**\\n * @dev Adds funds to a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _amount Amount of funds to add to reserve\\n */\\n function addReserve(address _reserveHolder, uint256 _amount) internal override {\\n reserves[_reserveHolder].funds = reserves[_reserveHolder].funds.add(_amount);\\n\\n emit ReserveFunded(_reserveHolder, _amount);\\n }\\n\\n /**\\n * @dev Clears contract storage used for a reserve\\n * @param _reserveHolder Address of reserve holder\\n */\\n function clearReserve(address _reserveHolder) internal override {\\n // This delete operation will only clear reserve.funds and will not clear the storage for reserve.claimedForRound\\n // reserve.claimedByAddress because these fields are mappings and the Solidity `delete` keyword will not modify mappings.\\n // This *could* be a problem in the following scenario:\\n //\\n // 1) In round N, for address A, reserve.claimedForRound[N] > 0 and reserve.claimedByAddress[N][r_i] > 0 where r_i is\\n // a member of the active set in round N\\n // 2) This function is called by MixinTicketBrokerCore.withdraw() in round N\\n // 3) Address A funds its reserve again\\n //\\n // After step 3, A has reserve.funds > 0, reserve.claimedForRound[N] > 0 and reserve.claimedByAddress[N][r_i] > 0\\n // despite having funded a fresh reserve after previously withdrawing all of its funds in the same round.\\n // We prevent this scenario by disallowing reserve claims starting at an address' withdraw round in\\n // MixinTicketBrokerCore.redeemWinningTicket()\\n delete reserves[_reserveHolder];\\n }\\n\\n /**\\n * @dev Claims funds from a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @param _amount Amount of funds to claim from the reserve\\n * @return Amount of funds (<= `_amount`) claimed by `_claimant` from the reserve for `_reserveHolder`\\n */\\n function claimFromReserve(\\n address _reserveHolder,\\n address _claimant,\\n uint256 _amount\\n ) internal override returns (uint256) {\\n uint256 claimableFunds = claimableReserve(_reserveHolder, _claimant);\\n // If the given amount > claimableFunds then claim claimableFunds\\n // If the given amount <= claimableFunds then claim the given amount\\n uint256 claimAmount = _amount > claimableFunds ? claimableFunds : _amount;\\n\\n if (claimAmount > 0) {\\n uint256 currentRound = roundsManager().currentRound();\\n Reserve storage reserve = reserves[_reserveHolder];\\n // Increase total amount claimed for the round\\n reserve.claimedForRound[currentRound] = reserve.claimedForRound[currentRound].add(claimAmount);\\n // Increase amount claimed by claimant for the round\\n reserve.claimedByAddress[currentRound][_claimant] = reserve.claimedByAddress[currentRound][_claimant].add(\\n claimAmount\\n );\\n // Decrease remaining reserve\\n reserve.funds = reserve.funds.sub(claimAmount);\\n\\n emit ReserveClaimed(_reserveHolder, _claimant, claimAmount);\\n }\\n\\n return claimAmount;\\n }\\n\\n /**\\n * @dev Returns the amount of funds remaining in a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return Amount of funds remaining in the reserve for `_reserveHolder`\\n */\\n function remainingReserve(address _reserveHolder) internal view override returns (uint256) {\\n return reserves[_reserveHolder].funds;\\n }\\n}\\n\",\"keccak256\":\"0x1b1d7694fe606eb1c0ba2e203889b416804bd1547ee63ed572c1c628f219c775\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinTicketBrokerCore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MReserve.sol\\\";\\nimport \\\"./interfaces/MTicketProcessor.sol\\\";\\nimport \\\"./interfaces/MTicketBrokerCore.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\nabstract contract MixinTicketBrokerCore is MixinContractRegistry, MReserve, MTicketProcessor, MTicketBrokerCore {\\n using SafeMath for uint256;\\n\\n struct Sender {\\n uint256 deposit; // Amount of funds deposited\\n uint256 withdrawRound; // Round that sender can withdraw deposit & reserve\\n }\\n\\n // Mapping of address => Sender\\n mapping(address => Sender) internal senders;\\n\\n // Number of rounds before a sender can withdraw after requesting an unlock\\n uint256 public unlockPeriod;\\n\\n // Mapping of ticket hashes => boolean indicating if ticket was redeemed\\n mapping(bytes32 => bool) public usedTickets;\\n\\n // Checks if msg.value is equal to the given deposit and reserve amounts\\n modifier checkDepositReserveETHValueSplit(uint256 _depositAmount, uint256 _reserveAmount) {\\n require(\\n msg.value == _depositAmount.add(_reserveAmount),\\n \\\"msg.value does not equal sum of deposit amount and reserve amount\\\"\\n );\\n\\n _;\\n }\\n\\n // Process deposit funding\\n modifier processDeposit(address _sender, uint256 _amount) {\\n Sender storage sender = senders[_sender];\\n sender.deposit = sender.deposit.add(_amount);\\n // If the sender themselves funds their deposit, cancel the unlock\\n if (msg.sender == _sender && _isUnlockInProgress(sender)) {\\n _cancelUnlock(sender, _sender);\\n }\\n\\n _;\\n\\n emit DepositFunded(_sender, _amount);\\n }\\n\\n // Process reserve funding\\n modifier processReserve(address _sender, uint256 _amount) {\\n Sender storage sender = senders[_sender];\\n addReserve(_sender, _amount);\\n // If the sender themselves funds their reserve, cancel the unlock\\n if (msg.sender == _sender && _isUnlockInProgress(sender)) {\\n _cancelUnlock(sender, _sender);\\n }\\n\\n _;\\n }\\n\\n /**\\n * @notice Adds ETH to the caller's deposit\\n */\\n function fundDeposit() external payable whenSystemNotPaused processDeposit(msg.sender, msg.value) {\\n processFunding(msg.value);\\n }\\n\\n /**\\n * @notice Adds ETH to the caller's reserve\\n */\\n function fundReserve() external payable whenSystemNotPaused processReserve(msg.sender, msg.value) {\\n processFunding(msg.value);\\n }\\n\\n /**\\n * @notice Adds ETH to the caller's deposit and reserve\\n * @param _depositAmount Amount of ETH to add to the caller's deposit\\n * @param _reserveAmount Amount of ETH to add to the caller's reserve\\n */\\n function fundDepositAndReserve(uint256 _depositAmount, uint256 _reserveAmount) external payable {\\n fundDepositAndReserveFor(msg.sender, _depositAmount, _reserveAmount);\\n }\\n\\n /**\\n * @notice Adds ETH to the address' deposit and reserve\\n * @param _depositAmount Amount of ETH to add to the address' deposit\\n * @param _reserveAmount Amount of ETH to add to the address' reserve\\n */\\n function fundDepositAndReserveFor(\\n address _addr,\\n uint256 _depositAmount,\\n uint256 _reserveAmount\\n )\\n public\\n payable\\n whenSystemNotPaused\\n checkDepositReserveETHValueSplit(_depositAmount, _reserveAmount)\\n processDeposit(_addr, _depositAmount)\\n processReserve(_addr, _reserveAmount)\\n {\\n processFunding(msg.value);\\n }\\n\\n /**\\n * @notice Redeems a winning ticket that has been signed by a sender and reveals the\\n recipient recipientRand that corresponds to the recipientRandHash included in the ticket\\n * @param _ticket Winning ticket to be redeemed in order to claim payment\\n * @param _sig Sender's signature over the hash of `_ticket`\\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\\n */\\n function redeemWinningTicket(\\n Ticket memory _ticket,\\n bytes memory _sig,\\n uint256 _recipientRand\\n ) public whenSystemNotPaused currentRoundInitialized {\\n bytes32 ticketHash = getTicketHash(_ticket);\\n\\n // Require a valid winning ticket for redemption\\n requireValidWinningTicket(_ticket, ticketHash, _sig, _recipientRand);\\n\\n Sender storage sender = senders[_ticket.sender];\\n\\n // Require sender to be locked\\n require(isLocked(sender), \\\"sender is unlocked\\\");\\n // Require either a non-zero deposit or non-zero reserve for the sender\\n require(sender.deposit > 0 || remainingReserve(_ticket.sender) > 0, \\\"sender deposit and reserve are zero\\\");\\n\\n // Mark ticket as used to prevent replay attacks involving redeeming\\n // the same winning ticket multiple times\\n usedTickets[ticketHash] = true;\\n\\n uint256 amountToTransfer;\\n\\n if (_ticket.faceValue > sender.deposit) {\\n // If ticket face value > sender's deposit then claim from\\n // the sender's reserve\\n\\n amountToTransfer = sender.deposit.add(\\n claimFromReserve(_ticket.sender, _ticket.recipient, _ticket.faceValue.sub(sender.deposit))\\n );\\n\\n sender.deposit = 0;\\n } else {\\n // If ticket face value <= sender's deposit then only deduct\\n // from sender's deposit\\n\\n amountToTransfer = _ticket.faceValue;\\n sender.deposit = sender.deposit.sub(_ticket.faceValue);\\n }\\n\\n if (amountToTransfer > 0) {\\n winningTicketTransfer(_ticket.recipient, amountToTransfer, _ticket.auxData);\\n\\n emit WinningTicketTransfer(_ticket.sender, _ticket.recipient, amountToTransfer);\\n }\\n\\n emit WinningTicketRedeemed(\\n _ticket.sender,\\n _ticket.recipient,\\n _ticket.faceValue,\\n _ticket.winProb,\\n _ticket.senderNonce,\\n _recipientRand,\\n _ticket.auxData\\n );\\n }\\n\\n /**\\n * @notice Initiates the unlock period for the caller\\n */\\n function unlock() public whenSystemNotPaused {\\n Sender storage sender = senders[msg.sender];\\n\\n require(sender.deposit > 0 || remainingReserve(msg.sender) > 0, \\\"sender deposit and reserve are zero\\\");\\n require(!_isUnlockInProgress(sender), \\\"unlock already initiated\\\");\\n\\n uint256 currentRound = roundsManager().currentRound();\\n sender.withdrawRound = currentRound.add(unlockPeriod);\\n\\n emit Unlock(msg.sender, currentRound, sender.withdrawRound);\\n }\\n\\n /**\\n * @notice Cancels the unlock period for the caller\\n */\\n function cancelUnlock() public whenSystemNotPaused {\\n Sender storage sender = senders[msg.sender];\\n\\n _cancelUnlock(sender, msg.sender);\\n }\\n\\n /**\\n * @notice Withdraws all ETH from the caller's deposit and reserve\\n */\\n function withdraw() public whenSystemNotPaused {\\n Sender storage sender = senders[msg.sender];\\n\\n uint256 deposit = sender.deposit;\\n uint256 reserve = remainingReserve(msg.sender);\\n\\n require(deposit > 0 || reserve > 0, \\\"sender deposit and reserve are zero\\\");\\n require(_isUnlockInProgress(sender), \\\"no unlock request in progress\\\");\\n require(!isLocked(sender), \\\"account is locked\\\");\\n\\n sender.deposit = 0;\\n clearReserve(msg.sender);\\n\\n withdrawTransfer(payable(msg.sender), deposit.add(reserve));\\n\\n emit Withdrawal(msg.sender, deposit, reserve);\\n }\\n\\n /**\\n * @notice Returns whether a sender is currently in the unlock period\\n * @param _sender Address of sender\\n * @return Boolean indicating whether `_sender` has an unlock in progress\\n */\\n function isUnlockInProgress(address _sender) public view returns (bool) {\\n Sender memory sender = senders[_sender];\\n return _isUnlockInProgress(sender);\\n }\\n\\n /**\\n * @notice Returns info about a sender\\n * @param _sender Address of sender\\n * @return sender Info about the sender for `_sender`\\n * @return reserve Info about the reserve for `_sender`\\n */\\n function getSenderInfo(address _sender) public view returns (Sender memory sender, ReserveInfo memory reserve) {\\n sender = senders[_sender];\\n reserve = getReserveInfo(_sender);\\n }\\n\\n /**\\n * @dev Returns the hash of a ticket\\n * @param _ticket Ticket to be hashed\\n * @return keccak256 hash of `_ticket`\\n */\\n function getTicketHash(Ticket memory _ticket) public pure returns (bytes32) {\\n return\\n keccak256(\\n abi.encodePacked(\\n _ticket.recipient,\\n _ticket.sender,\\n _ticket.faceValue,\\n _ticket.winProb,\\n _ticket.senderNonce,\\n _ticket.recipientRandHash,\\n _ticket.auxData\\n )\\n );\\n }\\n\\n /**\\n * @dev Helper to cancel an unlock\\n * @param _sender Sender that is cancelling an unlock\\n * @param _senderAddress Address of sender\\n */\\n function _cancelUnlock(Sender storage _sender, address _senderAddress) internal {\\n require(_isUnlockInProgress(_sender), \\\"no unlock request in progress\\\");\\n\\n _sender.withdrawRound = 0;\\n\\n emit UnlockCancelled(_senderAddress);\\n }\\n\\n /**\\n * @dev Validates a winning ticket, succeeds or reverts\\n * @param _ticket Winning ticket to be validated\\n * @param _ticketHash Hash of `_ticket`\\n * @param _sig Sender's signature over `_ticketHash`\\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\\n */\\n function requireValidWinningTicket(\\n Ticket memory _ticket,\\n bytes32 _ticketHash,\\n bytes memory _sig,\\n uint256 _recipientRand\\n ) internal view {\\n require(_ticket.recipient != address(0), \\\"ticket recipient is null address\\\");\\n require(_ticket.sender != address(0), \\\"ticket sender is null address\\\");\\n\\n requireValidTicketAuxData(_ticket.auxData);\\n\\n require(\\n keccak256(abi.encodePacked(_recipientRand)) == _ticket.recipientRandHash,\\n \\\"recipientRand does not match recipientRandHash\\\"\\n );\\n\\n require(!usedTickets[_ticketHash], \\\"ticket is used\\\");\\n\\n require(isValidTicketSig(_ticket.sender, _sig, _ticketHash), \\\"invalid signature over ticket hash\\\");\\n\\n require(isWinningTicket(_sig, _recipientRand, _ticket.winProb), \\\"ticket did not win\\\");\\n }\\n\\n /**\\n * @dev Returns whether a sender is locked\\n * @param _sender Sender to check for locked status\\n * @return Boolean indicating whether sender is currently locked\\n */\\n function isLocked(Sender memory _sender) internal view returns (bool) {\\n return _sender.withdrawRound == 0 || roundsManager().currentRound() < _sender.withdrawRound;\\n }\\n\\n /**\\n * @dev Returns whether a signature over a ticket hash is valid for a sender\\n * @param _sender Address of sender\\n * @param _sig Signature over `_ticketHash`\\n * @param _ticketHash Hash of the ticket\\n * @return Boolean indicating whether `_sig` is valid signature over `_ticketHash` for `_sender`\\n */\\n function isValidTicketSig(\\n address _sender,\\n bytes memory _sig,\\n bytes32 _ticketHash\\n ) internal pure returns (bool) {\\n require(_sig.length == 65, \\\"INVALID_SIGNATURE_LENGTH\\\");\\n address signer = ECDSA.recover(ECDSA.toEthSignedMessageHash(_ticketHash), _sig);\\n return signer != address(0) && _sender == signer;\\n }\\n\\n /**\\n * @dev Returns whether a ticket won\\n * @param _sig Sender's signature over the ticket\\n * @param _recipientRand The preimage for the recipientRandHash included in the ticket\\n * @param _winProb The winning probability of the ticket\\n * @return Boolean indicating whether the ticket won\\n */\\n function isWinningTicket(\\n bytes memory _sig,\\n uint256 _recipientRand,\\n uint256 _winProb\\n ) internal pure returns (bool) {\\n return uint256(keccak256(abi.encodePacked(_sig, _recipientRand))) < _winProb;\\n }\\n\\n /**\\n * @dev Helper to check if a sender is currently in the unlock period\\n * @param _sender Sender to check for an unlock\\n * @return Boolean indicating whether the sender is currently in the unlock period\\n */\\n function _isUnlockInProgress(Sender memory _sender) internal pure returns (bool) {\\n return _sender.withdrawRound > 0;\\n }\\n}\\n\",\"keccak256\":\"0x7a9f5cb50cef3f9e6d099ce77eb134c6bca03e052bb903afe0f48d34fee790e5\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinTicketProcessor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MTicketProcessor.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\nimport \\\"@openzeppelin/contracts/utils/math/SafeMath.sol\\\";\\n\\nabstract contract MixinTicketProcessor is MixinContractRegistry, MTicketProcessor {\\n using SafeMath for uint256;\\n\\n // Number of rounds that a ticket is valid for starting from\\n // its creationRound\\n uint256 public ticketValidityPeriod;\\n\\n /**\\n * @dev Process sent funds.\\n * @param _amount Amount of funds sent\\n */\\n function processFunding(uint256 _amount) internal override {\\n // Send funds to Minter\\n minter().depositETH{ value: _amount }();\\n }\\n\\n /**\\n * @dev Transfer withdrawal funds for a ticket sender\\n * @param _amount Amount of withdrawal funds\\n */\\n function withdrawTransfer(address payable _sender, uint256 _amount) internal override {\\n // Ask Minter to send withdrawal funds to the ticket sender\\n minter().trustedWithdrawETH(_sender, _amount);\\n }\\n\\n /**\\n * @dev Transfer funds for a recipient's winning ticket\\n * @param _recipient Address of recipient\\n * @param _amount Amount of funds for the winning ticket\\n * @param _auxData Auxilary data for the winning ticket\\n */\\n function winningTicketTransfer(\\n address _recipient,\\n uint256 _amount,\\n bytes memory _auxData\\n ) internal override {\\n (uint256 creationRound, ) = getCreationRoundAndBlockHash(_auxData);\\n\\n // Ask BondingManager to update fee pool for recipient with\\n // winning ticket funds\\n bondingManager().updateTranscoderWithFees(_recipient, _amount, creationRound);\\n }\\n\\n /**\\n * @dev Validates a ticket's auxilary data (succeeds or reverts)\\n * @param _auxData Auxilary data inclueded in a ticket\\n */\\n function requireValidTicketAuxData(bytes memory _auxData) internal view override {\\n (uint256 creationRound, bytes32 creationRoundBlockHash) = getCreationRoundAndBlockHash(_auxData);\\n bytes32 blockHash = roundsManager().blockHashForRound(creationRound);\\n\\n require(blockHash != bytes32(0), \\\"ticket creationRound does not have a block hash\\\");\\n require(creationRoundBlockHash == blockHash, \\\"ticket creationRoundBlockHash invalid for creationRound\\\");\\n\\n uint256 currRound = roundsManager().currentRound();\\n\\n require(creationRound.add(ticketValidityPeriod) > currRound, \\\"ticket is expired\\\");\\n }\\n\\n /**\\n * @dev Returns a ticket's creationRound and creationRoundBlockHash parsed from ticket auxilary data\\n * @param _auxData Auxilary data for a ticket\\n * @return creationRound and creationRoundBlockHash parsed from `_auxData`\\n */\\n function getCreationRoundAndBlockHash(bytes memory _auxData)\\n internal\\n pure\\n returns (uint256 creationRound, bytes32 creationRoundBlockHash)\\n {\\n require(_auxData.length == 64, \\\"invalid length for ticket auxData: must be 64 bytes\\\");\\n\\n // _auxData format:\\n // Bytes [0:31] = creationRound\\n // Bytes [32:63] = creationRoundBlockHash\\n assembly {\\n creationRound := mload(add(_auxData, 32))\\n creationRoundBlockHash := mload(add(_auxData, 64))\\n }\\n }\\n}\\n\",\"keccak256\":\"0x38a3a855f30ebce7af979a0876f11943b6064bc652908c47572f93a202989c41\",\"license\":\"MIT\"},\"contracts/pm/mixins/MixinWrappers.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./interfaces/MTicketBrokerCore.sol\\\";\\nimport \\\"./MixinContractRegistry.sol\\\";\\n\\nabstract contract MixinWrappers is MixinContractRegistry, MTicketBrokerCore {\\n /**\\n * @notice Redeems multiple winning tickets. The function will redeem all of the provided tickets and handle any failures gracefully without reverting the entire function\\n * @param _tickets Array of winning tickets to be redeemed in order to claim payment\\n * @param _sigs Array of sender signatures over the hash of tickets (`_sigs[i]` corresponds to `_tickets[i]`)\\n * @param _recipientRands Array of preimages for the recipientRandHash included in each ticket (`_recipientRands[i]` corresponds to `_tickets[i]`)\\n */\\n function batchRedeemWinningTickets(\\n Ticket[] memory _tickets,\\n bytes[] memory _sigs,\\n uint256[] memory _recipientRands\\n ) public whenSystemNotPaused currentRoundInitialized {\\n for (uint256 i = 0; i < _tickets.length; i++) {\\n redeemWinningTicketNoRevert(_tickets[i], _sigs[i], _recipientRands[i]);\\n }\\n }\\n\\n /**\\n * @dev Redeems a winning ticket that has been signed by a sender and reveals the\\n recipient recipientRand that corresponds to the recipientRandHash included in the ticket\\n This function wraps `redeemWinningTicket()` and returns false if the underlying call reverts\\n * @param _ticket Winning ticket to be redeemed in order to claim payment\\n * @param _sig Sender's signature over the hash of `_ticket`\\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\\n * @return success Boolean indicating whether the underlying `redeemWinningTicket()` call succeeded\\n */\\n function redeemWinningTicketNoRevert(\\n Ticket memory _ticket,\\n bytes memory _sig,\\n uint256 _recipientRand\\n ) internal returns (bool success) {\\n // ABI encode calldata for `redeemWinningTicket()`\\n // A tuple type is used to represent the Ticket struct in the function signature\\n bytes memory redeemWinningTicketCalldata = abi.encodeWithSignature(\\n \\\"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\\\",\\n _ticket,\\n _sig,\\n _recipientRand\\n );\\n\\n // Call `redeemWinningTicket()`\\n // solium-disable-next-line\\n (success, ) = address(this).call(redeemWinningTicketCalldata);\\n }\\n}\\n\",\"keccak256\":\"0xf0831bba68089167c5cc9ed9a04564d0a68e1454bd65cf91083103197d047b1d\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MContractRegistry.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"../../../bonding/IBondingManager.sol\\\";\\nimport \\\"../../../token/IMinter.sol\\\";\\nimport \\\"../../../rounds/IRoundsManager.sol\\\";\\n\\nabstract contract MContractRegistry {\\n /**\\n * @notice Checks if the current round has been initialized\\n * @dev Executes the 'currentRoundInitialized' modifier in 'MixinContractRegistry'\\n */\\n modifier currentRoundInitialized() virtual {\\n _;\\n }\\n\\n /**\\n * @dev Returns an instance of the IBondingManager interface\\n */\\n function bondingManager() internal view virtual returns (IBondingManager);\\n\\n /**\\n * @dev Returns an instance of the IMinter interface\\n */\\n function minter() internal view virtual returns (IMinter);\\n\\n /**\\n * @dev Returns an instance of the IRoundsManager interface\\n */\\n function roundsManager() internal view virtual returns (IRoundsManager);\\n}\\n\",\"keccak256\":\"0xc58fb56b6ccfe36e5e09322ca1793a805668c84877cf6856403da51e2e35a359\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MReserve.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nabstract contract MReserve {\\n struct ReserveInfo {\\n uint256 fundsRemaining; // Funds remaining in reserve\\n uint256 claimedInCurrentRound; // Funds claimed from reserve in current round\\n }\\n\\n // Emitted when funds are added to a reserve\\n event ReserveFunded(address indexed reserveHolder, uint256 amount);\\n // Emitted when funds are claimed from a reserve\\n event ReserveClaimed(address indexed reserveHolder, address claimant, uint256 amount);\\n\\n /**\\n * @notice Returns info about a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return info Info about the reserve for `_reserveHolder`\\n */\\n function getReserveInfo(address _reserveHolder) public view virtual returns (ReserveInfo memory info);\\n\\n /**\\n * @notice Returns the amount of funds claimed by a claimant from a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @return Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder`\\n */\\n function claimedReserve(address _reserveHolder, address _claimant) public view virtual returns (uint256);\\n\\n /**\\n * @dev Adds funds to a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _amount Amount of funds to add to reserve\\n */\\n function addReserve(address _reserveHolder, uint256 _amount) internal virtual;\\n\\n /**\\n * @dev Clears contract storage used for a reserve\\n * @param _reserveHolder Address of reserve holder\\n */\\n function clearReserve(address _reserveHolder) internal virtual;\\n\\n /**\\n * @dev Claims funds from a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @param _claimant Address of claimant\\n * @param _amount Amount of funds to claim from the reserve\\n * @return Amount of funds (<= `_amount`) claimed by `_claimant` from the reserve for `_reserveHolder`\\n */\\n function claimFromReserve(\\n address _reserveHolder,\\n address _claimant,\\n uint256 _amount\\n ) internal virtual returns (uint256);\\n\\n /**\\n * @dev Returns the amount of funds remaining in a reserve\\n * @param _reserveHolder Address of reserve holder\\n * @return Amount of funds remaining in the reserve for `_reserveHolder`\\n */\\n function remainingReserve(address _reserveHolder) internal view virtual returns (uint256);\\n}\\n\",\"keccak256\":\"0x01229dd7088e23db674d032c239d90a14e8922532a82c7d46a3e7fe5fa234827\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MTicketBrokerCore.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nabstract contract MTicketBrokerCore {\\n struct Ticket {\\n address recipient; // Address of ticket recipient\\n address sender; // Address of ticket sender\\n uint256 faceValue; // Face value of ticket paid to recipient if ticket wins\\n uint256 winProb; // Probability ticket will win represented as winProb / (2^256 - 1)\\n uint256 senderNonce; // Sender's monotonically increasing counter for each ticket\\n bytes32 recipientRandHash; // keccak256 hash commitment to recipient's random value\\n bytes auxData; // Auxilary data included in ticket used for additional validation\\n }\\n\\n // Emitted when funds are added to a sender's deposit\\n event DepositFunded(address indexed sender, uint256 amount);\\n // Emitted when a winning ticket is redeemed\\n event WinningTicketRedeemed(\\n address indexed sender,\\n address indexed recipient,\\n uint256 faceValue,\\n uint256 winProb,\\n uint256 senderNonce,\\n uint256 recipientRand,\\n bytes auxData\\n );\\n // Emitted when a funds transfer for a winning ticket redemption is executed\\n event WinningTicketTransfer(address indexed sender, address indexed recipient, uint256 amount);\\n // Emitted when a sender requests an unlock\\n event Unlock(address indexed sender, uint256 startRound, uint256 endRound);\\n // Emitted when a sender cancels an unlock\\n event UnlockCancelled(address indexed sender);\\n // Emitted when a sender withdraws its deposit & reserve\\n event Withdrawal(address indexed sender, uint256 deposit, uint256 reserve);\\n}\\n\",\"keccak256\":\"0x80c3b528a357a1895fc5e3d6a7b935db89ab1ba10a0af677d677b7a66434bc0f\",\"license\":\"MIT\"},\"contracts/pm/mixins/interfaces/MTicketProcessor.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nabstract contract MTicketProcessor {\\n /**\\n * @dev Process sent funds.\\n * @param _amount Amount of funds sent\\n */\\n function processFunding(uint256 _amount) internal virtual;\\n\\n /**\\n * @dev Transfer withdrawal funds for a ticket sender\\n * @param _amount Amount of withdrawal funds\\n */\\n function withdrawTransfer(address payable _sender, uint256 _amount) internal virtual;\\n\\n /**\\n * @dev Transfer funds for a recipient's winning ticket\\n * @param _recipient Address of recipient\\n * @param _amount Amount of funds for the winning ticket\\n * @param _auxData Auxilary data for the winning ticket\\n */\\n function winningTicketTransfer(\\n address _recipient,\\n uint256 _amount,\\n bytes memory _auxData\\n ) internal virtual;\\n\\n /**\\n * @dev Validates a ticket's auxilary data (succeeds or reverts)\\n * @param _auxData Auxilary data inclueded in a ticket\\n */\\n function requireValidTicketAuxData(bytes memory _auxData) internal view virtual;\\n}\\n\",\"keccak256\":\"0xe026045f70ec840465b6d146cd4ddc5ea8b9a8e8ee0c6288f44649dd3c4a12e9\",\"license\":\"MIT\"},\"contracts/rounds/IRoundsManager.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n/**\\n * @title RoundsManager interface\\n */\\ninterface IRoundsManager {\\n // Events\\n event NewRound(uint256 indexed round, bytes32 blockHash);\\n\\n // Deprecated events\\n // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding\\n // to these deprecated events.\\n // event NewRound(uint256 round)\\n\\n // External functions\\n function initializeRound() external;\\n\\n function lipUpgradeRound(uint256 _lip) external view returns (uint256);\\n\\n // Public functions\\n function blockNum() external view returns (uint256);\\n\\n function blockHash(uint256 _block) external view returns (bytes32);\\n\\n function blockHashForRound(uint256 _round) external view returns (bytes32);\\n\\n function currentRound() external view returns (uint256);\\n\\n function currentRoundStartBlock() external view returns (uint256);\\n\\n function currentRoundInitialized() external view returns (bool);\\n\\n function currentRoundLocked() external view returns (bool);\\n}\\n\",\"keccak256\":\"0xfc453a476bb68b874c21678a128b46ffcad0af69008e0e3e857d46499214f75f\",\"license\":\"MIT\"},\"contracts/token/IMinter.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"../IController.sol\\\";\\n\\n/**\\n * @title Minter interface\\n */\\ninterface IMinter {\\n // Events\\n event SetCurrentRewardTokens(uint256 currentMintableTokens, uint256 currentInflation);\\n\\n // External functions\\n function createReward(uint256 _fracNum, uint256 _fracDenom) external returns (uint256);\\n\\n function trustedTransferTokens(address _to, uint256 _amount) external;\\n\\n function trustedBurnTokens(uint256 _amount) external;\\n\\n function trustedWithdrawETH(address payable _to, uint256 _amount) external;\\n\\n function depositETH() external payable returns (bool);\\n\\n function setCurrentRewardTokens() external;\\n\\n function currentMintableTokens() external view returns (uint256);\\n\\n function currentMintedTokens() external view returns (uint256);\\n\\n // Public functions\\n function getController() external view returns (IController);\\n}\\n\",\"keccak256\":\"0x3fbb7a4239a8b5979fb4c45a41495e9694a9f454de82dca3cf6a14dfe71255c7\",\"license\":\"MIT\"},\"contracts/zeppelin/Ownable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\n/**\\n * @title Ownable\\n * @dev The Ownable contract has an owner address, and provides basic authorization control\\n * functions, this simplifies the implementation of \\\"user permissions\\\".\\n */\\ncontract Ownable {\\n address public owner;\\n\\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\\n\\n /**\\n * @dev The Ownable constructor sets the original `owner` of the contract to the sender\\n * account.\\n */\\n constructor() {\\n owner = msg.sender;\\n }\\n\\n /**\\n * @dev Throws if called by any account other than the owner.\\n */\\n modifier onlyOwner() {\\n require(msg.sender == owner);\\n _;\\n }\\n\\n /**\\n * @dev Allows the current owner to transfer control of the contract to a newOwner.\\n * @param newOwner The address to transfer ownership to.\\n */\\n function transferOwnership(address newOwner) public onlyOwner {\\n require(newOwner != address(0));\\n emit OwnershipTransferred(owner, newOwner);\\n owner = newOwner;\\n }\\n}\\n\",\"keccak256\":\"0x64f114689f2f161c4a4b8fc8442ab914436a33e6021bf17401eaeac73319a419\",\"license\":\"MIT\"},\"contracts/zeppelin/Pausable.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\npragma solidity 0.8.9;\\n\\nimport \\\"./Ownable.sol\\\";\\n\\n/**\\n * @title Pausable\\n * @dev Base contract which allows children to implement an emergency stop mechanism.\\n */\\ncontract Pausable is Ownable {\\n event Pause();\\n event Unpause();\\n\\n bool public paused;\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is not paused.\\n */\\n modifier whenNotPaused() {\\n require(!paused);\\n _;\\n }\\n\\n /**\\n * @dev Modifier to make a function callable only when the contract is paused.\\n */\\n modifier whenPaused() {\\n require(paused);\\n _;\\n }\\n\\n /**\\n * @dev called by the owner to pause, triggers stopped state\\n */\\n function pause() public onlyOwner whenNotPaused {\\n paused = true;\\n emit Pause();\\n }\\n\\n /**\\n * @dev called by the owner to unpause, returns to normal state\\n */\\n function unpause() public onlyOwner whenPaused {\\n paused = false;\\n emit Unpause();\\n }\\n}\\n\",\"keccak256\":\"0xe9635fcac46c22547a08f6977a8c75e7341411f1201f60bdd4c79c26e6c286ef\",\"license\":\"MIT\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b50604051620030083803806200300883398101604081905262000034916200005a565b600080546001600160a01b0319166001600160a01b03929092169190911790556200008c565b6000602082840312156200006d57600080fd5b81516001600160a01b03811681146200008557600080fd5b9392505050565b612f6c806200009c6000396000f3fe6080604052600436106101405760003560e01c806381779f38116100b6578063c2c4c2c81161006f578063c2c4c2c814610329578063c92978081461033e578063d01b808e1461035e578063e1a589da1461037e578063ec8b3cb6146103ac578063f77c4791146103cc57600080fd5b806381779f381461028b578063856a2cf8146102ab57806392eefe9b146102c1578063989f789c146102e1578063a69df4b5146102f4578063b03fa8641461030957600080fd5b8063511f407311610108578063511f4073146101f557806351720b411461020857806359a515ba1461021e5780635b6333eb1461024e5780636caa736b1461027b5780636f9c3c8f1461028357600080fd5b8063121cdcc21461014557806320d3a0b41461017a5780633ccfd60b1461019e5780633d0ddf84146101b55780634ac826da146101d5575b600080fd5b34801561015157600080fd5b50610165610160366004612718565b610404565b60405190151581526020015b60405180910390f35b34801561018657600080fd5b5061019060045481565b604051908152602001610171565b3480156101aa57600080fd5b506101b3610440565b005b3480156101c157600080fd5b506101b36101d0366004612735565b6105c6565b3480156101e157600080fd5b506101906101f036600461274e565b61062d565b6101b3610203366004612787565b6106ef565b34801561021457600080fd5b5061019060015481565b34801561022a57600080fd5b50610165610239366004612735565b60056020526000908152604090205460ff1681565b34801561025a57600080fd5b5061026e610269366004612718565b6106fe565b60405161017191906127a9565b6101b36107cc565b6101b3610878565b34801561029757600080fd5b506101906102a636600461274e565b6108e9565b3480156102b757600080fd5b5061019060065481565b3480156102cd57600080fd5b506101b36102dc366004612718565b610afe565b6101b36102ef3660046127c0565b610b54565b34801561030057600080fd5b506101b3610d0f565b34801561031557600080fd5b50610190610324366004612967565b610ea3565b34801561033557600080fd5b506101b3610ef5565b34801561034a57600080fd5b506101b3610359366004612735565b610f1b565b34801561036a57600080fd5b506101b3610379366004612ab3565b610fe3565b34801561038a57600080fd5b5061039e610399366004612718565b61112a565b604051610171929190612bab565b3480156103b857600080fd5b506101b36103c7366004612bd1565b61118b565b3480156103d857600080fd5b506000546103ec906001600160a01b031681565b6040516001600160a01b039091168152602001610171565b6001600160a01b0381166000908152600360209081526040808320815180830190925280548252600101549181018290529015155b9392505050565b61044861149d565b33600090815260036020908152604080832080546002909352922054811515806104725750600081115b6104975760405162461bcd60e51b815260040161048e90612c3e565b60405180910390fd5b6040805180820190915283548152600184015460209091018190526104fe5760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b60408051808201909152835481526001840154602082015261051f90611563565b156105605760405162461bcd60e51b81526020600482015260116024820152701858d8dbdd5b9d081a5cc81b1bd8dad959607a1b604482015260640161048e565b6000808455338152600260205260408120556105853361058084846115f7565b611603565b604080518381526020810183905233917fdf273cb619d95419a9cd0ec88123a0538c85064229baa6363788f743fff90deb91015b60405180910390a2505050565b6105ce611673565b60048190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252600c908201526b1d5b9b1bd8dad4195c9a5bd960a21b604082015260600190565b60405180910390a150565b6001600160a01b03821660009081526002602052604081208161064e611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561068657600080fd5b505afa15801561069a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106be9190612c81565b60009081526002909201602090815260408084206001600160a01b0387168552909152909120549150505b92915050565b6106fa338383610b54565b5050565b604080518082018252600080825260208083018290526001600160a01b038516808352600280835294832080548552908352939052909160010190610741611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561077957600080fd5b505afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b19190612c81565b81526020808201929092526040016000205490820152919050565b6107d461149d565b33600081815260036020526040902080543491906107f290836115f7565b8155336001600160a01b038416148015610825575060408051808201909152815481526001820154602090910181905215155b156108345761083481846117f9565b61083d3461189e565b826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f836040516105b991815260200190565b61088061149d565b336000818152600360205260409020349061089b8383611919565b336001600160a01b0384161480156108cc575060408051808201909152815481526001820154602090910181905215155b156108db576108db81846117f9565b6108e43461189e565b505050565b6001600160a01b03821660009081526002602052604081208161090a611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561094257600080fd5b505afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190612c81565b905061098461198b565b60405163022008dd60e21b81526001600160a01b038681166004830152919091169063088023749060240160206040518083038186803b1580156109c757600080fd5b505afa1580156109db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ff9190612c9a565b610a0e576000925050506106e9565b6000610a1861198b565b6001600160a01b0316632a4e0d556040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5057600080fd5b505afa158015610a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a889190612c81565b905080610a9b57600093505050506106e9565b60008281526001840160205260408120548454610ab7916115f7565b600084815260028601602090815260408083206001600160a01b038b168452909152902054909150610af390610aed83856119dc565b906119e8565b979650505050505050565b610b066119f4565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7090602001610622565b610b5c61149d565b8181610b6882826115f7565b3414610be65760405162461bcd60e51b815260206004820152604160248201527f6d73672e76616c756520646f6573206e6f7420657175616c2073756d206f662060448201527f6465706f73697420616d6f756e7420616e64207265736572766520616d6f756e6064820152601d60fa1b608482015260a40161048e565b6001600160a01b0385166000908152600360205260409020805486918691610c0e90836115f7565b8155336001600160a01b038416148015610c41575060408051808201909152815481526001820154602090910181905215155b15610c5057610c5081846117f9565b6001600160a01b038816600090815260036020526040902088908790610c768383611919565b336001600160a01b038416148015610ca7575060408051808201909152815481526001820154602090910181905215155b15610cb657610cb681846117f9565b610cbf3461189e565b505050826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f83604051610cfd91815260200190565b60405180910390a25050505050505050565b610d1761149d565b3360009081526003602052604090208054151580610d42575033600090815260026020526040812054115b610d5e5760405162461bcd60e51b815260040161048e90612c3e565b60408051808201909152815481526001820154602090910181905215610dc65760405162461bcd60e51b815260206004820152601860248201527f756e6c6f636b20616c726561647920696e697469617465640000000000000000604482015260640161048e565b6000610dd0611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0857600080fd5b505afa158015610e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e409190612c81565b9050610e57600454826115f790919063ffffffff16565b6001830181905560405133917ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c200491610e9791858252602082015260400190565b60405180910390a25050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098610ed8989097969101612ce8565b604051602081830303815290604052805190602001209050919050565b610efd61149d565b33600081815260036020526040902090610f189082906117f9565b50565b610f23611673565b60008111610f875760405162461bcd60e51b815260206004820152602b60248201527f7469636b657456616c6964697479506572696f64206d7573742062652067726560448201526a061746572207468616e20360ac1b606482015260840161048e565b60068190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252601490820152731d1a58dad95d15985b1a591a5d1e54195c9a5bd960621b604082015260600190565b610feb61149d565b610ff3611757565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561102b57600080fd5b505afa15801561103f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110639190612c9a565b6110af5760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b60005b8351811015611124576111118482815181106110d0576110d0612d4a565b60200260200101518483815181106110ea576110ea612d4a565b602002602001015184848151811061110457611104612d4a565b6020026020010151611a4e565b508061111c81612d76565b9150506110b2565b50505050565b60408051808201825260008082526020918201819052825180840184528181528083018290526001600160a01b038516825260038352908390208351808501909452805484526001015491830191909152611184836106fe565b9050915091565b61119361149d565b61119b611757565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111d357600080fd5b505afa1580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b9190612c9a565b6112575760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b600061126284610ea3565b905061127084828585611aef565b6020808501516001600160a01b03166000908152600382526040908190208151808301909252805482526001810154928201929092526112af90611563565b6112f05760405162461bcd60e51b81526020600482015260126024820152711cd95b99195c881a5cc81d5b9b1bd8dad95960721b604482015260640161048e565b80541515806113215750600061131f86602001516001600160a01b031660009081526002602052604090205490565b115b61133d5760405162461bcd60e51b815260040161048e90612c3e565b600082815260056020526040808220805460ff1916600117905582549087015111156113a65761139b6113938760200151886000015161138e86600001548b604001516119e890919063ffffffff16565b611d3e565b8354906115f7565b6000835590506113bb565b50604085015181546113b890826119e8565b82555b801561142a576113d48660000151828860c00151611ed6565b85600001516001600160a01b031686602001516001600160a01b03167f8b87351a208c06e3ceee59d80725fd77a23b4129e1b51ca231fc89b40712649c8360405161142191815260200190565b60405180910390a35b85600001516001600160a01b031686602001516001600160a01b03167fc389eb51ed006dbf2528507f010efdf5225ea596e1e1741d74f550dab1925ee7886040015189606001518a60800151898c60c0015160405161148d959493929190612dbd565b60405180910390a3505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114e957600080fd5b505afa1580156114fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115219190612c9a565b156115615760405162461bcd60e51b815260206004820152601060248201526f1cde5cdd195b481a5cc81c185d5cd95960821b604482015260640161048e565b565b60008160200151600014806106e957508160200151611580611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115b857600080fd5b505afa1580156115cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f09190612c81565b1092915050565b60006104398284612de8565b61160b611f5d565b6040516320283da960e01b81526001600160a01b0384811660048301526024820184905291909116906320283da990604401600060405180830381600087803b15801561165757600080fd5b505af115801561166b573d6000803e3d6000fd5b505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116bf57600080fd5b505afa1580156116d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f79190612e00565b6001600160a01b0316336001600160a01b0316146115615760405162461bcd60e51b815260206004820152601f60248201527f63616c6c6572206d75737420626520436f6e74726f6c6c6572206f776e657200604482015260640161048e565b60008054604051631c2d8fb360e31b81527fe8438ea868df48e3fc21f2f087b993c9b1837dc0f6135064161ce7d7a1701fe860048201526001600160a01b039091169063e16c7d98906024015b60206040518083038186803b1580156117bc57600080fd5b505afa1580156117d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f49190612e00565b905090565b6040805180820190915282548152600183015460209091018190526118605760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b6000600183018190556040516001600160a01b038316917ffa044b7b93a40365dc68049797c2eb06918523d694e5d56e406cac3eb35578e591a25050565b6118a6611f5d565b6001600160a01b031663f6326fb3826040518263ffffffff1660e01b81526004016020604051808303818588803b1580156118e057600080fd5b505af11580156118f4573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106fa9190612c9a565b6001600160a01b03821660009081526002602052604090205461193c90826115f7565b6001600160a01b038316600081815260026020526040908190209290925590517fb52b99b9e83551fcbd069b559cc3e823e2a1a3bad8ece46561ea77524394c85090610e979084815260200190565b60008054604051631c2d8fb360e31b81527f2517d59a36a86548e38734e8ab416f42afff4bca78706a66ad65750dae7f9e3760048201526001600160a01b039091169063e16c7d98906024016117a4565b60006104398284612e1d565b60006104398284612e3f565b6000546001600160a01b031633146115615760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015260640161048e565b600080848484604051602401611a6693929190612e56565b60408051601f198184030181529181526020820180516001600160e01b03166376459e5b60e11b179052519091503090611aa1908390612ee2565b6000604051808303816000865af19150503d8060008114611ade576040519150601f19603f3d011682016040523d82523d6000602084013e611ae3565b606091505b50909695505050505050565b83516001600160a01b0316611b465760405162461bcd60e51b815260206004820181905260248201527f7469636b657420726563697069656e74206973206e756c6c2061646472657373604482015260640161048e565b60208401516001600160a01b0316611ba05760405162461bcd60e51b815260206004820152601d60248201527f7469636b65742073656e646572206973206e756c6c2061646472657373000000604482015260640161048e565b611bad8460c00151611fae565b60a08401516040805160208101849052016040516020818303038152906040528051906020012014611c385760405162461bcd60e51b815260206004820152602e60248201527f726563697069656e7452616e6420646f6573206e6f74206d617463682072656360448201526d0d2e0d2cadce8a4c2dcc890c2e6d60931b606482015260840161048e565b60008381526005602052604090205460ff1615611c885760405162461bcd60e51b815260206004820152600e60248201526d1d1a58dad95d081a5cc81d5cd95960921b604482015260640161048e565b611c97846020015183856121fb565b611cee5760405162461bcd60e51b815260206004820152602260248201527f696e76616c6964207369676e6174757265206f766572207469636b65742068616044820152610e6d60f31b606482015260840161048e565b611cfd82828660600151612295565b6111245760405162461bcd60e51b81526020600482015260126024820152713a34b1b5b2ba103234b2103737ba103bb4b760711b604482015260640161048e565b600080611d4b85856108e9565b90506000818411611d5c5783611d5e565b815b90508015611ecd576000611d70611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611da857600080fd5b505afa158015611dbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de09190612c81565b6001600160a01b0388166000908152600260209081526040808320848452600181019092529091205491925090611e1790846115f7565b60008381526001830160209081526040808320939093556002840181528282206001600160a01b038b16835290522054611e5190846115f7565b600083815260028301602090815260408083206001600160a01b038c1684529091529020558054611e8290846119e8565b8155604080516001600160a01b038981168252602082018690528a16917f5c2b394723f408a40a60335e24b71829642e35f350cebe2036a96a66e895ea98910160405180910390a250505b95945050505050565b6000611ee1826122cc565b509050611eec61198b565b604051630ebad44b60e21b81526001600160a01b03868116600483015260248201869052604482018490529190911690633aeb512c90606401600060405180830381600087803b158015611f3f57600080fd5b505af1158015611f53573d6000803e3d6000fd5b5050505050505050565b60008054604051631c2d8fb360e31b81527f6e58ad548d72b425ea94c15f453bf26caddb061d82b2551db7fdd3cefe0e994060048201526001600160a01b039091169063e16c7d98906024016117a4565b600080611fba836122cc565b915091506000611fc8611757565b6001600160a01b0316633aa4add4846040518263ffffffff1660e01b8152600401611ff591815260200190565b60206040518083038186803b15801561200d57600080fd5b505afa158015612021573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120459190612c81565b9050806120ac5760405162461bcd60e51b815260206004820152602f60248201527f7469636b6574206372656174696f6e526f756e6420646f6573206e6f7420686160448201526e0ecca40c240c4d8dec6d640d0c2e6d608b1b606482015260840161048e565b8082146121215760405162461bcd60e51b815260206004820152603760248201527f7469636b6574206372656174696f6e526f756e64426c6f636b4861736820696e60448201527f76616c696420666f72206372656174696f6e526f756e64000000000000000000606482015260840161048e565b600061212b611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561216357600080fd5b505afa158015612177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219b9190612c81565b9050806121b3600654866115f790919063ffffffff16565b116121f45760405162461bcd60e51b81526020600482015260116024820152701d1a58dad95d081a5cc8195e1c1a5c9959607a1b604482015260640161048e565b5050505050565b6000825160411461224e5760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5349474e41545552455f4c454e4754480000000000000000604482015260640161048e565b600061226261225c8461234d565b85612388565b90506001600160a01b03811615801590611ecd5750806001600160a01b0316856001600160a01b03161495945050505050565b60008184846040516020016122ab929190612efe565b60408051601f19818403018152919052805160209091012010949350505050565b600080825160401461233c5760405162461bcd60e51b815260206004820152603360248201527f696e76616c6964206c656e67746820666f72207469636b657420617578446174604482015272613a206d75737420626520363420627974657360681b606482015260840161048e565b505060208101516040909101519091565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01610ed8565b600080600061239785856123ac565b915091506123a48161241c565b509392505050565b6000808251604114156123e35760208301516040840151606085015160001a6123d7878285856125d7565b94509450505050612415565b82516040141561240d57602083015160408401516124028683836126c4565b935093505050612415565b506000905060025b9250929050565b600081600481111561243057612430612f20565b14156124395750565b600181600481111561244d5761244d612f20565b141561249b5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161048e565b60028160048111156124af576124af612f20565b14156124fd5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161048e565b600381600481111561251157612511612f20565b141561256a5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161048e565b600481600481111561257e5761257e612f20565b1415610f185760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161048e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561260e57506000905060036126bb565b8460ff16601b1415801561262657508460ff16601c14155b1561263757506000905060046126bb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561268b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166126b4576000600192509250506126bb565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b016126e5878288856125d7565b935093505050935093915050565b6001600160a01b0381168114610f1857600080fd5b8035612713816126f3565b919050565b60006020828403121561272a57600080fd5b8135610439816126f3565b60006020828403121561274757600080fd5b5035919050565b6000806040838503121561276157600080fd5b823561276c816126f3565b9150602083013561277c816126f3565b809150509250929050565b6000806040838503121561279a57600080fd5b50508035926020909101359150565b8151815260208083015190820152604081016106e9565b6000806000606084860312156127d557600080fd5b83356127e0816126f3565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff8111828210171561282e5761282e6127f5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561285d5761285d6127f5565b604052919050565b600082601f83011261287657600080fd5b813567ffffffffffffffff811115612890576128906127f5565b6128a3601f8201601f1916602001612834565b8181528460208386010111156128b857600080fd5b816020850160208301376000918101602001919091529392505050565b600060e082840312156128e757600080fd5b6128ef61280b565b90506128fa82612708565b815261290860208301612708565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013567ffffffffffffffff81111561294f57600080fd5b61295b84828501612865565b60c08301525092915050565b60006020828403121561297957600080fd5b813567ffffffffffffffff81111561299057600080fd5b61299c848285016128d5565b949350505050565b600067ffffffffffffffff8211156129be576129be6127f5565b5060051b60200190565b600082601f8301126129d957600080fd5b813560206129ee6129e9836129a4565b612834565b82815260059290921b84018101918181019086841115612a0d57600080fd5b8286015b84811015612a4d57803567ffffffffffffffff811115612a315760008081fd5b612a3f8986838b0101612865565b845250918301918301612a11565b509695505050505050565b600082601f830112612a6957600080fd5b81356020612a796129e9836129a4565b82815260059290921b84018101918181019086841115612a9857600080fd5b8286015b84811015612a4d5780358352918301918301612a9c565b600080600060608486031215612ac857600080fd5b833567ffffffffffffffff80821115612ae057600080fd5b818601915086601f830112612af457600080fd5b81356020612b046129e9836129a4565b82815260059290921b8401810191818101908a841115612b2357600080fd5b8286015b84811015612b5b57803586811115612b3f5760008081fd5b612b4d8d86838b01016128d5565b845250918301918301612b27565b5097505087013592505080821115612b7257600080fd5b612b7e878388016129c8565b93506040860135915080821115612b9457600080fd5b50612ba186828701612a58565b9150509250925092565b825181526020808401518183015282516040830152820151606082015260808101610439565b600080600060608486031215612be657600080fd5b833567ffffffffffffffff80821115612bfe57600080fd5b612c0a878388016128d5565b94506020860135915080821115612c2057600080fd5b50612c2d86828701612865565b925050604084013590509250925092565b60208082526023908201527f73656e646572206465706f73697420616e64207265736572766520617265207a60408201526265726f60e81b606082015260800190565b600060208284031215612c9357600080fd5b5051919050565b600060208284031215612cac57600080fd5b8151801515811461043957600080fd5b60005b83811015612cd7578181015183820152602001612cbf565b838111156111245750506000910152565b60006bffffffffffffffffffffffff19808a60601b168352808960601b166014840152508660288301528560488301528460688301528360888301528251612d378160a8850160208701612cbc565b9190910160a80198975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612d8a57612d8a612d60565b5060010190565b60008151808452612da9816020860160208601612cbc565b601f01601f19169290920160200192915050565b85815284602082015283604082015282606082015260a060808201526000610af360a0830184612d91565b60008219821115612dfb57612dfb612d60565b500190565b600060208284031215612e1257600080fd5b8151610439816126f3565b600082612e3a57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612e5157612e51612d60565b500390565b60608152600060018060a01b0380865116606084015280602087015116608084015250604085015160a0830152606085015160c0830152608085015160e083015260a085015161010083015260c085015160e0610120840152612ebd610140840182612d91565b90508281036020840152612ed18186612d91565b915050826040830152949350505050565b60008251612ef4818460208701612cbc565b9190910192915050565b60008351612f10818460208801612cbc565b9190910191825250602001919050565b634e487b7160e01b600052602160045260246000fdfea264697066735822122088ef2a77769e316833ab9be870fcec7bee00cfc1143bcc795b1f6ce3cb21d6d264736f6c63430008090033", + "deployedBytecode": "0x6080604052600436106101405760003560e01c806381779f38116100b6578063c2c4c2c81161006f578063c2c4c2c814610329578063c92978081461033e578063d01b808e1461035e578063e1a589da1461037e578063ec8b3cb6146103ac578063f77c4791146103cc57600080fd5b806381779f381461028b578063856a2cf8146102ab57806392eefe9b146102c1578063989f789c146102e1578063a69df4b5146102f4578063b03fa8641461030957600080fd5b8063511f407311610108578063511f4073146101f557806351720b411461020857806359a515ba1461021e5780635b6333eb1461024e5780636caa736b1461027b5780636f9c3c8f1461028357600080fd5b8063121cdcc21461014557806320d3a0b41461017a5780633ccfd60b1461019e5780633d0ddf84146101b55780634ac826da146101d5575b600080fd5b34801561015157600080fd5b50610165610160366004612718565b610404565b60405190151581526020015b60405180910390f35b34801561018657600080fd5b5061019060045481565b604051908152602001610171565b3480156101aa57600080fd5b506101b3610440565b005b3480156101c157600080fd5b506101b36101d0366004612735565b6105c6565b3480156101e157600080fd5b506101906101f036600461274e565b61062d565b6101b3610203366004612787565b6106ef565b34801561021457600080fd5b5061019060015481565b34801561022a57600080fd5b50610165610239366004612735565b60056020526000908152604090205460ff1681565b34801561025a57600080fd5b5061026e610269366004612718565b6106fe565b60405161017191906127a9565b6101b36107cc565b6101b3610878565b34801561029757600080fd5b506101906102a636600461274e565b6108e9565b3480156102b757600080fd5b5061019060065481565b3480156102cd57600080fd5b506101b36102dc366004612718565b610afe565b6101b36102ef3660046127c0565b610b54565b34801561030057600080fd5b506101b3610d0f565b34801561031557600080fd5b50610190610324366004612967565b610ea3565b34801561033557600080fd5b506101b3610ef5565b34801561034a57600080fd5b506101b3610359366004612735565b610f1b565b34801561036a57600080fd5b506101b3610379366004612ab3565b610fe3565b34801561038a57600080fd5b5061039e610399366004612718565b61112a565b604051610171929190612bab565b3480156103b857600080fd5b506101b36103c7366004612bd1565b61118b565b3480156103d857600080fd5b506000546103ec906001600160a01b031681565b6040516001600160a01b039091168152602001610171565b6001600160a01b0381166000908152600360209081526040808320815180830190925280548252600101549181018290529015155b9392505050565b61044861149d565b33600090815260036020908152604080832080546002909352922054811515806104725750600081115b6104975760405162461bcd60e51b815260040161048e90612c3e565b60405180910390fd5b6040805180820190915283548152600184015460209091018190526104fe5760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b60408051808201909152835481526001840154602082015261051f90611563565b156105605760405162461bcd60e51b81526020600482015260116024820152701858d8dbdd5b9d081a5cc81b1bd8dad959607a1b604482015260640161048e565b6000808455338152600260205260408120556105853361058084846115f7565b611603565b604080518381526020810183905233917fdf273cb619d95419a9cd0ec88123a0538c85064229baa6363788f743fff90deb91015b60405180910390a2505050565b6105ce611673565b60048190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252600c908201526b1d5b9b1bd8dad4195c9a5bd960a21b604082015260600190565b60405180910390a150565b6001600160a01b03821660009081526002602052604081208161064e611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561068657600080fd5b505afa15801561069a573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906106be9190612c81565b60009081526002909201602090815260408084206001600160a01b0387168552909152909120549150505b92915050565b6106fa338383610b54565b5050565b604080518082018252600080825260208083018290526001600160a01b038516808352600280835294832080548552908352939052909160010190610741611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561077957600080fd5b505afa15801561078d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b19190612c81565b81526020808201929092526040016000205490820152919050565b6107d461149d565b33600081815260036020526040902080543491906107f290836115f7565b8155336001600160a01b038416148015610825575060408051808201909152815481526001820154602090910181905215155b156108345761083481846117f9565b61083d3461189e565b826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f836040516105b991815260200190565b61088061149d565b336000818152600360205260409020349061089b8383611919565b336001600160a01b0384161480156108cc575060408051808201909152815481526001820154602090910181905215155b156108db576108db81846117f9565b6108e43461189e565b505050565b6001600160a01b03821660009081526002602052604081208161090a611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561094257600080fd5b505afa158015610956573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097a9190612c81565b905061098461198b565b60405163022008dd60e21b81526001600160a01b038681166004830152919091169063088023749060240160206040518083038186803b1580156109c757600080fd5b505afa1580156109db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ff9190612c9a565b610a0e576000925050506106e9565b6000610a1861198b565b6001600160a01b0316632a4e0d556040518163ffffffff1660e01b815260040160206040518083038186803b158015610a5057600080fd5b505afa158015610a64573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a889190612c81565b905080610a9b57600093505050506106e9565b60008281526001840160205260408120548454610ab7916115f7565b600084815260028601602090815260408083206001600160a01b038b168452909152902054909150610af390610aed83856119dc565b906119e8565b979650505050505050565b610b066119f4565b600080546001600160a01b0319166001600160a01b0383169081179091556040519081527f4ff638452bbf33c012645d18ae6f05515ff5f2d1dfb0cece8cbf018c60903f7090602001610622565b610b5c61149d565b8181610b6882826115f7565b3414610be65760405162461bcd60e51b815260206004820152604160248201527f6d73672e76616c756520646f6573206e6f7420657175616c2073756d206f662060448201527f6465706f73697420616d6f756e7420616e64207265736572766520616d6f756e6064820152601d60fa1b608482015260a40161048e565b6001600160a01b0385166000908152600360205260409020805486918691610c0e90836115f7565b8155336001600160a01b038416148015610c41575060408051808201909152815481526001820154602090910181905215155b15610c5057610c5081846117f9565b6001600160a01b038816600090815260036020526040902088908790610c768383611919565b336001600160a01b038416148015610ca7575060408051808201909152815481526001820154602090910181905215155b15610cb657610cb681846117f9565b610cbf3461189e565b505050826001600160a01b03167f5159e237d952190e68d5215430f305831be7c9c8776d1377c76679ae4773413f83604051610cfd91815260200190565b60405180910390a25050505050505050565b610d1761149d565b3360009081526003602052604090208054151580610d42575033600090815260026020526040812054115b610d5e5760405162461bcd60e51b815260040161048e90612c3e565b60408051808201909152815481526001820154602090910181905215610dc65760405162461bcd60e51b815260206004820152601860248201527f756e6c6f636b20616c726561647920696e697469617465640000000000000000604482015260640161048e565b6000610dd0611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0857600080fd5b505afa158015610e1c573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e409190612c81565b9050610e57600454826115f790919063ffffffff16565b6001830181905560405133917ff7870c5b224cbc19873599e46ccfc7103934650509b1af0c3ce90138377c200491610e9791858252602082015260400190565b60405180910390a25050565b80516020808301516040808501516060860151608087015160a088015160c08901519451600098610ed8989097969101612ce8565b604051602081830303815290604052805190602001209050919050565b610efd61149d565b33600081815260036020526040902090610f189082906117f9565b50565b610f23611673565b60008111610f875760405162461bcd60e51b815260206004820152602b60248201527f7469636b657456616c6964697479506572696f64206d7573742062652067726560448201526a061746572207468616e20360ac1b606482015260840161048e565b60068190556040517f9f5033568d78ae30f29f01e944f97b2216493bd19d1b46d429673acff3dcd67490610622906020808252601490820152731d1a58dad95d15985b1a591a5d1e54195c9a5bd960621b604082015260600190565b610feb61149d565b610ff3611757565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b15801561102b57600080fd5b505afa15801561103f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110639190612c9a565b6110af5760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b60005b8351811015611124576111118482815181106110d0576110d0612d4a565b60200260200101518483815181106110ea576110ea612d4a565b602002602001015184848151811061110457611104612d4a565b6020026020010151611a4e565b508061111c81612d76565b9150506110b2565b50505050565b60408051808201825260008082526020918201819052825180840184528181528083018290526001600160a01b038516825260038352908390208351808501909452805484526001015491830191909152611184836106fe565b9050915091565b61119361149d565b61119b611757565b6001600160a01b031663219bc76c6040518163ffffffff1660e01b815260040160206040518083038186803b1580156111d357600080fd5b505afa1580156111e7573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061120b9190612c9a565b6112575760405162461bcd60e51b815260206004820181905260248201527f63757272656e7420726f756e64206973206e6f7420696e697469616c697a6564604482015260640161048e565b600061126284610ea3565b905061127084828585611aef565b6020808501516001600160a01b03166000908152600382526040908190208151808301909252805482526001810154928201929092526112af90611563565b6112f05760405162461bcd60e51b81526020600482015260126024820152711cd95b99195c881a5cc81d5b9b1bd8dad95960721b604482015260640161048e565b80541515806113215750600061131f86602001516001600160a01b031660009081526002602052604090205490565b115b61133d5760405162461bcd60e51b815260040161048e90612c3e565b600082815260056020526040808220805460ff1916600117905582549087015111156113a65761139b6113938760200151886000015161138e86600001548b604001516119e890919063ffffffff16565b611d3e565b8354906115f7565b6000835590506113bb565b50604085015181546113b890826119e8565b82555b801561142a576113d48660000151828860c00151611ed6565b85600001516001600160a01b031686602001516001600160a01b03167f8b87351a208c06e3ceee59d80725fd77a23b4129e1b51ca231fc89b40712649c8360405161142191815260200190565b60405180910390a35b85600001516001600160a01b031686602001516001600160a01b03167fc389eb51ed006dbf2528507f010efdf5225ea596e1e1741d74f550dab1925ee7886040015189606001518a60800151898c60c0015160405161148d959493929190612dbd565b60405180910390a3505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316635c975abb6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114e957600080fd5b505afa1580156114fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115219190612c9a565b156115615760405162461bcd60e51b815260206004820152601060248201526f1cde5cdd195b481a5cc81c185d5cd95960821b604482015260640161048e565b565b60008160200151600014806106e957508160200151611580611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156115b857600080fd5b505afa1580156115cc573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115f09190612c81565b1092915050565b60006104398284612de8565b61160b611f5d565b6040516320283da960e01b81526001600160a01b0384811660048301526024820184905291909116906320283da990604401600060405180830381600087803b15801561165757600080fd5b505af115801561166b573d6000803e3d6000fd5b505050505050565b60008054906101000a90046001600160a01b03166001600160a01b0316638da5cb5b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156116bf57600080fd5b505afa1580156116d3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116f79190612e00565b6001600160a01b0316336001600160a01b0316146115615760405162461bcd60e51b815260206004820152601f60248201527f63616c6c6572206d75737420626520436f6e74726f6c6c6572206f776e657200604482015260640161048e565b60008054604051631c2d8fb360e31b81527fe8438ea868df48e3fc21f2f087b993c9b1837dc0f6135064161ce7d7a1701fe860048201526001600160a01b039091169063e16c7d98906024015b60206040518083038186803b1580156117bc57600080fd5b505afa1580156117d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117f49190612e00565b905090565b6040805180820190915282548152600183015460209091018190526118605760405162461bcd60e51b815260206004820152601d60248201527f6e6f20756e6c6f636b207265717565737420696e2070726f6772657373000000604482015260640161048e565b6000600183018190556040516001600160a01b038316917ffa044b7b93a40365dc68049797c2eb06918523d694e5d56e406cac3eb35578e591a25050565b6118a6611f5d565b6001600160a01b031663f6326fb3826040518263ffffffff1660e01b81526004016020604051808303818588803b1580156118e057600080fd5b505af11580156118f4573d6000803e3d6000fd5b50505050506040513d601f19601f820116820180604052508101906106fa9190612c9a565b6001600160a01b03821660009081526002602052604090205461193c90826115f7565b6001600160a01b038316600081815260026020526040908190209290925590517fb52b99b9e83551fcbd069b559cc3e823e2a1a3bad8ece46561ea77524394c85090610e979084815260200190565b60008054604051631c2d8fb360e31b81527f2517d59a36a86548e38734e8ab416f42afff4bca78706a66ad65750dae7f9e3760048201526001600160a01b039091169063e16c7d98906024016117a4565b60006104398284612e1d565b60006104398284612e3f565b6000546001600160a01b031633146115615760405162461bcd60e51b815260206004820152601960248201527f63616c6c6572206d75737420626520436f6e74726f6c6c657200000000000000604482015260640161048e565b600080848484604051602401611a6693929190612e56565b60408051601f198184030181529181526020820180516001600160e01b03166376459e5b60e11b179052519091503090611aa1908390612ee2565b6000604051808303816000865af19150503d8060008114611ade576040519150601f19603f3d011682016040523d82523d6000602084013e611ae3565b606091505b50909695505050505050565b83516001600160a01b0316611b465760405162461bcd60e51b815260206004820181905260248201527f7469636b657420726563697069656e74206973206e756c6c2061646472657373604482015260640161048e565b60208401516001600160a01b0316611ba05760405162461bcd60e51b815260206004820152601d60248201527f7469636b65742073656e646572206973206e756c6c2061646472657373000000604482015260640161048e565b611bad8460c00151611fae565b60a08401516040805160208101849052016040516020818303038152906040528051906020012014611c385760405162461bcd60e51b815260206004820152602e60248201527f726563697069656e7452616e6420646f6573206e6f74206d617463682072656360448201526d0d2e0d2cadce8a4c2dcc890c2e6d60931b606482015260840161048e565b60008381526005602052604090205460ff1615611c885760405162461bcd60e51b815260206004820152600e60248201526d1d1a58dad95d081a5cc81d5cd95960921b604482015260640161048e565b611c97846020015183856121fb565b611cee5760405162461bcd60e51b815260206004820152602260248201527f696e76616c6964207369676e6174757265206f766572207469636b65742068616044820152610e6d60f31b606482015260840161048e565b611cfd82828660600151612295565b6111245760405162461bcd60e51b81526020600482015260126024820152713a34b1b5b2ba103234b2103737ba103bb4b760711b604482015260640161048e565b600080611d4b85856108e9565b90506000818411611d5c5783611d5e565b815b90508015611ecd576000611d70611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015611da857600080fd5b505afa158015611dbc573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611de09190612c81565b6001600160a01b0388166000908152600260209081526040808320848452600181019092529091205491925090611e1790846115f7565b60008381526001830160209081526040808320939093556002840181528282206001600160a01b038b16835290522054611e5190846115f7565b600083815260028301602090815260408083206001600160a01b038c1684529091529020558054611e8290846119e8565b8155604080516001600160a01b038981168252602082018690528a16917f5c2b394723f408a40a60335e24b71829642e35f350cebe2036a96a66e895ea98910160405180910390a250505b95945050505050565b6000611ee1826122cc565b509050611eec61198b565b604051630ebad44b60e21b81526001600160a01b03868116600483015260248201869052604482018490529190911690633aeb512c90606401600060405180830381600087803b158015611f3f57600080fd5b505af1158015611f53573d6000803e3d6000fd5b5050505050505050565b60008054604051631c2d8fb360e31b81527f6e58ad548d72b425ea94c15f453bf26caddb061d82b2551db7fdd3cefe0e994060048201526001600160a01b039091169063e16c7d98906024016117a4565b600080611fba836122cc565b915091506000611fc8611757565b6001600160a01b0316633aa4add4846040518263ffffffff1660e01b8152600401611ff591815260200190565b60206040518083038186803b15801561200d57600080fd5b505afa158015612021573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120459190612c81565b9050806120ac5760405162461bcd60e51b815260206004820152602f60248201527f7469636b6574206372656174696f6e526f756e6420646f6573206e6f7420686160448201526e0ecca40c240c4d8dec6d640d0c2e6d608b1b606482015260840161048e565b8082146121215760405162461bcd60e51b815260206004820152603760248201527f7469636b6574206372656174696f6e526f756e64426c6f636b4861736820696e60448201527f76616c696420666f72206372656174696f6e526f756e64000000000000000000606482015260840161048e565b600061212b611757565b6001600160a01b0316638a19c8bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561216357600080fd5b505afa158015612177573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061219b9190612c81565b9050806121b3600654866115f790919063ffffffff16565b116121f45760405162461bcd60e51b81526020600482015260116024820152701d1a58dad95d081a5cc8195e1c1a5c9959607a1b604482015260640161048e565b5050505050565b6000825160411461224e5760405162461bcd60e51b815260206004820152601860248201527f494e56414c49445f5349474e41545552455f4c454e4754480000000000000000604482015260640161048e565b600061226261225c8461234d565b85612388565b90506001600160a01b03811615801590611ecd5750806001600160a01b0316856001600160a01b03161495945050505050565b60008184846040516020016122ab929190612efe565b60408051601f19818403018152919052805160209091012010949350505050565b600080825160401461233c5760405162461bcd60e51b815260206004820152603360248201527f696e76616c6964206c656e67746820666f72207469636b657420617578446174604482015272613a206d75737420626520363420627974657360681b606482015260840161048e565b505060208101516040909101519091565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3332000000006020820152603c8101829052600090605c01610ed8565b600080600061239785856123ac565b915091506123a48161241c565b509392505050565b6000808251604114156123e35760208301516040840151606085015160001a6123d7878285856125d7565b94509450505050612415565b82516040141561240d57602083015160408401516124028683836126c4565b935093505050612415565b506000905060025b9250929050565b600081600481111561243057612430612f20565b14156124395750565b600181600481111561244d5761244d612f20565b141561249b5760405162461bcd60e51b815260206004820152601860248201527f45434453413a20696e76616c6964207369676e61747572650000000000000000604482015260640161048e565b60028160048111156124af576124af612f20565b14156124fd5760405162461bcd60e51b815260206004820152601f60248201527f45434453413a20696e76616c6964207369676e6174757265206c656e67746800604482015260640161048e565b600381600481111561251157612511612f20565b141561256a5760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202773272076616c604482015261756560f01b606482015260840161048e565b600481600481111561257e5761257e612f20565b1415610f185760405162461bcd60e51b815260206004820152602260248201527f45434453413a20696e76616c6964207369676e6174757265202776272076616c604482015261756560f01b606482015260840161048e565b6000807f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a083111561260e57506000905060036126bb565b8460ff16601b1415801561262657508460ff16601c14155b1561263757506000905060046126bb565b6040805160008082526020820180845289905260ff881692820192909252606081018690526080810185905260019060a0016020604051602081039080840390855afa15801561268b573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166126b4576000600192509250506126bb565b9150600090505b94509492505050565b6000806001600160ff1b03831660ff84901c601b016126e5878288856125d7565b935093505050935093915050565b6001600160a01b0381168114610f1857600080fd5b8035612713816126f3565b919050565b60006020828403121561272a57600080fd5b8135610439816126f3565b60006020828403121561274757600080fd5b5035919050565b6000806040838503121561276157600080fd5b823561276c816126f3565b9150602083013561277c816126f3565b809150509250929050565b6000806040838503121561279a57600080fd5b50508035926020909101359150565b8151815260208083015190820152604081016106e9565b6000806000606084860312156127d557600080fd5b83356127e0816126f3565b95602085013595506040909401359392505050565b634e487b7160e01b600052604160045260246000fd5b60405160e0810167ffffffffffffffff8111828210171561282e5761282e6127f5565b60405290565b604051601f8201601f1916810167ffffffffffffffff8111828210171561285d5761285d6127f5565b604052919050565b600082601f83011261287657600080fd5b813567ffffffffffffffff811115612890576128906127f5565b6128a3601f8201601f1916602001612834565b8181528460208386010111156128b857600080fd5b816020850160208301376000918101602001919091529392505050565b600060e082840312156128e757600080fd5b6128ef61280b565b90506128fa82612708565b815261290860208301612708565b602082015260408201356040820152606082013560608201526080820135608082015260a082013560a082015260c082013567ffffffffffffffff81111561294f57600080fd5b61295b84828501612865565b60c08301525092915050565b60006020828403121561297957600080fd5b813567ffffffffffffffff81111561299057600080fd5b61299c848285016128d5565b949350505050565b600067ffffffffffffffff8211156129be576129be6127f5565b5060051b60200190565b600082601f8301126129d957600080fd5b813560206129ee6129e9836129a4565b612834565b82815260059290921b84018101918181019086841115612a0d57600080fd5b8286015b84811015612a4d57803567ffffffffffffffff811115612a315760008081fd5b612a3f8986838b0101612865565b845250918301918301612a11565b509695505050505050565b600082601f830112612a6957600080fd5b81356020612a796129e9836129a4565b82815260059290921b84018101918181019086841115612a9857600080fd5b8286015b84811015612a4d5780358352918301918301612a9c565b600080600060608486031215612ac857600080fd5b833567ffffffffffffffff80821115612ae057600080fd5b818601915086601f830112612af457600080fd5b81356020612b046129e9836129a4565b82815260059290921b8401810191818101908a841115612b2357600080fd5b8286015b84811015612b5b57803586811115612b3f5760008081fd5b612b4d8d86838b01016128d5565b845250918301918301612b27565b5097505087013592505080821115612b7257600080fd5b612b7e878388016129c8565b93506040860135915080821115612b9457600080fd5b50612ba186828701612a58565b9150509250925092565b825181526020808401518183015282516040830152820151606082015260808101610439565b600080600060608486031215612be657600080fd5b833567ffffffffffffffff80821115612bfe57600080fd5b612c0a878388016128d5565b94506020860135915080821115612c2057600080fd5b50612c2d86828701612865565b925050604084013590509250925092565b60208082526023908201527f73656e646572206465706f73697420616e64207265736572766520617265207a60408201526265726f60e81b606082015260800190565b600060208284031215612c9357600080fd5b5051919050565b600060208284031215612cac57600080fd5b8151801515811461043957600080fd5b60005b83811015612cd7578181015183820152602001612cbf565b838111156111245750506000910152565b60006bffffffffffffffffffffffff19808a60601b168352808960601b166014840152508660288301528560488301528460688301528360888301528251612d378160a8850160208701612cbc565b9190910160a80198975050505050505050565b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052601160045260246000fd5b6000600019821415612d8a57612d8a612d60565b5060010190565b60008151808452612da9816020860160208601612cbc565b601f01601f19169290920160200192915050565b85815284602082015283604082015282606082015260a060808201526000610af360a0830184612d91565b60008219821115612dfb57612dfb612d60565b500190565b600060208284031215612e1257600080fd5b8151610439816126f3565b600082612e3a57634e487b7160e01b600052601260045260246000fd5b500490565b600082821015612e5157612e51612d60565b500390565b60608152600060018060a01b0380865116606084015280602087015116608084015250604085015160a0830152606085015160c0830152608085015160e083015260a085015161010083015260c085015160e0610120840152612ebd610140840182612d91565b90508281036020840152612ed18186612d91565b915050826040830152949350505050565b60008251612ef4818460208701612cbc565b9190910192915050565b60008351612f10818460208801612cbc565b9190910191825250602001919050565b634e487b7160e01b600052602160045260246000fdfea264697066735822122088ef2a77769e316833ab9be870fcec7bee00cfc1143bcc795b1f6ce3cb21d6d264736f6c63430008090033", "devdoc": { "kind": "dev", "methods": { @@ -949,23 +949,23 @@ "type": "t_bytes32" }, { - "astId": 8568, + "astId": 8647, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "reserves", "offset": 0, "slot": "2", - "type": "t_mapping(t_address,t_struct(Reserve)8563_storage)" + "type": "t_mapping(t_address,t_struct(Reserve)8642_storage)" }, { - "astId": 8892, + "astId": 8971, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "senders", "offset": 0, "slot": "3", - "type": "t_mapping(t_address,t_struct(Sender)8887_storage)" + "type": "t_mapping(t_address,t_struct(Sender)8966_storage)" }, { - "astId": 8894, + "astId": 8973, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "unlockPeriod", "offset": 0, @@ -973,7 +973,7 @@ "type": "t_uint256" }, { - "astId": 8898, + "astId": 8977, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "usedTickets", "offset": 0, @@ -981,7 +981,7 @@ "type": "t_mapping(t_bytes32,t_bool)" }, { - "astId": 9695, + "astId": 9784, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "ticketValidityPeriod", "offset": 0, @@ -1010,19 +1010,19 @@ "label": "contract IController", "numberOfBytes": "20" }, - "t_mapping(t_address,t_struct(Reserve)8563_storage)": { + "t_mapping(t_address,t_struct(Reserve)8642_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct MixinReserve.Reserve)", "numberOfBytes": "32", - "value": "t_struct(Reserve)8563_storage" + "value": "t_struct(Reserve)8642_storage" }, - "t_mapping(t_address,t_struct(Sender)8887_storage)": { + "t_mapping(t_address,t_struct(Sender)8966_storage)": { "encoding": "mapping", "key": "t_address", "label": "mapping(address => struct MixinTicketBrokerCore.Sender)", "numberOfBytes": "32", - "value": "t_struct(Sender)8887_storage" + "value": "t_struct(Sender)8966_storage" }, "t_mapping(t_address,t_uint256)": { "encoding": "mapping", @@ -1052,12 +1052,12 @@ "numberOfBytes": "32", "value": "t_uint256" }, - "t_struct(Reserve)8563_storage": { + "t_struct(Reserve)8642_storage": { "encoding": "inplace", "label": "struct MixinReserve.Reserve", "members": [ { - "astId": 8552, + "astId": 8631, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "funds", "offset": 0, @@ -1065,7 +1065,7 @@ "type": "t_uint256" }, { - "astId": 8556, + "astId": 8635, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "claimedForRound", "offset": 0, @@ -1073,7 +1073,7 @@ "type": "t_mapping(t_uint256,t_uint256)" }, { - "astId": 8562, + "astId": 8641, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "claimedByAddress", "offset": 0, @@ -1083,12 +1083,12 @@ ], "numberOfBytes": "96" }, - "t_struct(Sender)8887_storage": { + "t_struct(Sender)8966_storage": { "encoding": "inplace", "label": "struct MixinTicketBrokerCore.Sender", "members": [ { - "astId": 8884, + "astId": 8963, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "deposit", "offset": 0, @@ -1096,7 +1096,7 @@ "type": "t_uint256" }, { - "astId": 8886, + "astId": 8965, "contract": "contracts/pm/TicketBroker.sol:TicketBroker", "label": "withdrawRound", "offset": 0, diff --git a/deployments/arbitrumMainnet/solcInputs/13bbf81b78bf748dd89a83d5a98b32f5.json b/deployments/arbitrumMainnet/solcInputs/13bbf81b78bf748dd89a83d5a98b32f5.json new file mode 100644 index 00000000..871241ff --- /dev/null +++ b/deployments/arbitrumMainnet/solcInputs/13bbf81b78bf748dd89a83d5a98b32f5.json @@ -0,0 +1,287 @@ +{ + "language": "Solidity", + "sources": { + "contracts/bonding/BondingManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../ManagerProxyTarget.sol\";\nimport \"./IBondingManager.sol\";\nimport \"../libraries/SortedDoublyLL.sol\";\nimport \"../libraries/MathUtils.sol\";\nimport \"../libraries/PreciseMathUtils.sol\";\nimport \"./libraries/EarningsPool.sol\";\nimport \"./libraries/EarningsPoolLIP36.sol\";\nimport \"../token/ILivepeerToken.sol\";\nimport \"../token/IMinter.sol\";\nimport \"../rounds/IRoundsManager.sol\";\nimport \"../snapshots/IMerkleSnapshot.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title BondingManager\n * @notice Manages bonding, transcoder and rewards/fee accounting related operations of the Livepeer protocol\n */\ncontract BondingManager is ManagerProxyTarget, IBondingManager {\n using SafeMath for uint256;\n using SortedDoublyLL for SortedDoublyLL.Data;\n using EarningsPool for EarningsPool.Data;\n using EarningsPoolLIP36 for EarningsPool.Data;\n\n // Constants\n // Occurances are replaced at compile time\n // and computed to a single value if possible by the optimizer\n uint256 constant MAX_FUTURE_ROUND = 2**256 - 1;\n\n // Time between unbonding and possible withdrawl in rounds\n uint64 public unbondingPeriod;\n\n // Represents a transcoder's current state\n struct Transcoder {\n uint256 lastRewardRound; // Last round that the transcoder called reward\n uint256 rewardCut; // % of reward paid to transcoder by a delegator\n uint256 feeShare; // % of fees paid to delegators by transcoder\n mapping(uint256 => EarningsPool.Data) earningsPoolPerRound; // Mapping of round => earnings pool for the round\n uint256 lastActiveStakeUpdateRound; // Round for which the stake was last updated while the transcoder is active\n uint256 activationRound; // Round in which the transcoder became active - 0 if inactive\n uint256 deactivationRound; // Round in which the transcoder will become inactive\n uint256 activeCumulativeRewards; // The transcoder's cumulative rewards that are active in the current round\n uint256 cumulativeRewards; // The transcoder's cumulative rewards (earned via the its active staked rewards and its reward cut).\n uint256 cumulativeFees; // The transcoder's cumulative fees (earned via the its active staked rewards and its fee share)\n uint256 lastFeeRound; // Latest round in which the transcoder received fees\n }\n\n // The various states a transcoder can be in\n enum TranscoderStatus {\n NotRegistered,\n Registered\n }\n\n // Represents a delegator's current state\n struct Delegator {\n uint256 bondedAmount; // The amount of bonded tokens\n uint256 fees; // The amount of fees collected\n address delegateAddress; // The address delegated to\n uint256 delegatedAmount; // The amount of tokens delegated to the delegator\n uint256 startRound; // The round the delegator transitions to bonded phase and is delegated to someone\n uint256 lastClaimRound; // The last round during which the delegator claimed its earnings\n uint256 nextUnbondingLockId; // ID for the next unbonding lock created\n mapping(uint256 => UnbondingLock) unbondingLocks; // Mapping of unbonding lock ID => unbonding lock\n }\n\n // The various states a delegator can be in\n enum DelegatorStatus {\n Pending,\n Bonded,\n Unbonded\n }\n\n // Represents an amount of tokens that are being unbonded\n struct UnbondingLock {\n uint256 amount; // Amount of tokens being unbonded\n uint256 withdrawRound; // Round at which unbonding period is over and tokens can be withdrawn\n }\n\n // Keep track of the known transcoders and delegators\n mapping(address => Delegator) private delegators;\n mapping(address => Transcoder) private transcoders;\n\n // The total active stake (sum of the stake of active set members) for the current round\n uint256 public currentRoundTotalActiveStake;\n // The total active stake (sum of the stake of active set members) for the next round\n uint256 public nextRoundTotalActiveStake;\n\n // The transcoder pool is used to keep track of the transcoders that are eligible for activation.\n // The pool keeps track of the pending active set in round N and the start of round N + 1 transcoders\n // in the pool are locked into the active set for round N + 1\n SortedDoublyLL.Data private transcoderPool;\n\n // Check if sender is TicketBroker\n modifier onlyTicketBroker() {\n _onlyTicketBroker();\n _;\n }\n\n // Check if sender is RoundsManager\n modifier onlyRoundsManager() {\n _onlyRoundsManager();\n _;\n }\n\n // Check if sender is Verifier\n modifier onlyVerifier() {\n _onlyVerifier();\n _;\n }\n\n // Check if current round is initialized\n modifier currentRoundInitialized() {\n _currentRoundInitialized();\n _;\n }\n\n // Automatically claim earnings from lastClaimRound through the current round\n modifier autoClaimEarnings(address _delegator) {\n _autoClaimEarnings(_delegator);\n _;\n }\n\n /**\n * @notice BondingManager constructor. Only invokes constructor of base Manager contract with provided Controller address\n * @dev This constructor will not initialize any state variables besides `controller`. The following setter functions\n * should be used to initialize state variables post-deployment:\n * - setUnbondingPeriod()\n * - setNumActiveTranscoders()\n * - setMaxEarningsClaimsRounds()\n * @param _controller Address of Controller that this contract will be registered with\n */\n constructor(address _controller) Manager(_controller) {}\n\n /**\n * @notice Set unbonding period. Only callable by Controller owner\n * @param _unbondingPeriod Rounds between unbonding and possible withdrawal\n */\n function setUnbondingPeriod(uint64 _unbondingPeriod) external onlyControllerOwner {\n unbondingPeriod = _unbondingPeriod;\n\n emit ParameterUpdate(\"unbondingPeriod\");\n }\n\n /**\n * @notice Set maximum number of active transcoders. Only callable by Controller owner\n * @param _numActiveTranscoders Number of active transcoders\n */\n function setNumActiveTranscoders(uint256 _numActiveTranscoders) external onlyControllerOwner {\n transcoderPool.setMaxSize(_numActiveTranscoders);\n\n emit ParameterUpdate(\"numActiveTranscoders\");\n }\n\n /**\n * @notice Sets commission rates as a transcoder and if the caller is not in the transcoder pool tries to add it\n * @dev Percentages are represented as numerators of fractions over MathUtils.PERC_DIVISOR\n * @param _rewardCut % of reward paid to transcoder by a delegator\n * @param _feeShare % of fees paid to delegators by a transcoder\n */\n function transcoder(uint256 _rewardCut, uint256 _feeShare) external {\n transcoderWithHint(_rewardCut, _feeShare, address(0), address(0));\n }\n\n /**\n * @notice Delegate stake towards a specific address\n * @param _amount The amount of tokens to stake\n * @param _to The address of the transcoder to stake towards\n */\n function bond(uint256 _amount, address _to) external {\n bondWithHint(_amount, _to, address(0), address(0), address(0), address(0));\n }\n\n /**\n * @notice Unbond an amount of the delegator's bonded stake\n * @param _amount Amount of tokens to unbond\n */\n function unbond(uint256 _amount) external {\n unbondWithHint(_amount, address(0), address(0));\n }\n\n /**\n * @notice Rebond tokens for an unbonding lock to a delegator's current delegate while a delegator is in the Bonded or Pending status\n * @param _unbondingLockId ID of unbonding lock to rebond with\n */\n function rebond(uint256 _unbondingLockId) external {\n rebondWithHint(_unbondingLockId, address(0), address(0));\n }\n\n /**\n * @notice Rebond tokens for an unbonding lock to a delegate while a delegator is in the Unbonded status\n * @param _to Address of delegate\n * @param _unbondingLockId ID of unbonding lock to rebond with\n */\n function rebondFromUnbonded(address _to, uint256 _unbondingLockId) external {\n rebondFromUnbondedWithHint(_to, _unbondingLockId, address(0), address(0));\n }\n\n /**\n * @notice Withdraws tokens for an unbonding lock that has existed through an unbonding period\n * @param _unbondingLockId ID of unbonding lock to withdraw with\n */\n function withdrawStake(uint256 _unbondingLockId) external whenSystemNotPaused currentRoundInitialized {\n Delegator storage del = delegators[msg.sender];\n UnbondingLock storage lock = del.unbondingLocks[_unbondingLockId];\n\n require(isValidUnbondingLock(msg.sender, _unbondingLockId), \"invalid unbonding lock ID\");\n require(\n lock.withdrawRound <= roundsManager().currentRound(),\n \"withdraw round must be before or equal to the current round\"\n );\n\n uint256 amount = lock.amount;\n uint256 withdrawRound = lock.withdrawRound;\n // Delete unbonding lock\n delete del.unbondingLocks[_unbondingLockId];\n\n // Tell Minter to transfer stake (LPT) to the delegator\n minter().trustedTransferTokens(msg.sender, amount);\n\n emit WithdrawStake(msg.sender, _unbondingLockId, amount, withdrawRound);\n }\n\n /**\n * @notice Withdraws fees to the caller\n */\n function withdrawFees(address payable _recipient, uint256 _amount)\n external\n whenSystemNotPaused\n currentRoundInitialized\n autoClaimEarnings(msg.sender)\n {\n require(_recipient != address(0), \"invalid recipient\");\n uint256 fees = delegators[msg.sender].fees;\n require(fees >= _amount, \"insufficient fees to withdraw\");\n delegators[msg.sender].fees = fees.sub(_amount);\n\n // Tell Minter to transfer fees (ETH) to the address\n minter().trustedWithdrawETH(_recipient, _amount);\n\n emit WithdrawFees(msg.sender, _recipient, _amount);\n }\n\n /**\n * @notice Mint token rewards for an active transcoder and its delegators\n */\n function reward() external {\n rewardWithHint(address(0), address(0));\n }\n\n /**\n * @notice Update transcoder's fee pool. Only callable by the TicketBroker\n * @param _transcoder Transcoder address\n * @param _fees Fees to be added to the fee pool\n */\n function updateTranscoderWithFees(\n address _transcoder,\n uint256 _fees,\n uint256 _round\n ) external whenSystemNotPaused onlyTicketBroker {\n // Silence unused param compiler warning\n _round;\n\n require(isRegisteredTranscoder(_transcoder), \"transcoder must be registered\");\n\n uint256 currentRound = roundsManager().currentRound();\n\n Transcoder storage t = transcoders[_transcoder];\n\n uint256 lastRewardRound = t.lastRewardRound;\n uint256 activeCumulativeRewards = t.activeCumulativeRewards;\n\n // LIP-36: Add fees for the current round instead of '_round'\n // https://github.com/livepeer/LIPs/issues/35#issuecomment-673659199\n EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[currentRound];\n EarningsPool.Data memory prevEarningsPool = latestCumulativeFactorsPool(t, currentRound.sub(1));\n\n // if transcoder hasn't called 'reward()' for '_round' its 'transcoderFeeShare', 'transcoderRewardCut' and 'totalStake'\n // on the 'EarningsPool' for '_round' would not be initialized and the fee distribution wouldn't happen as expected\n // for cumulative fee calculation this would result in division by zero.\n if (currentRound > lastRewardRound) {\n earningsPool.setCommission(t.rewardCut, t.feeShare);\n\n uint256 lastUpdateRound = t.lastActiveStakeUpdateRound;\n if (lastUpdateRound < currentRound) {\n earningsPool.setStake(t.earningsPoolPerRound[lastUpdateRound].totalStake);\n }\n\n // If reward() has not been called yet in the current round, then the transcoder's activeCumulativeRewards has not\n // yet been set in for the round. When the transcoder calls reward() its activeCumulativeRewards will be set to its\n // current cumulativeRewards. So, we can just use the transcoder's cumulativeRewards here because this will become\n // the transcoder's activeCumulativeRewards if it calls reward() later on in the current round\n activeCumulativeRewards = t.cumulativeRewards;\n }\n\n uint256 totalStake = earningsPool.totalStake;\n if (prevEarningsPool.cumulativeRewardFactor == 0 && lastRewardRound == currentRound) {\n // if transcoder called reward for 'currentRound' but not for 'currentRound - 1' (missed reward call)\n // retroactively calculate what its cumulativeRewardFactor would have been for 'currentRound - 1' (cfr. previous lastRewardRound for transcoder)\n // based on rewards for currentRound\n IMinter mtr = minter();\n uint256 rewards = PreciseMathUtils.percOf(\n mtr.currentMintableTokens().add(mtr.currentMintedTokens()),\n totalStake,\n currentRoundTotalActiveStake\n );\n uint256 transcoderCommissionRewards = MathUtils.percOf(rewards, earningsPool.transcoderRewardCut);\n uint256 delegatorsRewards = rewards.sub(transcoderCommissionRewards);\n\n prevEarningsPool.cumulativeRewardFactor = PreciseMathUtils.percOf(\n earningsPool.cumulativeRewardFactor,\n totalStake,\n delegatorsRewards.add(totalStake)\n );\n }\n\n uint256 delegatorsFees = MathUtils.percOf(_fees, earningsPool.transcoderFeeShare);\n uint256 transcoderCommissionFees = _fees.sub(delegatorsFees);\n // Calculate the fees earned by the transcoder's earned rewards\n uint256 transcoderRewardStakeFees = PreciseMathUtils.percOf(\n delegatorsFees,\n activeCumulativeRewards,\n totalStake\n );\n // Track fees earned by the transcoder based on its earned rewards and feeShare\n t.cumulativeFees = t.cumulativeFees.add(transcoderRewardStakeFees).add(transcoderCommissionFees);\n // Update cumulative fee factor with new fees\n // The cumulativeFeeFactor is used to calculate fees for all delegators including the transcoder (self-delegated)\n // Note that delegatorsFees includes transcoderRewardStakeFees, but no delegator will claim that amount using\n // the earnings claiming algorithm and instead that amount is accounted for in the transcoder's cumulativeFees field\n earningsPool.updateCumulativeFeeFactor(prevEarningsPool, delegatorsFees);\n\n t.lastFeeRound = currentRound;\n }\n\n /**\n * @notice Slash a transcoder. Only callable by the Verifier\n * @param _transcoder Transcoder address\n * @param _finder Finder that proved a transcoder violated a slashing condition. Null address if there is no finder\n * @param _slashAmount Percentage of transcoder bond to be slashed\n * @param _finderFee Percentage of penalty awarded to finder. Zero if there is no finder\n */\n function slashTranscoder(\n address _transcoder,\n address _finder,\n uint256 _slashAmount,\n uint256 _finderFee\n ) external whenSystemNotPaused onlyVerifier {\n Delegator storage del = delegators[_transcoder];\n\n if (del.bondedAmount > 0) {\n uint256 penalty = MathUtils.percOf(delegators[_transcoder].bondedAmount, _slashAmount);\n\n // If active transcoder, resign it\n if (transcoderPool.contains(_transcoder)) {\n resignTranscoder(_transcoder);\n }\n\n // Decrease bonded stake\n del.bondedAmount = del.bondedAmount.sub(penalty);\n\n // If still bonded decrease delegate's delegated amount\n if (delegatorStatus(_transcoder) == DelegatorStatus.Bonded) {\n delegators[del.delegateAddress].delegatedAmount = delegators[del.delegateAddress].delegatedAmount.sub(\n penalty\n );\n }\n\n // Account for penalty\n uint256 burnAmount = penalty;\n\n // Award finder fee if there is a finder address\n if (_finder != address(0)) {\n uint256 finderAmount = MathUtils.percOf(penalty, _finderFee);\n minter().trustedTransferTokens(_finder, finderAmount);\n\n // Minter burns the slashed funds - finder reward\n minter().trustedBurnTokens(burnAmount.sub(finderAmount));\n\n emit TranscoderSlashed(_transcoder, _finder, penalty, finderAmount);\n } else {\n // Minter burns the slashed funds\n minter().trustedBurnTokens(burnAmount);\n\n emit TranscoderSlashed(_transcoder, address(0), penalty, 0);\n }\n } else {\n emit TranscoderSlashed(_transcoder, _finder, 0, 0);\n }\n }\n\n /**\n * @notice Claim token pools shares for a delegator from its lastClaimRound through the end round\n * @param _endRound The last round for which to claim token pools shares for a delegator\n */\n function claimEarnings(uint256 _endRound) external whenSystemNotPaused currentRoundInitialized {\n // Silence unused param compiler warning\n _endRound;\n\n _autoClaimEarnings(msg.sender);\n }\n\n /**\n * @notice Called during round initialization to set the total active stake for the round. Only callable by the RoundsManager\n */\n function setCurrentRoundTotalActiveStake() external onlyRoundsManager {\n currentRoundTotalActiveStake = nextRoundTotalActiveStake;\n }\n\n /**\n * @notice Sets commission rates as a transcoder and if the caller is not in the transcoder pool tries to add it using an optional list hint\n * @dev Percentages are represented as numerators of fractions over MathUtils.PERC_DIVISOR. If the caller is going to be added to the pool, the\n * caller can provide an optional hint for the insertion position in the pool via the `_newPosPrev` and `_newPosNext` params. A linear search will\n * be executed starting at the hint to find the correct position - in the best case, the hint is the correct position so no search is executed.\n * See SortedDoublyLL.sol for details on list hints\n * @param _rewardCut % of reward paid to transcoder by a delegator\n * @param _feeShare % of fees paid to delegators by a transcoder\n * @param _newPosPrev Address of previous transcoder in pool if the caller joins the pool\n * @param _newPosNext Address of next transcoder in pool if the caller joins the pool\n */\n function transcoderWithHint(\n uint256 _rewardCut,\n uint256 _feeShare,\n address _newPosPrev,\n address _newPosNext\n ) public whenSystemNotPaused currentRoundInitialized {\n require(!roundsManager().currentRoundLocked(), \"can't update transcoder params, current round is locked\");\n require(MathUtils.validPerc(_rewardCut), \"invalid rewardCut percentage\");\n require(MathUtils.validPerc(_feeShare), \"invalid feeShare percentage\");\n require(isRegisteredTranscoder(msg.sender), \"transcoder must be registered\");\n\n Transcoder storage t = transcoders[msg.sender];\n uint256 currentRound = roundsManager().currentRound();\n\n require(\n !isActiveTranscoder(msg.sender) || t.lastRewardRound == currentRound,\n \"caller can't be active or must have already called reward for the current round\"\n );\n\n t.rewardCut = _rewardCut;\n t.feeShare = _feeShare;\n\n if (!transcoderPool.contains(msg.sender)) {\n tryToJoinActiveSet(\n msg.sender,\n delegators[msg.sender].delegatedAmount,\n currentRound.add(1),\n _newPosPrev,\n _newPosNext\n );\n }\n\n emit TranscoderUpdate(msg.sender, _rewardCut, _feeShare);\n }\n\n /**\n * @notice Delegates stake \"on behalf of\" another address towards a specific address\n * and updates the transcoder pool using optional list hints if needed\n * @dev If the caller is decreasing the stake of its old delegate in the transcoder pool, the caller can provide an optional hint\n * for the insertion position of the old delegate via the `_oldDelegateNewPosPrev` and `_oldDelegateNewPosNext` params.\n * If the caller is delegating to a delegate that is in the transcoder pool, the caller can provide an optional hint for the\n * insertion position of the delegate via the `_currDelegateNewPosPrev` and `_currDelegateNewPosNext` params.\n * In both cases, a linear search will be executed starting at the hint to find the correct position. In the best case, the hint\n * is the correct position so no search is executed. See SortedDoublyLL.sol for details on list hints\n * @param _amount The amount of tokens to stake.\n * @param _owner The address of the owner of the bond\n * @param _to The address of the transcoder to stake towards\n * @param _oldDelegateNewPosPrev The address of the previous transcoder in the pool for the old delegate\n * @param _oldDelegateNewPosNext The address of the next transcoder in the pool for the old delegate\n * @param _currDelegateNewPosPrev The address of the previous transcoder in the pool for the current delegate\n * @param _currDelegateNewPosNext The address of the next transcoder in the pool for the current delegate\n */\n function bondForWithHint(\n uint256 _amount,\n address _owner,\n address _to,\n address _oldDelegateNewPosPrev,\n address _oldDelegateNewPosNext,\n address _currDelegateNewPosPrev,\n address _currDelegateNewPosNext\n ) public whenSystemNotPaused currentRoundInitialized {\n // the `autoClaimEarnings` modifier has been replaced with its internal function as a `Stack too deep` error work-around\n _autoClaimEarnings(_owner);\n Delegator storage del = delegators[_owner];\n\n uint256 currentRound = roundsManager().currentRound();\n // Amount to delegate\n uint256 delegationAmount = _amount;\n // Current delegate\n address currentDelegate = del.delegateAddress;\n // Current bonded amount\n uint256 currentBondedAmount = del.bondedAmount;\n\n // Requirements for a third party caller that is not the L2Migrator\n if (msg.sender != _owner && msg.sender != l2Migrator()) {\n // Does not trigger self-delegation\n // Does not change the delegate if it is already non-null\n if (delegatorStatus(_owner) == DelegatorStatus.Unbonded) {\n require(_to != _owner, \"INVALID_DELEGATE\");\n } else {\n require(currentDelegate == _to, \"INVALID_DELEGATE_CHANGE\");\n }\n }\n\n if (delegatorStatus(_owner) == DelegatorStatus.Unbonded) {\n // New delegate\n // Set start round\n // Don't set start round if delegator is in pending state because the start round would not change\n del.startRound = currentRound.add(1);\n // Unbonded state = no existing delegate and no bonded stake\n // Thus, delegation amount = provided amount\n } else if (currentBondedAmount > 0 && currentDelegate != _to) {\n // A registered transcoder cannot delegate its bonded stake toward another address\n // because it can only be delegated toward itself\n // In the future, if delegation towards another registered transcoder as an already\n // registered transcoder becomes useful (i.e. for transitive delegation), this restriction\n // could be removed\n require(!isRegisteredTranscoder(_owner), \"registered transcoders can't delegate towards other addresses\");\n // Changing delegate\n // Set start round\n del.startRound = currentRound.add(1);\n // Update amount to delegate with previous delegation amount\n delegationAmount = delegationAmount.add(currentBondedAmount);\n\n decreaseTotalStake(currentDelegate, currentBondedAmount, _oldDelegateNewPosPrev, _oldDelegateNewPosNext);\n }\n\n {\n Transcoder storage newDelegate = transcoders[_to];\n EarningsPool.Data storage currPool = newDelegate.earningsPoolPerRound[currentRound];\n if (currPool.cumulativeRewardFactor == 0) {\n currPool.cumulativeRewardFactor = cumulativeFactorsPool(newDelegate, newDelegate.lastRewardRound)\n .cumulativeRewardFactor;\n }\n if (currPool.cumulativeFeeFactor == 0) {\n currPool.cumulativeFeeFactor = cumulativeFactorsPool(newDelegate, newDelegate.lastFeeRound)\n .cumulativeFeeFactor;\n }\n }\n\n // cannot delegate to someone without having bonded stake\n require(delegationAmount > 0, \"delegation amount must be greater than 0\");\n // Update delegate\n del.delegateAddress = _to;\n // Update bonded amount\n del.bondedAmount = currentBondedAmount.add(_amount);\n\n increaseTotalStake(_to, delegationAmount, _currDelegateNewPosPrev, _currDelegateNewPosNext);\n\n if (_amount > 0) {\n // Transfer the LPT to the Minter\n livepeerToken().transferFrom(msg.sender, address(minter()), _amount);\n }\n\n emit Bond(_to, currentDelegate, _owner, _amount, del.bondedAmount);\n }\n\n /**\n * @notice Delegates stake towards a specific address and updates the transcoder pool using optional list hints if needed\n * @dev If the caller is decreasing the stake of its old delegate in the transcoder pool, the caller can provide an optional hint\n * for the insertion position of the old delegate via the `_oldDelegateNewPosPrev` and `_oldDelegateNewPosNext` params.\n * If the caller is delegating to a delegate that is in the transcoder pool, the caller can provide an optional hint for the\n * insertion position of the delegate via the `_currDelegateNewPosPrev` and `_currDelegateNewPosNext` params.\n * In both cases, a linear search will be executed starting at the hint to find the correct position. In the best case, the hint\n * is the correct position so no search is executed. See SortedDoublyLL.sol for details on list hints\n * @param _amount The amount of tokens to stake.\n * @param _to The address of the transcoder to stake towards\n * @param _oldDelegateNewPosPrev The address of the previous transcoder in the pool for the old delegate\n * @param _oldDelegateNewPosNext The address of the next transcoder in the pool for the old delegate\n * @param _currDelegateNewPosPrev The address of the previous transcoder in the pool for the current delegate\n * @param _currDelegateNewPosNext The address of the next transcoder in the pool for the current delegate\n */\n function bondWithHint(\n uint256 _amount,\n address _to,\n address _oldDelegateNewPosPrev,\n address _oldDelegateNewPosNext,\n address _currDelegateNewPosPrev,\n address _currDelegateNewPosNext\n ) public {\n bondForWithHint(\n _amount,\n msg.sender,\n _to,\n _oldDelegateNewPosPrev,\n _oldDelegateNewPosNext,\n _currDelegateNewPosPrev,\n _currDelegateNewPosNext\n );\n }\n\n /**\n * @notice Transfers ownership of a bond to a new delegator using optional hints if needed\n *\n * If the receiver is already bonded to a different delegate than the bond owner then the stake goes\n * to the receiver's delegate otherwise the receiver's delegate is set as the owner's delegate\n *\n * @dev If the original delegate is in the transcoder pool, the caller can provide an optional hint for the\n * insertion position of the delegate via the `_oldDelegateNewPosPrev` and `_oldDelegateNewPosNext` params.\n * If the target delegate is in the transcoder pool, the caller can provide an optional hint for the\n * insertion position of the delegate via the `_newDelegateNewPosPrev` and `_newDelegateNewPosNext` params.\n *\n * In both cases, a linear search will be executed starting at the hint to find the correct position. In the best case, the hint\n * is the correct position so no search is executed. See SortedDoublyLL.sol for details on list hints\n * @param _delegator Receiver of the bond\n * @param _amount Portion of the bond to transfer to receiver\n * @param _oldDelegateNewPosPrev Address of previous transcoder in pool if the delegate remains in the pool\n * @param _oldDelegateNewPosNext Address of next transcoder in pool if the delegate remains in the pool\n * @param _newDelegateNewPosPrev Address of previous transcoder in pool if the delegate is in the pool\n * @param _newDelegateNewPosNext Address of next transcoder in pool if the delegate is in the pool\n */\n function transferBond(\n address _delegator,\n uint256 _amount,\n address _oldDelegateNewPosPrev,\n address _oldDelegateNewPosNext,\n address _newDelegateNewPosPrev,\n address _newDelegateNewPosNext\n ) public whenSystemNotPaused currentRoundInitialized {\n // the `autoClaimEarnings` modifier has been replaced with its internal function as a `Stack too deep` error work-around\n _autoClaimEarnings(msg.sender);\n Delegator storage oldDel = delegators[msg.sender];\n Delegator storage newDel = delegators[_delegator];\n // Cache delegate address of caller before unbondWithHint because\n // if unbondWithHint is for a full unbond the caller's delegate address will be set to null\n address oldDelDelegate = oldDel.delegateAddress;\n\n unbondWithHint(_amount, _oldDelegateNewPosPrev, _oldDelegateNewPosNext);\n\n uint256 oldDelUnbondingLockId = oldDel.nextUnbondingLockId.sub(1);\n uint256 withdrawRound = oldDel.unbondingLocks[oldDelUnbondingLockId].withdrawRound;\n\n // Burn lock for current owner\n delete oldDel.unbondingLocks[oldDelUnbondingLockId];\n\n // Create lock for new owner\n uint256 newDelUnbondingLockId = newDel.nextUnbondingLockId;\n\n newDel.unbondingLocks[newDelUnbondingLockId] = UnbondingLock({ amount: _amount, withdrawRound: withdrawRound });\n newDel.nextUnbondingLockId = newDel.nextUnbondingLockId.add(1);\n\n emit TransferBond(msg.sender, _delegator, oldDelUnbondingLockId, newDelUnbondingLockId, _amount);\n\n // Claim earnings for receiver before processing unbonding lock\n uint256 currentRound = roundsManager().currentRound();\n uint256 lastClaimRound = newDel.lastClaimRound;\n if (lastClaimRound < currentRound) {\n updateDelegatorWithEarnings(_delegator, currentRound, lastClaimRound);\n }\n\n // Rebond lock for new owner\n if (newDel.delegateAddress == address(0) && newDel.bondedAmount == 0) {\n // Requirements for caller\n // Does not trigger self-delegation\n require(oldDelDelegate != _delegator, \"INVALID_DELEGATOR\");\n\n newDel.delegateAddress = oldDelDelegate;\n }\n\n // Move to Pending state if receiver is currently in Unbonded state\n if (delegatorStatus(_delegator) == DelegatorStatus.Unbonded) {\n newDel.startRound = currentRound.add(1);\n }\n\n // Process rebond using unbonding lock\n processRebond(_delegator, newDelUnbondingLockId, _newDelegateNewPosPrev, _newDelegateNewPosNext);\n }\n\n /**\n * @notice Unbond an amount of the delegator's bonded stake and updates the transcoder pool using an optional list hint if needed\n * @dev If the caller remains in the transcoder pool, the caller can provide an optional hint for its insertion position in the\n * pool via the `_newPosPrev` and `_newPosNext` params. A linear search will be executed starting at the hint to find the correct position.\n * In the best case, the hint is the correct position so no search is executed. See SortedDoublyLL.sol details on list hints\n * @param _amount Amount of tokens to unbond\n * @param _newPosPrev Address of previous transcoder in pool if the caller remains in the pool\n * @param _newPosNext Address of next transcoder in pool if the caller remains in the pool\n */\n function unbondWithHint(\n uint256 _amount,\n address _newPosPrev,\n address _newPosNext\n ) public whenSystemNotPaused currentRoundInitialized autoClaimEarnings(msg.sender) {\n require(delegatorStatus(msg.sender) == DelegatorStatus.Bonded, \"caller must be bonded\");\n\n Delegator storage del = delegators[msg.sender];\n\n require(_amount > 0, \"unbond amount must be greater than 0\");\n require(_amount <= del.bondedAmount, \"amount is greater than bonded amount\");\n\n address currentDelegate = del.delegateAddress;\n uint256 currentRound = roundsManager().currentRound();\n uint256 withdrawRound = currentRound.add(unbondingPeriod);\n uint256 unbondingLockId = del.nextUnbondingLockId;\n\n // Create new unbonding lock\n del.unbondingLocks[unbondingLockId] = UnbondingLock({ amount: _amount, withdrawRound: withdrawRound });\n // Increment ID for next unbonding lock\n del.nextUnbondingLockId = unbondingLockId.add(1);\n // Decrease delegator's bonded amount\n del.bondedAmount = del.bondedAmount.sub(_amount);\n\n if (del.bondedAmount == 0) {\n // Delegator no longer delegated to anyone if it does not have a bonded amount\n del.delegateAddress = address(0);\n // Delegator does not have a start round if it is no longer delegated to anyone\n del.startRound = 0;\n\n if (transcoderPool.contains(msg.sender)) {\n resignTranscoder(msg.sender);\n }\n }\n\n // If msg.sender was resigned this statement will only decrease delegators[currentDelegate].delegatedAmount\n decreaseTotalStake(currentDelegate, _amount, _newPosPrev, _newPosNext);\n\n emit Unbond(currentDelegate, msg.sender, unbondingLockId, _amount, withdrawRound);\n }\n\n /**\n * @notice Rebond tokens for an unbonding lock to a delegator's current delegate while a delegator is in the Bonded or Pending status and updates\n * the transcoder pool using an optional list hint if needed\n * @dev If the delegate is in the transcoder pool, the caller can provide an optional hint for the delegate's insertion position in the\n * pool via the `_newPosPrev` and `_newPosNext` params. A linear search will be executed starting at the hint to find the correct position.\n * In the best case, the hint is the correct position so no search is executed. See SortedDoublyLL.sol details on list hints\n * @param _unbondingLockId ID of unbonding lock to rebond with\n * @param _newPosPrev Address of previous transcoder in pool if the delegate is in the pool\n * @param _newPosNext Address of next transcoder in pool if the delegate is in the pool\n */\n function rebondWithHint(\n uint256 _unbondingLockId,\n address _newPosPrev,\n address _newPosNext\n ) public whenSystemNotPaused currentRoundInitialized autoClaimEarnings(msg.sender) {\n require(delegatorStatus(msg.sender) != DelegatorStatus.Unbonded, \"caller must be bonded\");\n\n // Process rebond using unbonding lock\n processRebond(msg.sender, _unbondingLockId, _newPosPrev, _newPosNext);\n }\n\n /**\n * @notice Rebond tokens for an unbonding lock to a delegate while a delegator is in the Unbonded status and updates the transcoder pool using\n * an optional list hint if needed\n * @dev If the delegate joins the transcoder pool, the caller can provide an optional hint for the delegate's insertion position in the\n * pool via the `_newPosPrev` and `_newPosNext` params. A linear search will be executed starting at the hint to find the correct position.\n * In the best case, the hint is the correct position so no search is executed. See SortedDoublyLL.sol for details on list hints\n * @param _to Address of delegate\n * @param _unbondingLockId ID of unbonding lock to rebond with\n * @param _newPosPrev Address of previous transcoder in pool if the delegate joins the pool\n * @param _newPosNext Address of next transcoder in pool if the delegate joins the pool\n */\n function rebondFromUnbondedWithHint(\n address _to,\n uint256 _unbondingLockId,\n address _newPosPrev,\n address _newPosNext\n ) public whenSystemNotPaused currentRoundInitialized autoClaimEarnings(msg.sender) {\n require(delegatorStatus(msg.sender) == DelegatorStatus.Unbonded, \"caller must be unbonded\");\n\n // Set delegator's start round and transition into Pending state\n delegators[msg.sender].startRound = roundsManager().currentRound().add(1);\n // Set delegator's delegate\n delegators[msg.sender].delegateAddress = _to;\n // Process rebond using unbonding lock\n processRebond(msg.sender, _unbondingLockId, _newPosPrev, _newPosNext);\n }\n\n /**\n * @notice Mint token rewards for an active transcoder and its delegators and update the transcoder pool using an optional list hint if needed\n * @dev If the caller is in the transcoder pool, the caller can provide an optional hint for its insertion position in the\n * pool via the `_newPosPrev` and `_newPosNext` params. A linear search will be executed starting at the hint to find the correct position.\n * In the best case, the hint is the correct position so no search is executed. See SortedDoublyLL.sol for details on list hints\n * @param _newPosPrev Address of previous transcoder in pool if the caller is in the pool\n * @param _newPosNext Address of next transcoder in pool if the caller is in the pool\n */\n function rewardWithHint(address _newPosPrev, address _newPosNext)\n public\n whenSystemNotPaused\n currentRoundInitialized\n {\n uint256 currentRound = roundsManager().currentRound();\n\n require(isActiveTranscoder(msg.sender), \"caller must be an active transcoder\");\n require(\n transcoders[msg.sender].lastRewardRound != currentRound,\n \"caller has already called reward for the current round\"\n );\n\n Transcoder storage t = transcoders[msg.sender];\n EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[currentRound];\n\n // Set last round that transcoder called reward\n earningsPool.setCommission(t.rewardCut, t.feeShare);\n\n // If transcoder didn't receive stake updates during the previous round and hasn't called reward for > 1 round\n // the 'totalStake' on its 'EarningsPool' for the current round wouldn't be initialized\n // Thus we sync the the transcoder's stake to when it was last updated\n // 'updateTrancoderWithRewards()' will set the update round to 'currentRound +1' so this synchronization shouldn't occur frequently\n uint256 lastUpdateRound = t.lastActiveStakeUpdateRound;\n if (lastUpdateRound < currentRound) {\n earningsPool.setStake(t.earningsPoolPerRound[lastUpdateRound].totalStake);\n }\n\n // Create reward based on active transcoder's stake relative to the total active stake\n // rewardTokens = (current mintable tokens for the round * active transcoder stake) / total active stake\n uint256 rewardTokens = minter().createReward(earningsPool.totalStake, currentRoundTotalActiveStake);\n\n updateTranscoderWithRewards(msg.sender, rewardTokens, currentRound, _newPosPrev, _newPosNext);\n\n // Set last round that transcoder called reward\n t.lastRewardRound = currentRound;\n\n emit Reward(msg.sender, rewardTokens);\n }\n\n /**\n * @notice Returns pending bonded stake for a delegator from its lastClaimRound through an end round\n * @param _delegator Address of delegator\n * @param _endRound The last round to compute pending stake from\n * @return Pending bonded stake for '_delegator' since last claiming rewards\n */\n function pendingStake(address _delegator, uint256 _endRound) public view returns (uint256) {\n // Silence unused param compiler warning\n _endRound;\n\n uint256 endRound = roundsManager().currentRound();\n (uint256 stake, ) = pendingStakeAndFees(_delegator, endRound);\n return stake;\n }\n\n /**\n * @notice Returns pending fees for a delegator from its lastClaimRound through an end round\n * @param _delegator Address of delegator\n * @param _endRound The last round to compute pending fees from\n * @return Pending fees for '_delegator' since last claiming fees\n */\n function pendingFees(address _delegator, uint256 _endRound) public view returns (uint256) {\n // Silence unused param compiler warning\n _endRound;\n\n uint256 endRound = roundsManager().currentRound();\n (, uint256 fees) = pendingStakeAndFees(_delegator, endRound);\n return fees;\n }\n\n /**\n * @notice Returns total bonded stake for a transcoder\n * @param _transcoder Address of transcoder\n * @return total bonded stake for a delegator\n */\n function transcoderTotalStake(address _transcoder) public view returns (uint256) {\n return delegators[_transcoder].delegatedAmount;\n }\n\n /**\n * @notice Computes transcoder status\n * @param _transcoder Address of transcoder\n * @return registered or not registered transcoder status\n */\n function transcoderStatus(address _transcoder) public view returns (TranscoderStatus) {\n if (isRegisteredTranscoder(_transcoder)) return TranscoderStatus.Registered;\n return TranscoderStatus.NotRegistered;\n }\n\n /**\n * @notice Computes delegator status\n * @param _delegator Address of delegator\n * @return bonded, unbonded or pending delegator status\n */\n function delegatorStatus(address _delegator) public view returns (DelegatorStatus) {\n Delegator storage del = delegators[_delegator];\n\n if (del.bondedAmount == 0) {\n // Delegator unbonded all its tokens\n return DelegatorStatus.Unbonded;\n } else if (del.startRound > roundsManager().currentRound()) {\n // Delegator round start is in the future\n return DelegatorStatus.Pending;\n } else {\n // Delegator round start is now or in the past\n // del.startRound != 0 here because if del.startRound = 0 then del.bondedAmount = 0 which\n // would trigger the first if clause\n return DelegatorStatus.Bonded;\n }\n }\n\n /**\n * @notice Return transcoder information\n * @param _transcoder Address of transcoder\n * @return lastRewardRound Trancoder's last reward round\n * @return rewardCut Transcoder's reward cut\n * @return feeShare Transcoder's fee share\n * @return lastActiveStakeUpdateRound Round in which transcoder's stake was last updated while active\n * @return activationRound Round in which transcoder became active\n * @return deactivationRound Round in which transcoder will no longer be active\n * @return activeCumulativeRewards Transcoder's cumulative rewards that are currently active\n * @return cumulativeRewards Transcoder's cumulative rewards (earned via its active staked rewards and its reward cut)\n * @return cumulativeFees Transcoder's cumulative fees (earned via its active staked rewards and its fee share)\n * @return lastFeeRound Latest round that the transcoder received fees\n */\n function getTranscoder(address _transcoder)\n public\n view\n returns (\n uint256 lastRewardRound,\n uint256 rewardCut,\n uint256 feeShare,\n uint256 lastActiveStakeUpdateRound,\n uint256 activationRound,\n uint256 deactivationRound,\n uint256 activeCumulativeRewards,\n uint256 cumulativeRewards,\n uint256 cumulativeFees,\n uint256 lastFeeRound\n )\n {\n Transcoder storage t = transcoders[_transcoder];\n\n lastRewardRound = t.lastRewardRound;\n rewardCut = t.rewardCut;\n feeShare = t.feeShare;\n lastActiveStakeUpdateRound = t.lastActiveStakeUpdateRound;\n activationRound = t.activationRound;\n deactivationRound = t.deactivationRound;\n activeCumulativeRewards = t.activeCumulativeRewards;\n cumulativeRewards = t.cumulativeRewards;\n cumulativeFees = t.cumulativeFees;\n lastFeeRound = t.lastFeeRound;\n }\n\n /**\n * @notice Return transcoder's earnings pool for a given round\n * @param _transcoder Address of transcoder\n * @param _round Round number\n * @return totalStake Transcoder's total stake in '_round'\n * @return transcoderRewardCut Transcoder's reward cut for '_round'\n * @return transcoderFeeShare Transcoder's fee share for '_round'\n * @return cumulativeRewardFactor The cumulative reward factor for delegator rewards calculation (only used after LIP-36)\n * @return cumulativeFeeFactor The cumulative fee factor for delegator fees calculation (only used after LIP-36)\n */\n function getTranscoderEarningsPoolForRound(address _transcoder, uint256 _round)\n public\n view\n returns (\n uint256 totalStake,\n uint256 transcoderRewardCut,\n uint256 transcoderFeeShare,\n uint256 cumulativeRewardFactor,\n uint256 cumulativeFeeFactor\n )\n {\n EarningsPool.Data storage earningsPool = transcoders[_transcoder].earningsPoolPerRound[_round];\n\n totalStake = earningsPool.totalStake;\n transcoderRewardCut = earningsPool.transcoderRewardCut;\n transcoderFeeShare = earningsPool.transcoderFeeShare;\n cumulativeRewardFactor = earningsPool.cumulativeRewardFactor;\n cumulativeFeeFactor = earningsPool.cumulativeFeeFactor;\n }\n\n /**\n * @notice Return delegator info\n * @param _delegator Address of delegator\n * @return bondedAmount total amount bonded by '_delegator'\n * @return fees amount of fees collected by '_delegator'\n * @return delegateAddress address '_delegator' has bonded to\n * @return delegatedAmount total amount delegated to '_delegator'\n * @return startRound round in which bond for '_delegator' became effective\n * @return lastClaimRound round for which '_delegator' has last claimed earnings\n * @return nextUnbondingLockId ID for the next unbonding lock created for '_delegator'\n */\n function getDelegator(address _delegator)\n public\n view\n returns (\n uint256 bondedAmount,\n uint256 fees,\n address delegateAddress,\n uint256 delegatedAmount,\n uint256 startRound,\n uint256 lastClaimRound,\n uint256 nextUnbondingLockId\n )\n {\n Delegator storage del = delegators[_delegator];\n\n bondedAmount = del.bondedAmount;\n fees = del.fees;\n delegateAddress = del.delegateAddress;\n delegatedAmount = del.delegatedAmount;\n startRound = del.startRound;\n lastClaimRound = del.lastClaimRound;\n nextUnbondingLockId = del.nextUnbondingLockId;\n }\n\n /**\n * @notice Return delegator's unbonding lock info\n * @param _delegator Address of delegator\n * @param _unbondingLockId ID of unbonding lock\n * @return amount of stake locked up by unbonding lock\n * @return withdrawRound round in which 'amount' becomes available for withdrawal\n */\n function getDelegatorUnbondingLock(address _delegator, uint256 _unbondingLockId)\n public\n view\n returns (uint256 amount, uint256 withdrawRound)\n {\n UnbondingLock storage lock = delegators[_delegator].unbondingLocks[_unbondingLockId];\n\n return (lock.amount, lock.withdrawRound);\n }\n\n /**\n * @notice Returns max size of transcoder pool\n * @return transcoder pool max size\n */\n function getTranscoderPoolMaxSize() public view returns (uint256) {\n return transcoderPool.getMaxSize();\n }\n\n /**\n * @notice Returns size of transcoder pool\n * @return transcoder pool current size\n */\n function getTranscoderPoolSize() public view returns (uint256) {\n return transcoderPool.getSize();\n }\n\n /**\n * @notice Returns transcoder with most stake in pool\n * @return address for transcoder with highest stake in transcoder pool\n */\n function getFirstTranscoderInPool() public view returns (address) {\n return transcoderPool.getFirst();\n }\n\n /**\n * @notice Returns next transcoder in pool for a given transcoder\n * @param _transcoder Address of a transcoder in the pool\n * @return address for the transcoder after '_transcoder' in transcoder pool\n */\n function getNextTranscoderInPool(address _transcoder) public view returns (address) {\n return transcoderPool.getNext(_transcoder);\n }\n\n /**\n * @notice Return total bonded tokens\n * @return total active stake for the current round\n */\n function getTotalBonded() public view returns (uint256) {\n return currentRoundTotalActiveStake;\n }\n\n /**\n * @notice Return whether a transcoder is active for the current round\n * @param _transcoder Transcoder address\n * @return true if transcoder is active\n */\n function isActiveTranscoder(address _transcoder) public view returns (bool) {\n Transcoder storage t = transcoders[_transcoder];\n uint256 currentRound = roundsManager().currentRound();\n return t.activationRound <= currentRound && currentRound < t.deactivationRound;\n }\n\n /**\n * @notice Return whether a transcoder is registered\n * @param _transcoder Transcoder address\n * @return true if transcoder is self-bonded\n */\n function isRegisteredTranscoder(address _transcoder) public view returns (bool) {\n Delegator storage d = delegators[_transcoder];\n return d.delegateAddress == _transcoder && d.bondedAmount > 0;\n }\n\n /**\n * @notice Return whether an unbonding lock for a delegator is valid\n * @param _delegator Address of delegator\n * @param _unbondingLockId ID of unbonding lock\n * @return true if unbondingLock for ID has a non-zero withdraw round\n */\n function isValidUnbondingLock(address _delegator, uint256 _unbondingLockId) public view returns (bool) {\n // A unbonding lock is only valid if it has a non-zero withdraw round (the default value is zero)\n return delegators[_delegator].unbondingLocks[_unbondingLockId].withdrawRound > 0;\n }\n\n /**\n * @notice Return an EarningsPool.Data struct with cumulative factors for a given round that are rescaled if needed\n * @param _transcoder Storage pointer to a transcoder struct\n * @param _round The round to fetch the cumulative factors for\n */\n function cumulativeFactorsPool(Transcoder storage _transcoder, uint256 _round)\n internal\n view\n returns (EarningsPool.Data memory pool)\n {\n pool.cumulativeRewardFactor = _transcoder.earningsPoolPerRound[_round].cumulativeRewardFactor;\n pool.cumulativeFeeFactor = _transcoder.earningsPoolPerRound[_round].cumulativeFeeFactor;\n\n return pool;\n }\n\n /**\n * @notice Return an EarningsPool.Data struct with the latest cumulative factors for a given round\n * @param _transcoder Storage pointer to a transcoder struct\n * @param _round The round to fetch the latest cumulative factors for\n * @return pool An EarningsPool.Data populated with the latest cumulative factors for _round\n */\n function latestCumulativeFactorsPool(Transcoder storage _transcoder, uint256 _round)\n internal\n view\n returns (EarningsPool.Data memory pool)\n {\n pool = cumulativeFactorsPool(_transcoder, _round);\n\n uint256 lastRewardRound = _transcoder.lastRewardRound;\n // Only use the cumulativeRewardFactor for lastRewardRound if lastRewardRound is before _round\n if (pool.cumulativeRewardFactor == 0 && lastRewardRound < _round) {\n pool.cumulativeRewardFactor = cumulativeFactorsPool(_transcoder, lastRewardRound).cumulativeRewardFactor;\n }\n\n uint256 lastFeeRound = _transcoder.lastFeeRound;\n // Only use the cumulativeFeeFactor for lastFeeRound if lastFeeRound is before _round\n if (pool.cumulativeFeeFactor == 0 && lastFeeRound < _round) {\n pool.cumulativeFeeFactor = cumulativeFactorsPool(_transcoder, lastFeeRound).cumulativeFeeFactor;\n }\n\n return pool;\n }\n\n /**\n * @notice Return a delegator's cumulative stake and fees using the LIP-36 earnings claiming algorithm\n * @param _transcoder Storage pointer to a transcoder struct for a delegator's delegate\n * @param _startRound The round for the start cumulative factors\n * @param _endRound The round for the end cumulative factors\n * @param _stake The delegator's initial stake before including earned rewards\n * @param _fees The delegator's initial fees before including earned fees\n * @return cStake , cFees where cStake is the delegator's cumulative stake including earned rewards and cFees is the delegator's cumulative fees including earned fees\n */\n function delegatorCumulativeStakeAndFees(\n Transcoder storage _transcoder,\n uint256 _startRound,\n uint256 _endRound,\n uint256 _stake,\n uint256 _fees\n ) internal view returns (uint256 cStake, uint256 cFees) {\n // Fetch start cumulative factors\n EarningsPool.Data memory startPool = cumulativeFactorsPool(_transcoder, _startRound);\n\n // If the start cumulativeRewardFactor is 0 set the default value to PreciseMathUtils.percPoints(1, 1)\n if (startPool.cumulativeRewardFactor == 0) {\n startPool.cumulativeRewardFactor = PreciseMathUtils.percPoints(1, 1);\n }\n\n // Fetch end cumulative factors\n EarningsPool.Data memory endPool = latestCumulativeFactorsPool(_transcoder, _endRound);\n\n // If the end cumulativeRewardFactor is 0 set the default value to PreciseMathUtils.percPoints(1, 1)\n if (endPool.cumulativeRewardFactor == 0) {\n endPool.cumulativeRewardFactor = PreciseMathUtils.percPoints(1, 1);\n }\n\n cFees = _fees.add(\n PreciseMathUtils.percOf(\n _stake,\n endPool.cumulativeFeeFactor.sub(startPool.cumulativeFeeFactor),\n startPool.cumulativeRewardFactor\n )\n );\n\n cStake = PreciseMathUtils.percOf(_stake, endPool.cumulativeRewardFactor, startPool.cumulativeRewardFactor);\n\n return (cStake, cFees);\n }\n\n /**\n * @notice Return the pending stake and fees for a delegator\n * @param _delegator Address of a delegator\n * @param _endRound The last round to claim earnings for when calculating the pending stake and fees\n * @return stake , fees where stake is the delegator's pending stake and fees is the delegator's pending fees\n */\n function pendingStakeAndFees(address _delegator, uint256 _endRound)\n internal\n view\n returns (uint256 stake, uint256 fees)\n {\n Delegator storage del = delegators[_delegator];\n Transcoder storage t = transcoders[del.delegateAddress];\n\n fees = del.fees;\n stake = del.bondedAmount;\n\n uint256 startRound = del.lastClaimRound.add(1);\n address delegateAddr = del.delegateAddress;\n bool isTranscoder = _delegator == delegateAddr;\n\n // Make sure there is a round to claim i.e. end round - (start round - 1) > 0\n if (startRound <= _endRound) {\n (stake, fees) = delegatorCumulativeStakeAndFees(t, startRound.sub(1), _endRound, stake, fees);\n }\n // cumulativeRewards and cumulativeFees will track *all* rewards/fees earned by the transcoder\n // so it is important that this is only executed with the end round as the current round or else\n // the returned stake and fees will reflect rewards/fees earned in the future relative to the end round\n if (isTranscoder) {\n stake = stake.add(t.cumulativeRewards);\n fees = fees.add(t.cumulativeFees);\n }\n\n return (stake, fees);\n }\n\n /**\n * @dev Increase the total stake for a delegate and updates its 'lastActiveStakeUpdateRound'\n * @param _delegate The delegate to increase the stake for\n * @param _amount The amount to increase the stake for '_delegate' by\n */\n function increaseTotalStake(\n address _delegate,\n uint256 _amount,\n address _newPosPrev,\n address _newPosNext\n ) internal {\n if (isRegisteredTranscoder(_delegate)) {\n uint256 currStake = transcoderTotalStake(_delegate);\n uint256 newStake = currStake.add(_amount);\n uint256 currRound = roundsManager().currentRound();\n uint256 nextRound = currRound.add(1);\n\n // If the transcoder is already in the active set update its stake and return\n if (transcoderPool.contains(_delegate)) {\n transcoderPool.updateKey(_delegate, newStake, _newPosPrev, _newPosNext);\n nextRoundTotalActiveStake = nextRoundTotalActiveStake.add(_amount);\n Transcoder storage t = transcoders[_delegate];\n\n // currStake (the transcoder's delegatedAmount field) will reflect the transcoder's stake from lastActiveStakeUpdateRound\n // because it is updated every time lastActiveStakeUpdateRound is updated\n // The current active total stake is set to currStake to ensure that the value can be used in updateTranscoderWithRewards()\n // and updateTranscoderWithFees() when lastActiveStakeUpdateRound > currentRound\n if (t.lastActiveStakeUpdateRound < currRound) {\n t.earningsPoolPerRound[currRound].setStake(currStake);\n }\n\n t.earningsPoolPerRound[nextRound].setStake(newStake);\n t.lastActiveStakeUpdateRound = nextRound;\n } else {\n // Check if the transcoder is eligible to join the active set in the update round\n tryToJoinActiveSet(_delegate, newStake, nextRound, _newPosPrev, _newPosNext);\n }\n }\n\n // Increase delegate's delegated amount\n delegators[_delegate].delegatedAmount = delegators[_delegate].delegatedAmount.add(_amount);\n }\n\n /**\n * @dev Decrease the total stake for a delegate and updates its 'lastActiveStakeUpdateRound'\n * @param _delegate The transcoder to decrease the stake for\n * @param _amount The amount to decrease the stake for '_delegate' by\n */\n function decreaseTotalStake(\n address _delegate,\n uint256 _amount,\n address _newPosPrev,\n address _newPosNext\n ) internal {\n if (transcoderPool.contains(_delegate)) {\n uint256 currStake = transcoderTotalStake(_delegate);\n uint256 newStake = currStake.sub(_amount);\n uint256 currRound = roundsManager().currentRound();\n uint256 nextRound = currRound.add(1);\n\n transcoderPool.updateKey(_delegate, newStake, _newPosPrev, _newPosNext);\n nextRoundTotalActiveStake = nextRoundTotalActiveStake.sub(_amount);\n Transcoder storage t = transcoders[_delegate];\n\n // currStake (the transcoder's delegatedAmount field) will reflect the transcoder's stake from lastActiveStakeUpdateRound\n // because it is updated every time lastActiveStakeUpdateRound is updated\n // The current active total stake is set to currStake to ensure that the value can be used in updateTranscoderWithRewards()\n // and updateTranscoderWithFees() when lastActiveStakeUpdateRound > currentRound\n if (t.lastActiveStakeUpdateRound < currRound) {\n t.earningsPoolPerRound[currRound].setStake(currStake);\n }\n\n t.lastActiveStakeUpdateRound = nextRound;\n t.earningsPoolPerRound[nextRound].setStake(newStake);\n }\n\n // Decrease old delegate's delegated amount\n delegators[_delegate].delegatedAmount = delegators[_delegate].delegatedAmount.sub(_amount);\n }\n\n /**\n * @dev Tries to add a transcoder to active transcoder pool, evicts the active transcoder with the lowest stake if the pool is full\n * @param _transcoder The transcoder to insert into the transcoder pool\n * @param _totalStake The total stake for '_transcoder'\n * @param _activationRound The round in which the transcoder should become active\n */\n function tryToJoinActiveSet(\n address _transcoder,\n uint256 _totalStake,\n uint256 _activationRound,\n address _newPosPrev,\n address _newPosNext\n ) internal {\n uint256 pendingNextRoundTotalActiveStake = nextRoundTotalActiveStake;\n\n if (transcoderPool.isFull()) {\n address lastTranscoder = transcoderPool.getLast();\n uint256 lastStake = transcoderTotalStake(lastTranscoder);\n\n // If the pool is full and the transcoder has less stake than the least stake transcoder in the pool\n // then the transcoder is unable to join the active set for the next round\n if (_totalStake <= lastStake) {\n return;\n }\n\n // Evict the least stake transcoder from the active set for the next round\n // Not zeroing 'Transcoder.lastActiveStakeUpdateRound' saves gas (5k when transcoder is evicted and 20k when transcoder is reinserted)\n // There should be no side-effects as long as the value is properly updated on stake updates\n // Not zeroing the stake on the current round's 'EarningsPool' saves gas and should have no side effects as long as\n // 'EarningsPool.setStake()' is called whenever a transcoder becomes active again.\n transcoderPool.remove(lastTranscoder);\n transcoders[lastTranscoder].deactivationRound = _activationRound;\n pendingNextRoundTotalActiveStake = pendingNextRoundTotalActiveStake.sub(lastStake);\n\n emit TranscoderDeactivated(lastTranscoder, _activationRound);\n }\n\n transcoderPool.insert(_transcoder, _totalStake, _newPosPrev, _newPosNext);\n pendingNextRoundTotalActiveStake = pendingNextRoundTotalActiveStake.add(_totalStake);\n Transcoder storage t = transcoders[_transcoder];\n t.lastActiveStakeUpdateRound = _activationRound;\n t.activationRound = _activationRound;\n t.deactivationRound = MAX_FUTURE_ROUND;\n t.earningsPoolPerRound[_activationRound].setStake(_totalStake);\n nextRoundTotalActiveStake = pendingNextRoundTotalActiveStake;\n emit TranscoderActivated(_transcoder, _activationRound);\n }\n\n /**\n * @dev Remove a transcoder from the pool and deactivate it\n */\n function resignTranscoder(address _transcoder) internal {\n // Not zeroing 'Transcoder.lastActiveStakeUpdateRound' saves gas (5k when transcoder is evicted and 20k when transcoder is reinserted)\n // There should be no side-effects as long as the value is properly updated on stake updates\n // Not zeroing the stake on the current round's 'EarningsPool' saves gas and should have no side effects as long as\n // 'EarningsPool.setStake()' is called whenever a transcoder becomes active again.\n transcoderPool.remove(_transcoder);\n nextRoundTotalActiveStake = nextRoundTotalActiveStake.sub(transcoderTotalStake(_transcoder));\n uint256 deactivationRound = roundsManager().currentRound().add(1);\n transcoders[_transcoder].deactivationRound = deactivationRound;\n emit TranscoderDeactivated(_transcoder, deactivationRound);\n }\n\n /**\n * @dev Update a transcoder with rewards and update the transcoder pool with an optional list hint if needed.\n * See SortedDoublyLL.sol for details on list hints\n * @param _transcoder Address of transcoder\n * @param _rewards Amount of rewards\n * @param _round Round that transcoder is updated\n * @param _newPosPrev Address of previous transcoder in pool if the transcoder is in the pool\n * @param _newPosNext Address of next transcoder in pool if the transcoder is in the pool\n */\n function updateTranscoderWithRewards(\n address _transcoder,\n uint256 _rewards,\n uint256 _round,\n address _newPosPrev,\n address _newPosNext\n ) internal {\n Transcoder storage t = transcoders[_transcoder];\n EarningsPool.Data storage earningsPool = t.earningsPoolPerRound[_round];\n EarningsPool.Data memory prevEarningsPool = cumulativeFactorsPool(t, t.lastRewardRound);\n\n t.activeCumulativeRewards = t.cumulativeRewards;\n\n uint256 transcoderCommissionRewards = MathUtils.percOf(_rewards, earningsPool.transcoderRewardCut);\n uint256 delegatorsRewards = _rewards.sub(transcoderCommissionRewards);\n // Calculate the rewards earned by the transcoder's earned rewards\n uint256 transcoderRewardStakeRewards = PreciseMathUtils.percOf(\n delegatorsRewards,\n t.activeCumulativeRewards,\n earningsPool.totalStake\n );\n // Track rewards earned by the transcoder based on its earned rewards and rewardCut\n t.cumulativeRewards = t.cumulativeRewards.add(transcoderRewardStakeRewards).add(transcoderCommissionRewards);\n // Update cumulative reward factor with new rewards\n // The cumulativeRewardFactor is used to calculate rewards for all delegators including the transcoder (self-delegated)\n // Note that delegatorsRewards includes transcoderRewardStakeRewards, but no delegator will claim that amount using\n // the earnings claiming algorithm and instead that amount is accounted for in the transcoder's cumulativeRewards field\n earningsPool.updateCumulativeRewardFactor(prevEarningsPool, delegatorsRewards);\n // Update transcoder's total stake with rewards\n increaseTotalStake(_transcoder, _rewards, _newPosPrev, _newPosNext);\n }\n\n /**\n * @dev Update a delegator with token pools shares from its lastClaimRound through a given round\n * @param _delegator Delegator address\n * @param _endRound The last round for which to update a delegator's stake with earnings pool shares\n * @param _lastClaimRound The round for which a delegator has last claimed earnings\n */\n function updateDelegatorWithEarnings(\n address _delegator,\n uint256 _endRound,\n uint256 _lastClaimRound\n ) internal {\n Delegator storage del = delegators[_delegator];\n uint256 startRound = _lastClaimRound.add(1);\n uint256 currentBondedAmount = del.bondedAmount;\n uint256 currentFees = del.fees;\n\n // Only will have earnings to claim if you have a delegate\n // If not delegated, skip the earnings claim process\n if (del.delegateAddress != address(0)) {\n (currentBondedAmount, currentFees) = pendingStakeAndFees(_delegator, _endRound);\n\n // Check whether the endEarningsPool is initialised\n // If it is not initialised set it's cumulative factors so that they can be used when a delegator\n // next claims earnings as the start cumulative factors (see delegatorCumulativeStakeAndFees())\n Transcoder storage t = transcoders[del.delegateAddress];\n EarningsPool.Data storage endEarningsPool = t.earningsPoolPerRound[_endRound];\n if (endEarningsPool.cumulativeRewardFactor == 0) {\n uint256 lastRewardRound = t.lastRewardRound;\n if (lastRewardRound < _endRound) {\n endEarningsPool.cumulativeRewardFactor = cumulativeFactorsPool(t, lastRewardRound)\n .cumulativeRewardFactor;\n }\n }\n if (endEarningsPool.cumulativeFeeFactor == 0) {\n uint256 lastFeeRound = t.lastFeeRound;\n if (lastFeeRound < _endRound) {\n endEarningsPool.cumulativeFeeFactor = cumulativeFactorsPool(t, lastFeeRound).cumulativeFeeFactor;\n }\n }\n\n if (del.delegateAddress == _delegator) {\n t.cumulativeFees = 0;\n t.cumulativeRewards = 0;\n // activeCumulativeRewards is not cleared here because the next reward() call will set it to cumulativeRewards\n }\n }\n\n emit EarningsClaimed(\n del.delegateAddress,\n _delegator,\n currentBondedAmount.sub(del.bondedAmount),\n currentFees.sub(del.fees),\n startRound,\n _endRound\n );\n\n del.lastClaimRound = _endRound;\n // Rewards are bonded by default\n del.bondedAmount = currentBondedAmount;\n del.fees = currentFees;\n }\n\n /**\n * @dev Update the state of a delegator and its delegate by processing a rebond using an unbonding lock and update the transcoder pool with an optional\n * list hint if needed. See SortedDoublyLL.sol for details on list hints\n * @param _delegator Address of delegator\n * @param _unbondingLockId ID of unbonding lock to rebond with\n * @param _newPosPrev Address of previous transcoder in pool if the delegate is already in or joins the pool\n * @param _newPosNext Address of next transcoder in pool if the delegate is already in or joins the pool\n */\n function processRebond(\n address _delegator,\n uint256 _unbondingLockId,\n address _newPosPrev,\n address _newPosNext\n ) internal {\n Delegator storage del = delegators[_delegator];\n UnbondingLock storage lock = del.unbondingLocks[_unbondingLockId];\n\n require(isValidUnbondingLock(_delegator, _unbondingLockId), \"invalid unbonding lock ID\");\n\n uint256 amount = lock.amount;\n // Increase delegator's bonded amount\n del.bondedAmount = del.bondedAmount.add(amount);\n\n // Delete lock\n delete del.unbondingLocks[_unbondingLockId];\n\n increaseTotalStake(del.delegateAddress, amount, _newPosPrev, _newPosNext);\n\n emit Rebond(del.delegateAddress, _delegator, _unbondingLockId, amount);\n }\n\n /**\n * @dev Return LivepeerToken interface\n * @return Livepeer token contract registered with Controller\n */\n function livepeerToken() internal view returns (ILivepeerToken) {\n return ILivepeerToken(controller.getContract(keccak256(\"LivepeerToken\")));\n }\n\n /**\n * @dev Return Minter interface\n * @return Minter contract registered with Controller\n */\n function minter() internal view returns (IMinter) {\n return IMinter(controller.getContract(keccak256(\"Minter\")));\n }\n\n /**\n * @dev Return Address of L2Migrator\n * @return l2Migrator contract address registered with Controller\n */\n function l2Migrator() internal view returns (address) {\n return controller.getContract(keccak256(\"L2Migrator\"));\n }\n\n /**\n * @dev Return RoundsManager interface\n * @return RoundsManager contract registered with Controller\n */\n function roundsManager() internal view returns (IRoundsManager) {\n return IRoundsManager(controller.getContract(keccak256(\"RoundsManager\")));\n }\n\n function _onlyTicketBroker() internal view {\n require(msg.sender == controller.getContract(keccak256(\"TicketBroker\")), \"caller must be TicketBroker\");\n }\n\n function _onlyRoundsManager() internal view {\n require(msg.sender == controller.getContract(keccak256(\"RoundsManager\")), \"caller must be RoundsManager\");\n }\n\n function _onlyVerifier() internal view {\n require(msg.sender == controller.getContract(keccak256(\"Verifier\")), \"caller must be Verifier\");\n }\n\n function _currentRoundInitialized() internal view {\n require(roundsManager().currentRoundInitialized(), \"current round is not initialized\");\n }\n\n function _autoClaimEarnings(address _delegator) internal {\n uint256 currentRound = roundsManager().currentRound();\n uint256 lastClaimRound = delegators[_delegator].lastClaimRound;\n if (lastClaimRound < currentRound) {\n updateDelegatorWithEarnings(_delegator, currentRound, lastClaimRound);\n }\n }\n}\n" + }, + "contracts/ManagerProxyTarget.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./Manager.sol\";\n\n/**\n * @title ManagerProxyTarget\n * @notice The base contract that target contracts used by a proxy contract should inherit from\n * @dev Both the target contract and the proxy contract (implemented as ManagerProxy) MUST inherit from ManagerProxyTarget in order to guarantee\n that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can\n potentially break the delegate proxy upgradeability mechanism\n */\nabstract contract ManagerProxyTarget is Manager {\n // Used to look up target contract address in controller's registry\n bytes32 public targetContractId;\n}\n" + }, + "contracts/bonding/IBondingManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n/**\n * @title Interface for BondingManager\n * TODO: switch to interface type\n */\ninterface IBondingManager {\n event TranscoderUpdate(address indexed transcoder, uint256 rewardCut, uint256 feeShare);\n event TranscoderActivated(address indexed transcoder, uint256 activationRound);\n event TranscoderDeactivated(address indexed transcoder, uint256 deactivationRound);\n event TranscoderSlashed(address indexed transcoder, address finder, uint256 penalty, uint256 finderReward);\n event Reward(address indexed transcoder, uint256 amount);\n event Bond(\n address indexed newDelegate,\n address indexed oldDelegate,\n address indexed delegator,\n uint256 additionalAmount,\n uint256 bondedAmount\n );\n event Unbond(\n address indexed delegate,\n address indexed delegator,\n uint256 unbondingLockId,\n uint256 amount,\n uint256 withdrawRound\n );\n event Rebond(address indexed delegate, address indexed delegator, uint256 unbondingLockId, uint256 amount);\n event TransferBond(\n address indexed oldDelegator,\n address indexed newDelegator,\n uint256 oldUnbondingLockId,\n uint256 newUnbondingLockId,\n uint256 amount\n );\n event WithdrawStake(address indexed delegator, uint256 unbondingLockId, uint256 amount, uint256 withdrawRound);\n event WithdrawFees(address indexed delegator, address recipient, uint256 amount);\n event EarningsClaimed(\n address indexed delegate,\n address indexed delegator,\n uint256 rewards,\n uint256 fees,\n uint256 startRound,\n uint256 endRound\n );\n\n // Deprecated events\n // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding\n // to these deprecated events.\n // event Bond(address indexed delegate, address indexed delegator);\n // event Unbond(address indexed delegate, address indexed delegator);\n // event WithdrawStake(address indexed delegator);\n // event TranscoderUpdate(address indexed transcoder, uint256 pendingRewardCut, uint256 pendingFeeShare, uint256 pendingPricePerSegment, bool registered);\n // event TranscoderEvicted(address indexed transcoder);\n // event TranscoderResigned(address indexed transcoder);\n\n // External functions\n function updateTranscoderWithFees(\n address _transcoder,\n uint256 _fees,\n uint256 _round\n ) external;\n\n function slashTranscoder(\n address _transcoder,\n address _finder,\n uint256 _slashAmount,\n uint256 _finderFee\n ) external;\n\n function setCurrentRoundTotalActiveStake() external;\n\n // Public functions\n function getTranscoderPoolSize() external view returns (uint256);\n\n function transcoderTotalStake(address _transcoder) external view returns (uint256);\n\n function isActiveTranscoder(address _transcoder) external view returns (bool);\n\n function getTotalBonded() external view returns (uint256);\n}\n" + }, + "contracts/libraries/SortedDoublyLL.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title A sorted doubly linked list with nodes sorted in descending order. Optionally accepts insert position hints\n *\n * Given a new node with a `key`, a hint is of the form `(prevId, nextId)` s.t. `prevId` and `nextId` are adjacent in the list.\n * `prevId` is a node with a key >= `key` and `nextId` is a node with a key <= `key`. If the sender provides a hint that is a valid insert position\n * the insert operation is a constant time storage write. However, the provided hint in a given transaction might be a valid insert position, but if other transactions are included first, when\n * the given transaction is executed the provided hint may no longer be a valid insert position. For example, one of the nodes referenced might be removed or their keys may\n * be updated such that the the pair of nodes in the hint no longer represent a valid insert position. If one of the nodes in the hint becomes invalid, we still try to use the other\n * valid node as a starting point for finding the appropriate insert position. If both nodes in the hint become invalid, we use the head of the list as a starting point\n * to find the appropriate insert position.\n */\nlibrary SortedDoublyLL {\n using SafeMath for uint256;\n\n // Information for a node in the list\n struct Node {\n uint256 key; // Node's key used for sorting\n address nextId; // Id of next node (smaller key) in the list\n address prevId; // Id of previous node (larger key) in the list\n }\n\n // Information for the list\n struct Data {\n address head; // Head of the list. Also the node in the list with the largest key\n address tail; // Tail of the list. Also the node in the list with the smallest key\n uint256 maxSize; // Maximum size of the list\n uint256 size; // Current size of the list\n mapping(address => Node) nodes; // Track the corresponding ids for each node in the list\n }\n\n /**\n * @dev Set the maximum size of the list\n * @param _size Maximum size\n */\n function setMaxSize(Data storage self, uint256 _size) public {\n require(_size > self.maxSize, \"new max size must be greater than old max size\");\n\n self.maxSize = _size;\n }\n\n /**\n * @dev Add a node to the list\n * @param _id Node's id\n * @param _key Node's key\n * @param _prevId Id of previous node for the insert position\n * @param _nextId Id of next node for the insert position\n */\n function insert(\n Data storage self,\n address _id,\n uint256 _key,\n address _prevId,\n address _nextId\n ) public {\n // List must not be full\n require(!isFull(self), \"list is full\");\n // List must not already contain node\n require(!contains(self, _id), \"node already in list\");\n // Node id must not be null\n require(_id != address(0), \"node id is null\");\n // Key must be non-zero\n require(_key > 0, \"key is zero\");\n\n address prevId = _prevId;\n address nextId = _nextId;\n\n if (!validInsertPosition(self, _key, prevId, nextId)) {\n // Sender's hint was not a valid insert position\n // Use sender's hint to find a valid insert position\n (prevId, nextId) = findInsertPosition(self, _key, prevId, nextId);\n }\n\n self.nodes[_id].key = _key;\n\n if (prevId == address(0) && nextId == address(0)) {\n // Insert as head and tail\n self.head = _id;\n self.tail = _id;\n } else if (prevId == address(0)) {\n // Insert before `prevId` as the head\n self.nodes[_id].nextId = self.head;\n self.nodes[self.head].prevId = _id;\n self.head = _id;\n } else if (nextId == address(0)) {\n // Insert after `nextId` as the tail\n self.nodes[_id].prevId = self.tail;\n self.nodes[self.tail].nextId = _id;\n self.tail = _id;\n } else {\n // Insert at insert position between `prevId` and `nextId`\n self.nodes[_id].nextId = nextId;\n self.nodes[_id].prevId = prevId;\n self.nodes[prevId].nextId = _id;\n self.nodes[nextId].prevId = _id;\n }\n\n self.size = self.size.add(1);\n }\n\n /**\n * @dev Remove a node from the list\n * @param _id Node's id\n */\n function remove(Data storage self, address _id) public {\n // List must contain the node\n require(contains(self, _id), \"node not in list\");\n\n if (self.size > 1) {\n // List contains more than a single node\n if (_id == self.head) {\n // The removed node is the head\n // Set head to next node\n self.head = self.nodes[_id].nextId;\n // Set prev pointer of new head to null\n self.nodes[self.head].prevId = address(0);\n } else if (_id == self.tail) {\n // The removed node is the tail\n // Set tail to previous node\n self.tail = self.nodes[_id].prevId;\n // Set next pointer of new tail to null\n self.nodes[self.tail].nextId = address(0);\n } else {\n // The removed node is neither the head nor the tail\n // Set next pointer of previous node to the next node\n self.nodes[self.nodes[_id].prevId].nextId = self.nodes[_id].nextId;\n // Set prev pointer of next node to the previous node\n self.nodes[self.nodes[_id].nextId].prevId = self.nodes[_id].prevId;\n }\n } else {\n // List contains a single node\n // Set the head and tail to null\n self.head = address(0);\n self.tail = address(0);\n }\n\n delete self.nodes[_id];\n self.size = self.size.sub(1);\n }\n\n /**\n * @dev Update the key of a node in the list\n * @param _id Node's id\n * @param _newKey Node's new key\n * @param _prevId Id of previous node for the new insert position\n * @param _nextId Id of next node for the new insert position\n */\n function updateKey(\n Data storage self,\n address _id,\n uint256 _newKey,\n address _prevId,\n address _nextId\n ) public {\n // List must contain the node\n require(contains(self, _id), \"node not in list\");\n\n // Remove node from the list\n remove(self, _id);\n\n if (_newKey > 0) {\n // Insert node if it has a non-zero key\n insert(self, _id, _newKey, _prevId, _nextId);\n }\n }\n\n /**\n * @dev Checks if the list contains a node\n * @param _id Address of transcoder\n * @return true if '_id' is in list\n */\n function contains(Data storage self, address _id) public view returns (bool) {\n // List only contains non-zero keys, so if key is non-zero the node exists\n return self.nodes[_id].key > 0;\n }\n\n /**\n * @dev Checks if the list is full\n * @return true if list is full\n */\n function isFull(Data storage self) public view returns (bool) {\n return self.size == self.maxSize;\n }\n\n /**\n * @dev Checks if the list is empty\n * @return true if list is empty\n */\n function isEmpty(Data storage self) public view returns (bool) {\n return self.size == 0;\n }\n\n /**\n * @dev Returns the current size of the list\n * @return current size of the list\n */\n function getSize(Data storage self) public view returns (uint256) {\n return self.size;\n }\n\n /**\n * @dev Returns the maximum size of the list\n */\n function getMaxSize(Data storage self) public view returns (uint256) {\n return self.maxSize;\n }\n\n /**\n * @dev Returns the key of a node in the list\n * @param _id Node's id\n * @return key for node with '_id'\n */\n function getKey(Data storage self, address _id) public view returns (uint256) {\n return self.nodes[_id].key;\n }\n\n /**\n * @dev Returns the first node in the list (node with the largest key)\n * @return address for the head of the list\n */\n function getFirst(Data storage self) public view returns (address) {\n return self.head;\n }\n\n /**\n * @dev Returns the last node in the list (node with the smallest key)\n * @return address for the tail of the list\n */\n function getLast(Data storage self) public view returns (address) {\n return self.tail;\n }\n\n /**\n * @dev Returns the next node (with a smaller key) in the list for a given node\n * @param _id Node's id\n * @return address for the node following node in list with '_id'\n */\n function getNext(Data storage self, address _id) public view returns (address) {\n return self.nodes[_id].nextId;\n }\n\n /**\n * @dev Returns the previous node (with a larger key) in the list for a given node\n * @param _id Node's id\n * address for the node before node in list with '_id'\n */\n function getPrev(Data storage self, address _id) public view returns (address) {\n return self.nodes[_id].prevId;\n }\n\n /**\n * @dev Check if a pair of nodes is a valid insertion point for a new node with the given key\n * @param _key Node's key\n * @param _prevId Id of previous node for the insert position\n * @param _nextId Id of next node for the insert position\n * @return if the insert position is valid\n */\n function validInsertPosition(\n Data storage self,\n uint256 _key,\n address _prevId,\n address _nextId\n ) public view returns (bool) {\n if (_prevId == address(0) && _nextId == address(0)) {\n // `(null, null)` is a valid insert position if the list is empty\n return isEmpty(self);\n } else if (_prevId == address(0)) {\n // `(null, _nextId)` is a valid insert position if `_nextId` is the head of the list\n return self.head == _nextId && _key >= self.nodes[_nextId].key;\n } else if (_nextId == address(0)) {\n // `(_prevId, null)` is a valid insert position if `_prevId` is the tail of the list\n return self.tail == _prevId && _key <= self.nodes[_prevId].key;\n } else {\n // `(_prevId, _nextId)` is a valid insert position if they are adjacent nodes and `_key` falls between the two nodes' keys\n return\n self.nodes[_prevId].nextId == _nextId &&\n self.nodes[_prevId].key >= _key &&\n _key >= self.nodes[_nextId].key;\n }\n }\n\n /**\n * @dev Descend the list (larger keys to smaller keys) to find a valid insert position\n * @param _key Node's key\n * @param _startId Id of node to start ascending the list from\n */\n function descendList(\n Data storage self,\n uint256 _key,\n address _startId\n ) private view returns (address, address) {\n // If `_startId` is the head, check if the insert position is before the head\n if (self.head == _startId && _key >= self.nodes[_startId].key) {\n return (address(0), _startId);\n }\n\n address prevId = _startId;\n address nextId = self.nodes[prevId].nextId;\n\n // Descend the list until we reach the end or until we find a valid insert position\n while (prevId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) {\n prevId = self.nodes[prevId].nextId;\n nextId = self.nodes[prevId].nextId;\n }\n\n return (prevId, nextId);\n }\n\n /**\n * @dev Ascend the list (smaller keys to larger keys) to find a valid insert position\n * @param _key Node's key\n * @param _startId Id of node to start descending the list from\n */\n function ascendList(\n Data storage self,\n uint256 _key,\n address _startId\n ) private view returns (address, address) {\n // If `_startId` is the tail, check if the insert position is after the tail\n if (self.tail == _startId && _key <= self.nodes[_startId].key) {\n return (_startId, address(0));\n }\n\n address nextId = _startId;\n address prevId = self.nodes[nextId].prevId;\n\n // Ascend the list until we reach the end or until we find a valid insertion point\n while (nextId != address(0) && !validInsertPosition(self, _key, prevId, nextId)) {\n nextId = self.nodes[nextId].prevId;\n prevId = self.nodes[nextId].prevId;\n }\n\n return (prevId, nextId);\n }\n\n /**\n * @dev Find the insert position for a new node with the given key\n * @param _key Node's key\n * @param _prevId Id of previous node for the insert position\n * @param _nextId Id of next node for the insert position\n */\n function findInsertPosition(\n Data storage self,\n uint256 _key,\n address _prevId,\n address _nextId\n ) private view returns (address, address) {\n address prevId = _prevId;\n address nextId = _nextId;\n\n if (prevId != address(0)) {\n if (!contains(self, prevId) || _key > self.nodes[prevId].key) {\n // `prevId` does not exist anymore or now has a smaller key than the given key\n prevId = address(0);\n }\n }\n\n if (nextId != address(0)) {\n if (!contains(self, nextId) || _key < self.nodes[nextId].key) {\n // `nextId` does not exist anymore or now has a larger key than the given key\n nextId = address(0);\n }\n }\n\n if (prevId == address(0) && nextId == address(0)) {\n // No hint - descend list starting from head\n return descendList(self, _key, self.head);\n } else if (prevId == address(0)) {\n // No `prevId` for hint - ascend list starting from `nextId`\n return ascendList(self, _key, nextId);\n } else if (nextId == address(0)) {\n // No `nextId` for hint - descend list starting from `prevId`\n return descendList(self, _key, prevId);\n } else {\n // Descend list starting from `prevId`\n return descendList(self, _key, prevId);\n }\n }\n}\n" + }, + "contracts/libraries/MathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nlibrary MathUtils {\n using SafeMath for uint256;\n\n // Divisor used for representing percentages\n uint256 public constant PERC_DIVISOR = 1000000;\n\n /**\n * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR\n * @param _amount Amount that is supposed to be a percentage\n */\n function validPerc(uint256 _amount) internal pure returns (bool) {\n return _amount <= PERC_DIVISOR;\n }\n\n /**\n * @dev Compute percentage of a value with the percentage represented by a fraction\n * @param _amount Amount to take the percentage of\n * @param _fracNum Numerator of fraction representing the percentage\n * @param _fracDenom Denominator of fraction representing the percentage\n */\n function percOf(\n uint256 _amount,\n uint256 _fracNum,\n uint256 _fracDenom\n ) internal pure returns (uint256) {\n return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR);\n }\n\n /**\n * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR\n * @param _amount Amount to take the percentage of\n * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator\n */\n function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) {\n return _amount.mul(_fracNum).div(PERC_DIVISOR);\n }\n\n /**\n * @dev Compute percentage representation of a fraction\n * @param _fracNum Numerator of fraction represeting the percentage\n * @param _fracDenom Denominator of fraction represeting the percentage\n */\n function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {\n return _fracNum.mul(PERC_DIVISOR).div(_fracDenom);\n }\n}\n" + }, + "contracts/libraries/PreciseMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nlibrary PreciseMathUtils {\n using SafeMath for uint256;\n\n // Divisor used for representing percentages\n uint256 public constant PERC_DIVISOR = 10**27;\n\n /**\n * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR\n * @param _amount Amount that is supposed to be a percentage\n */\n function validPerc(uint256 _amount) internal pure returns (bool) {\n return _amount <= PERC_DIVISOR;\n }\n\n /**\n * @dev Compute percentage of a value with the percentage represented by a fraction\n * @param _amount Amount to take the percentage of\n * @param _fracNum Numerator of fraction representing the percentage\n * @param _fracDenom Denominator of fraction representing the percentage\n */\n function percOf(\n uint256 _amount,\n uint256 _fracNum,\n uint256 _fracDenom\n ) internal pure returns (uint256) {\n return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR);\n }\n\n /**\n * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR\n * @param _amount Amount to take the percentage of\n * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator\n */\n function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) {\n return _amount.mul(_fracNum).div(PERC_DIVISOR);\n }\n\n /**\n * @dev Compute percentage representation of a fraction\n * @param _fracNum Numerator of fraction represeting the percentage\n * @param _fracDenom Denominator of fraction represeting the percentage\n */\n function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {\n return _fracNum.mul(PERC_DIVISOR).div(_fracDenom);\n }\n}\n" + }, + "contracts/bonding/libraries/EarningsPool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../libraries/MathUtils.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title EarningsPool\n * @dev Manages reward and fee pools for delegators and transcoders\n */\nlibrary EarningsPool {\n using SafeMath for uint256;\n\n struct Data {\n uint256 totalStake; // Transcoder's total stake during the earnings pool's round\n uint256 transcoderRewardCut; // Transcoder's reward cut during the earnings pool's round\n uint256 transcoderFeeShare; // Transcoder's fee share during the earnings pool's round\n // LIP-36 (https://github.com/livepeer/LIPs/blob/master/LIPs/LIP-36.md) fields\n // See EarningsPoolLIP36.sol\n uint256 cumulativeRewardFactor;\n uint256 cumulativeFeeFactor;\n }\n\n /**\n * @dev Sets transcoderRewardCut and transcoderFeeshare for an EarningsPool\n * @param earningsPool Storage pointer to EarningsPool struct\n * @param _rewardCut Reward cut of transcoder during the earnings pool's round\n * @param _feeShare Fee share of transcoder during the earnings pool's round\n */\n function setCommission(\n EarningsPool.Data storage earningsPool,\n uint256 _rewardCut,\n uint256 _feeShare\n ) internal {\n earningsPool.transcoderRewardCut = _rewardCut;\n earningsPool.transcoderFeeShare = _feeShare;\n }\n\n /**\n * @dev Sets totalStake for an EarningsPool\n * @param earningsPool Storage pointer to EarningsPool struct\n * @param _stake Total stake of the transcoder during the earnings pool's round\n */\n function setStake(EarningsPool.Data storage earningsPool, uint256 _stake) internal {\n earningsPool.totalStake = _stake;\n }\n}\n" + }, + "contracts/bonding/libraries/EarningsPoolLIP36.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./EarningsPool.sol\";\nimport \"../../libraries/PreciseMathUtils.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nlibrary EarningsPoolLIP36 {\n using SafeMath for uint256;\n\n /**\n * @notice Update the cumulative fee factor stored in an earnings pool with new fees\n * @param earningsPool Storage pointer to EarningsPools.Data struct\n * @param _prevEarningsPool In-memory EarningsPool.Data struct that stores the previous cumulative reward and fee factors\n * @param _fees Amount of new fees\n */\n function updateCumulativeFeeFactor(\n EarningsPool.Data storage earningsPool,\n EarningsPool.Data memory _prevEarningsPool,\n uint256 _fees\n ) internal {\n uint256 prevCumulativeFeeFactor = _prevEarningsPool.cumulativeFeeFactor;\n uint256 prevCumulativeRewardFactor = _prevEarningsPool.cumulativeRewardFactor != 0\n ? _prevEarningsPool.cumulativeRewardFactor\n : PreciseMathUtils.percPoints(1, 1);\n\n // Initialize the cumulativeFeeFactor when adding fees for the first time\n if (earningsPool.cumulativeFeeFactor == 0) {\n earningsPool.cumulativeFeeFactor = prevCumulativeFeeFactor.add(\n PreciseMathUtils.percOf(prevCumulativeRewardFactor, _fees, earningsPool.totalStake)\n );\n return;\n }\n\n earningsPool.cumulativeFeeFactor = earningsPool.cumulativeFeeFactor.add(\n PreciseMathUtils.percOf(prevCumulativeRewardFactor, _fees, earningsPool.totalStake)\n );\n }\n\n /**\n * @notice Update the cumulative reward factor stored in an earnings pool with new rewards\n * @param earningsPool Storage pointer to EarningsPool.Data struct\n * @param _prevEarningsPool Storage pointer to EarningsPool.Data struct that stores the previous cumulative reward factor\n * @param _rewards Amount of new rewards\n */\n function updateCumulativeRewardFactor(\n EarningsPool.Data storage earningsPool,\n EarningsPool.Data memory _prevEarningsPool,\n uint256 _rewards\n ) internal {\n uint256 prevCumulativeRewardFactor = _prevEarningsPool.cumulativeRewardFactor != 0\n ? _prevEarningsPool.cumulativeRewardFactor\n : PreciseMathUtils.percPoints(1, 1);\n\n earningsPool.cumulativeRewardFactor = prevCumulativeRewardFactor.add(\n PreciseMathUtils.percOf(prevCumulativeRewardFactor, _rewards, earningsPool.totalStake)\n );\n }\n}\n" + }, + "contracts/token/ILivepeerToken.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\n\ninterface ILivepeerToken is IERC20 {\n function mint(address _to, uint256 _amount) external;\n\n function burn(uint256 _amount) external;\n}\n" + }, + "contracts/token/IMinter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../IController.sol\";\n\n/**\n * @title Minter interface\n */\ninterface IMinter {\n // Events\n event SetCurrentRewardTokens(uint256 currentMintableTokens, uint256 currentInflation);\n\n // External functions\n function createReward(uint256 _fracNum, uint256 _fracDenom) external returns (uint256);\n\n function trustedTransferTokens(address _to, uint256 _amount) external;\n\n function trustedBurnTokens(uint256 _amount) external;\n\n function trustedWithdrawETH(address payable _to, uint256 _amount) external;\n\n function depositETH() external payable returns (bool);\n\n function setCurrentRewardTokens() external;\n\n function currentMintableTokens() external view returns (uint256);\n\n function currentMintedTokens() external view returns (uint256);\n\n // Public functions\n function getController() external view returns (IController);\n}\n" + }, + "contracts/rounds/IRoundsManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n/**\n * @title RoundsManager interface\n */\ninterface IRoundsManager {\n // Events\n event NewRound(uint256 indexed round, bytes32 blockHash);\n\n // Deprecated events\n // These event signatures can be used to construct the appropriate topic hashes to filter for past logs corresponding\n // to these deprecated events.\n // event NewRound(uint256 round)\n\n // External functions\n function initializeRound() external;\n\n function lipUpgradeRound(uint256 _lip) external view returns (uint256);\n\n // Public functions\n function blockNum() external view returns (uint256);\n\n function blockHash(uint256 _block) external view returns (bytes32);\n\n function blockHashForRound(uint256 _round) external view returns (bytes32);\n\n function currentRound() external view returns (uint256);\n\n function currentRoundStartBlock() external view returns (uint256);\n\n function currentRoundInitialized() external view returns (bool);\n\n function currentRoundLocked() external view returns (bool);\n}\n" + }, + "contracts/snapshots/IMerkleSnapshot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\ninterface IMerkleSnapshot {\n function verify(\n bytes32 _id,\n bytes32[] calldata _proof,\n bytes32 _leaf\n ) external view returns (bool);\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeMath.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/math/SafeMath.sol)\n\npragma solidity ^0.8.0;\n\n// CAUTION\n// This version of SafeMath should only be used with Solidity 0.8 or later,\n// because it relies on the compiler's built in overflow checks.\n\n/**\n * @dev Wrappers over Solidity's arithmetic operations.\n *\n * NOTE: `SafeMath` is generally not needed starting with Solidity 0.8, since the compiler\n * now has built in overflow checking.\n */\nlibrary SafeMath {\n /**\n * @dev Returns the addition of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n uint256 c = a + b;\n if (c < a) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the substraction of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b > a) return (false, 0);\n return (true, a - b);\n }\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, with an overflow flag.\n *\n * _Available since v3.4._\n */\n function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n // Gas optimization: this is cheaper than requiring 'a' not being zero, but the\n // benefit is lost if 'b' is also tested.\n // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522\n if (a == 0) return (true, 0);\n uint256 c = a * b;\n if (c / a != b) return (false, 0);\n return (true, c);\n }\n }\n\n /**\n * @dev Returns the division of two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a / b);\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.\n *\n * _Available since v3.4._\n */\n function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {\n unchecked {\n if (b == 0) return (false, 0);\n return (true, a % b);\n }\n }\n\n /**\n * @dev Returns the addition of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `+` operator.\n *\n * Requirements:\n *\n * - Addition cannot overflow.\n */\n function add(uint256 a, uint256 b) internal pure returns (uint256) {\n return a + b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting on\n * overflow (when the result is negative).\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(uint256 a, uint256 b) internal pure returns (uint256) {\n return a - b;\n }\n\n /**\n * @dev Returns the multiplication of two unsigned integers, reverting on\n * overflow.\n *\n * Counterpart to Solidity's `*` operator.\n *\n * Requirements:\n *\n * - Multiplication cannot overflow.\n */\n function mul(uint256 a, uint256 b) internal pure returns (uint256) {\n return a * b;\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator.\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(uint256 a, uint256 b) internal pure returns (uint256) {\n return a / b;\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting when dividing by zero.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(uint256 a, uint256 b) internal pure returns (uint256) {\n return a % b;\n }\n\n /**\n * @dev Returns the subtraction of two unsigned integers, reverting with custom message on\n * overflow (when the result is negative).\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {trySub}.\n *\n * Counterpart to Solidity's `-` operator.\n *\n * Requirements:\n *\n * - Subtraction cannot overflow.\n */\n function sub(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b <= a, errorMessage);\n return a - b;\n }\n }\n\n /**\n * @dev Returns the integer division of two unsigned integers, reverting with custom message on\n * division by zero. The result is rounded towards zero.\n *\n * Counterpart to Solidity's `/` operator. Note: this function uses a\n * `revert` opcode (which leaves remaining gas untouched) while Solidity\n * uses an invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function div(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a / b;\n }\n }\n\n /**\n * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),\n * reverting with custom message when dividing by zero.\n *\n * CAUTION: This function is deprecated because it requires allocating memory for the error\n * message unnecessarily. For custom revert reasons use {tryMod}.\n *\n * Counterpart to Solidity's `%` operator. This function uses a `revert`\n * opcode (which leaves remaining gas untouched) while Solidity uses an\n * invalid opcode to revert (consuming all remaining gas).\n *\n * Requirements:\n *\n * - The divisor cannot be zero.\n */\n function mod(\n uint256 a,\n uint256 b,\n string memory errorMessage\n ) internal pure returns (uint256) {\n unchecked {\n require(b > 0, errorMessage);\n return a % b;\n }\n }\n}\n" + }, + "contracts/Manager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./IManager.sol\";\nimport \"./IController.sol\";\n\ncontract Manager is IManager {\n // Controller that contract is registered with\n IController public controller;\n\n // Check if sender is controller\n modifier onlyController() {\n _onlyController();\n _;\n }\n\n // Check if sender is controller owner\n modifier onlyControllerOwner() {\n _onlyControllerOwner();\n _;\n }\n\n // Check if controller is not paused\n modifier whenSystemNotPaused() {\n _whenSystemNotPaused();\n _;\n }\n\n // Check if controller is paused\n modifier whenSystemPaused() {\n _whenSystemPaused();\n _;\n }\n\n constructor(address _controller) {\n controller = IController(_controller);\n }\n\n /**\n * @notice Set controller. Only callable by current controller\n * @param _controller Controller contract address\n */\n function setController(address _controller) external onlyController {\n controller = IController(_controller);\n\n emit SetController(_controller);\n }\n\n function _onlyController() private view {\n require(msg.sender == address(controller), \"caller must be Controller\");\n }\n\n function _onlyControllerOwner() private view {\n require(msg.sender == controller.owner(), \"caller must be Controller owner\");\n }\n\n function _whenSystemNotPaused() private view {\n require(!controller.paused(), \"system is paused\");\n }\n\n function _whenSystemPaused() private view {\n require(controller.paused(), \"system is not paused\");\n }\n}\n" + }, + "contracts/IManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\ninterface IManager {\n event SetController(address controller);\n event ParameterUpdate(string param);\n\n function setController(address _controller) external;\n}\n" + }, + "contracts/IController.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./zeppelin/Pausable.sol\";\n\nabstract contract IController is Pausable {\n event SetContractInfo(bytes32 id, address contractAddress, bytes20 gitCommitHash);\n\n function setContractInfo(\n bytes32 _id,\n address _contractAddress,\n bytes20 _gitCommitHash\n ) external virtual;\n\n function updateController(bytes32 _id, address _controller) external virtual;\n\n function getContract(bytes32 _id) public view virtual returns (address);\n}\n" + }, + "contracts/zeppelin/Pausable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./Ownable.sol\";\n\n/**\n * @title Pausable\n * @dev Base contract which allows children to implement an emergency stop mechanism.\n */\ncontract Pausable is Ownable {\n event Pause();\n event Unpause();\n\n bool public paused;\n\n /**\n * @dev Modifier to make a function callable only when the contract is not paused.\n */\n modifier whenNotPaused() {\n require(!paused);\n _;\n }\n\n /**\n * @dev Modifier to make a function callable only when the contract is paused.\n */\n modifier whenPaused() {\n require(paused);\n _;\n }\n\n /**\n * @dev called by the owner to pause, triggers stopped state\n */\n function pause() public onlyOwner whenNotPaused {\n paused = true;\n emit Pause();\n }\n\n /**\n * @dev called by the owner to unpause, returns to normal state\n */\n function unpause() public onlyOwner whenPaused {\n paused = false;\n emit Unpause();\n }\n}\n" + }, + "contracts/zeppelin/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n/**\n * @title Ownable\n * @dev The Ownable contract has an owner address, and provides basic authorization control\n * functions, this simplifies the implementation of \"user permissions\".\n */\ncontract Ownable {\n address public owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev The Ownable constructor sets the original `owner` of the contract to the sender\n * account.\n */\n constructor() {\n owner = msg.sender;\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n require(msg.sender == owner);\n _;\n }\n\n /**\n * @dev Allows the current owner to transfer control of the contract to a newOwner.\n * @param newOwner The address to transfer ownership to.\n */\n function transferOwnership(address newOwner) public onlyOwner {\n require(newOwner != address(0));\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (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 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 `recipient`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address recipient, 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 `sender` to `recipient` 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 sender,\n address recipient,\n uint256 amount\n ) external returns (bool);\n\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" + }, + "contracts/token/Minter.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../Manager.sol\";\nimport \"./IMinter.sol\";\nimport \"./ILivepeerToken.sol\";\nimport \"../rounds/IRoundsManager.sol\";\nimport \"../bonding/IBondingManager.sol\";\nimport \"../libraries/MathUtilsV2.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\ninterface IL2LPTDataCache {\n function l1CirculatingSupply() external view returns (uint256);\n}\n\n/**\n * @title Minter\n * @dev Manages inflation rate and the minting of new tokens for each round of the Livepeer protocol\n */\ncontract Minter is Manager, IMinter {\n using SafeMath for uint256;\n\n // Per round inflation rate\n uint256 public inflation;\n // Change in inflation rate per round until the target bonding rate is achieved\n uint256 public inflationChange;\n // Target bonding rate\n uint256 public targetBondingRate;\n\n // Current number of mintable tokens. Reset every round\n uint256 public currentMintableTokens;\n // Current number of minted tokens. Reset every round\n uint256 public currentMintedTokens;\n\n // Checks if caller is BondingManager\n modifier onlyBondingManager() {\n require(msg.sender == controller.getContract(keccak256(\"BondingManager\")), \"msg.sender not BondingManager\");\n _;\n }\n\n // Checks if caller is RoundsManager\n modifier onlyRoundsManager() {\n require(msg.sender == controller.getContract(keccak256(\"RoundsManager\")), \"msg.sender not RoundsManager\");\n _;\n }\n\n // Checks if caller is either BondingManager or JobsManager\n modifier onlyBondingManagerOrJobsManager() {\n require(\n msg.sender == controller.getContract(keccak256(\"BondingManager\")) ||\n msg.sender == controller.getContract(keccak256(\"JobsManager\")),\n \"msg.sender not BondingManager or JobsManager\"\n );\n _;\n }\n\n // Checks if caller is either the currently registered Minter or JobsManager\n modifier onlyMinterOrJobsManager() {\n require(\n msg.sender == controller.getContract(keccak256(\"Minter\")) ||\n msg.sender == controller.getContract(keccak256(\"JobsManager\")),\n \"msg.sender not Minter or JobsManager\"\n );\n _;\n }\n\n /**\n * @notice Minter constructor\n * @param _inflation Base inflation rate as a percentage of current total token supply\n * @param _inflationChange Change in inflation rate each round (increase or decrease) if target bonding rate is not achieved\n * @param _targetBondingRate Target bonding rate as a percentage of total bonded tokens / total token supply\n */\n constructor(\n address _controller,\n uint256 _inflation,\n uint256 _inflationChange,\n uint256 _targetBondingRate\n ) Manager(_controller) {\n // Inflation must be valid percentage\n require(MathUtils.validPerc(_inflation), \"_inflation is invalid percentage\");\n // Inflation change must be valid percentage\n require(MathUtils.validPerc(_inflationChange), \"_inflationChange is invalid percentage\");\n // Target bonding rate must be valid percentage\n require(MathUtils.validPerc(_targetBondingRate), \"_targetBondingRate is invalid percentage\");\n\n inflation = _inflation;\n inflationChange = _inflationChange;\n targetBondingRate = _targetBondingRate;\n }\n\n /**\n * @notice Set targetBondingRate. Only callable by Controller owner\n * @param _targetBondingRate Target bonding rate as a percentage of total bonded tokens / total token supply\n */\n function setTargetBondingRate(uint256 _targetBondingRate) external onlyControllerOwner {\n // Must be valid percentage\n require(MathUtils.validPerc(_targetBondingRate), \"_targetBondingRate is invalid percentage\");\n\n targetBondingRate = _targetBondingRate;\n\n emit ParameterUpdate(\"targetBondingRate\");\n }\n\n /**\n * @notice Set inflationChange. Only callable by Controller owner\n * @param _inflationChange Inflation change as a percentage of total token supply\n */\n function setInflationChange(uint256 _inflationChange) external onlyControllerOwner {\n // Must be valid percentage\n require(MathUtils.validPerc(_inflationChange), \"_inflationChange is invalid percentage\");\n\n inflationChange = _inflationChange;\n\n emit ParameterUpdate(\"inflationChange\");\n }\n\n /**\n * @notice Migrate to a new Minter by transferring the current Minter's LPT + ETH balance to the new Minter\n * @dev Only callable by Controller owner\n * @param _newMinter Address of new Minter\n */\n function migrateToNewMinter(IMinter _newMinter) external onlyControllerOwner {\n // New Minter cannot be the current Minter\n require(_newMinter != this, \"new Minter cannot be current Minter\");\n // Check for null address\n require(address(_newMinter) != address(0), \"new Minter cannot be null address\");\n\n IController newMinterController = _newMinter.getController();\n // New Minter must have same Controller as current Minter\n require(newMinterController == controller, \"new Minter Controller must be current Controller\");\n // New Minter's Controller must have the current Minter registered\n require(newMinterController.getContract(keccak256(\"Minter\")) == address(this), \"new Minter must be registered\");\n\n // Transfer current Minter's token balance to new Minter\n livepeerToken().transfer(address(_newMinter), livepeerToken().balanceOf(address(this)));\n // Transfer current Minter's ETH balance to new Minter\n _newMinter.depositETH{ value: address(this).balance }();\n }\n\n /**\n * @notice Create reward based on a fractional portion of the mintable tokens for the current round\n * @param _fracNum Numerator of fraction (active transcoder's stake)\n * @param _fracDenom Denominator of fraction (total active stake)\n */\n function createReward(uint256 _fracNum, uint256 _fracDenom)\n external\n onlyBondingManager\n whenSystemNotPaused\n returns (uint256)\n {\n // Compute and mint fraction of mintable tokens to include in reward\n uint256 mintAmount = MathUtils.percOf(currentMintableTokens, _fracNum, _fracDenom);\n // Update amount of minted tokens for round\n currentMintedTokens = currentMintedTokens.add(mintAmount);\n // Minted tokens must not exceed mintable tokens\n require(currentMintedTokens <= currentMintableTokens, \"minted tokens cannot exceed mintable tokens\");\n // Mint new tokens\n livepeerToken().mint(address(this), mintAmount);\n\n // Reward = minted tokens\n return mintAmount;\n }\n\n /**\n * @notice Transfer tokens to a receipient. Only callable by BondingManager - always trusts BondingManager\n * @param _to Recipient address\n * @param _amount Amount of tokens\n */\n function trustedTransferTokens(address _to, uint256 _amount) external onlyBondingManager whenSystemNotPaused {\n livepeerToken().transfer(_to, _amount);\n }\n\n /**\n * @notice Burn tokens. Only callable by BondingManager - always trusts BondingManager\n * @param _amount Amount of tokens to burn\n */\n function trustedBurnTokens(uint256 _amount) external onlyBondingManager whenSystemNotPaused {\n livepeerToken().burn(_amount);\n }\n\n /**\n * @notice Withdraw ETH to a recipient. Only callable by BondingManager or TicketBroker - always trusts these two contracts\n * @param _to Recipient address\n * @param _amount Amount of ETH\n */\n function trustedWithdrawETH(address payable _to, uint256 _amount)\n external\n onlyBondingManagerOrJobsManager\n whenSystemNotPaused\n {\n _to.transfer(_amount);\n }\n\n /**\n * @notice Deposit ETH to this contract. Only callable by the currently registered Minter or JobsManager\n */\n function depositETH() external payable onlyMinterOrJobsManager returns (bool) {\n return true;\n }\n\n /**\n * @notice Set inflation and mintable tokens for the round. Only callable by the RoundsManager\n */\n function setCurrentRewardTokens() external onlyRoundsManager whenSystemNotPaused {\n setInflation();\n\n // Set mintable tokens based upon current inflation and current total token supply\n currentMintableTokens = MathUtils.percOf(getGlobalTotalSupply(), inflation);\n currentMintedTokens = 0;\n\n emit SetCurrentRewardTokens(currentMintableTokens, inflation);\n }\n\n /**\n * @dev Returns Controller interface\n */\n function getController() public view returns (IController) {\n return controller;\n }\n\n /**\n * @notice Calculate and return global LPT total supply\n * @return Global LPT total supply\n */\n function getGlobalTotalSupply() public view returns (uint256) {\n // Global total supply = L2 total supply + L1 circulating supply\n return livepeerToken().totalSupply().add(l2LPTDataCache().l1CirculatingSupply());\n }\n\n /**\n * @dev Set inflation based upon the current bonding rate and target bonding rate\n */\n function setInflation() internal {\n uint256 currentBondingRate;\n uint256 totalSupply = getGlobalTotalSupply();\n\n if (totalSupply > 0) {\n uint256 totalBonded = bondingManager().getTotalBonded();\n currentBondingRate = MathUtils.percPoints(totalBonded, totalSupply);\n }\n\n if (currentBondingRate < targetBondingRate) {\n // Bonding rate is below the target - increase inflation\n inflation = inflation.add(inflationChange);\n } else if (currentBondingRate > targetBondingRate) {\n // Bonding rate is above the target - decrease inflation\n if (inflationChange > inflation) {\n inflation = 0;\n } else {\n inflation = inflation.sub(inflationChange);\n }\n }\n }\n\n /**\n * @dev Returns LivepeerToken interface\n */\n function livepeerToken() internal view returns (ILivepeerToken) {\n return ILivepeerToken(controller.getContract(keccak256(\"LivepeerToken\")));\n }\n\n /**\n * @dev Returns BondingManager interface\n */\n function bondingManager() internal view returns (IBondingManager) {\n return IBondingManager(controller.getContract(keccak256(\"BondingManager\")));\n }\n\n /**\n * @dev Returns L2LPTDataCache interface\n */\n function l2LPTDataCache() internal view returns (IL2LPTDataCache) {\n return IL2LPTDataCache(controller.getContract(keccak256(\"L2LPTDataCache\")));\n }\n}\n" + }, + "contracts/libraries/MathUtilsV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nlibrary MathUtils {\n using SafeMath for uint256;\n\n // Divisor used for representing percentages\n uint256 public constant PERC_DIVISOR = 1000000000;\n\n /**\n * @dev Returns whether an amount is a valid percentage out of PERC_DIVISOR\n * @param _amount Amount that is supposed to be a percentage\n */\n function validPerc(uint256 _amount) internal pure returns (bool) {\n return _amount <= PERC_DIVISOR;\n }\n\n /**\n * @dev Compute percentage of a value with the percentage represented by a fraction\n * @param _amount Amount to take the percentage of\n * @param _fracNum Numerator of fraction representing the percentage\n * @param _fracDenom Denominator of fraction representing the percentage\n */\n function percOf(\n uint256 _amount,\n uint256 _fracNum,\n uint256 _fracDenom\n ) internal pure returns (uint256) {\n return _amount.mul(percPoints(_fracNum, _fracDenom)).div(PERC_DIVISOR);\n }\n\n /**\n * @dev Compute percentage of a value with the percentage represented by a fraction over PERC_DIVISOR\n * @param _amount Amount to take the percentage of\n * @param _fracNum Numerator of fraction representing the percentage with PERC_DIVISOR as the denominator\n */\n function percOf(uint256 _amount, uint256 _fracNum) internal pure returns (uint256) {\n return _amount.mul(_fracNum).div(PERC_DIVISOR);\n }\n\n /**\n * @dev Compute percentage representation of a fraction\n * @param _fracNum Numerator of fraction represeting the percentage\n * @param _fracDenom Denominator of fraction represeting the percentage\n */\n function percPoints(uint256 _fracNum, uint256 _fracDenom) internal pure returns (uint256) {\n return _fracNum.mul(PERC_DIVISOR).div(_fracDenom);\n }\n}\n" + }, + "contracts/test/TestMathUtilsV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../libraries/MathUtilsV2.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestMathUtilsV2 {\n function test_validPerc() public {\n Assert.equal(MathUtils.validPerc(50), true, \"50 should be a valid percentage\");\n Assert.equal(MathUtils.validPerc(0), true, \"0 should be a valid percentage\");\n Assert.equal(MathUtils.validPerc(1000000000), true, \"the max should be a valid percentage\");\n Assert.equal(MathUtils.validPerc(1000000001), false, \"1 more than the max should not be valid percentage\");\n }\n\n function test_percOf1() public {\n Assert.equal(MathUtils.percOf(100, 3, 4), 75, \"3/4 of 100 should be 75\");\n Assert.equal(MathUtils.percOf(100, 7, 9), 77, \"7/9 of 100 should be 77\");\n }\n\n function test_percOf2() public {\n Assert.equal(MathUtils.percOf(100, 3), 0, \".0000003% of 100 is 0\");\n Assert.equal(MathUtils.percOf(1000000000, 1), 1, \".0000001% of 1000000000 is 1\");\n Assert.equal(MathUtils.percOf(100, 100000000), 10, \"10% of 100 is 10\");\n }\n\n function test_percPoints() public {\n Assert.equal(MathUtils.percPoints(3, 4), 750000000, \"3/4 should convert to valid percentage\");\n Assert.equal(MathUtils.percPoints(100, 300), 333333333, \"100/300 should convert to valid percentage\");\n }\n}\n" + }, + "contracts/test/helpers/truffle/Assert.sol": { + "content": "// This file taken from here: https://raw.githubusercontent.com/smartcontractproduction/sol-unit/master/contracts/src/Assertions.sol\n// It was renamed to Assert.sol by Tim Coulter. Refactored for solidity 0.5.0 by Cruz Molina.\n//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./AssertString.sol\";\nimport \"./AssertBytes32.sol\";\nimport \"./AssertAddress.sol\";\nimport \"./AssertBool.sol\";\nimport \"./AssertUint.sol\";\nimport \"./AssertInt.sol\";\nimport \"./AssertUintArray.sol\";\nimport \"./AssertIntArray.sol\";\nimport \"./AssertAddressArray.sol\";\n// import \"./AssertAddressPayableArray.sol\";\n// ^would require an oldAssert.sol (0.4.0) & a newAssert.sol (0.5.0)\nimport \"./AssertBytes32Array.sol\";\nimport \"./AssertBalance.sol\";\nimport \"./AssertGeneral.sol\";\n\n/*\n File: Assertions.slb\n\n Author: Andreas Olofsson (androlo1980@gmail.com)\n\n Library: Assertions\n\n Assertions for unit testing contracts. Tests are run with the\n \n unit-testing framework.\n\n (start code)\n contract ModAdder {\n\n function addMod(uint a, uint b, uint modulus) constant returns (uint sum) {\n if (modulus == 0)\n throw;\n return addmod(a, b, modulus);\n }\n\n }\n\n contract SomeTest {\n using Assertions for uint;\n\n function testAdd() {\n var adder = new ModAdder();\n adder.addMod(50, 66, 30).equal(26, \"addition returned the wrong sum\");\n }\n }\n (end)\n\n It is also possible to extend , to have all bindings (using) properly set up.\n\n (start code)\n\n contract SomeTest is Test {\n\n function testAdd() {\n var adder = new ModAdder();\n adder.addMod(50, 66, 30).equal(26, \"addition returned the wrong sum\");\n }\n }\n (end)\n*/\n\nlibrary Assert {\n // ************************************** general **************************************\n\n /*\n Function: fail()\n\n Mark the test as failed.\n\n Params:\n message (string) - A message associated with the failure.\n\n Returns:\n result (bool) - false.\n */\n function fail(string memory message) internal returns (bool result) {\n return AssertGeneral.fail(message);\n }\n\n // ************************************** strings **************************************\n\n /*\n Function: equal(string)\n\n Assert that two strings are equal.\n\n : _stringsEqual(A, B) == true\n\n Params:\n A (string) - The first string.\n B (string) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n string memory a,\n string memory b,\n string memory message\n ) internal returns (bool result) {\n return AssertString.equal(a, b, message);\n }\n\n /*\n Function: notEqual(string)\n\n Assert that two strings are not equal.\n\n : _stringsEqual(A, B) == false\n\n Params:\n A (string) - The first string.\n B (string) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n string memory a,\n string memory b,\n string memory message\n ) internal returns (bool result) {\n return AssertString.notEqual(a, b, message);\n }\n\n /*\n Function: isEmpty(string)\n\n Assert that a string is empty.\n\n : _stringsEqual(str, STRING_NULL) == true\n\n Params:\n str (string) - The string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isEmpty(string memory str, string memory message) internal returns (bool result) {\n return AssertString.isEmpty(str, message);\n }\n\n /*\n Function: isNotEmpty(string)\n\n Assert that a string is not empty.\n\n : _stringsEqual(str, STRING_NULL) == false\n\n Params:\n str (string) - The string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotEmpty(string memory str, string memory message) internal returns (bool result) {\n return AssertString.isNotEmpty(str, message);\n }\n\n // ************************************** bytes32 **************************************\n\n /*\n Function: equal(bytes32)\n\n Assert that two 'bytes32' are equal.\n\n : A == B\n\n Params:\n A (bytes32) - The first 'bytes32'.\n B (bytes32) - The second 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n bytes32 a,\n bytes32 b,\n string memory message\n ) internal returns (bool result) {\n return AssertBytes32.equal(a, b, message);\n }\n\n /*\n Function: notEqual(bytes32)\n\n Assert that two 'bytes32' are not equal.\n\n : A != B\n\n Params:\n A (bytes32) - The first 'bytes32'.\n B (bytes32) - The second 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n bytes32 a,\n bytes32 b,\n string memory message\n ) internal returns (bool result) {\n return AssertBytes32.notEqual(a, b, message);\n }\n\n /*\n Function: isZero(bytes32)\n\n Assert that a 'bytes32' is zero.\n\n : bts == BYTES32_NULL\n\n Params:\n bts (bytes32) - The 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(bytes32 bts, string memory message) internal returns (bool result) {\n return AssertBytes32.isZero(bts, message);\n }\n\n /*\n Function: isNotZero(bytes32)\n\n Assert that a 'bytes32' is not zero.\n\n : bts != BYTES32_NULL\n\n Params:\n bts (bytes32) - The 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(bytes32 bts, string memory message) internal returns (bool result) {\n return AssertBytes32.isNotZero(bts, message);\n }\n\n // ************************************** address **************************************\n\n /*\n Function: equal(address)\n\n Assert that two addresses are equal.\n\n : A == B\n\n Params:\n A (address) - The first address.\n B (address) - The second address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n address a,\n address b,\n string memory message\n ) internal returns (bool result) {\n return AssertAddress.equal(a, b, message);\n }\n\n /*\n Function: notEqual(address)\n\n Assert that two addresses are not equal.\n\n : A != B\n\n Params:\n A (address) - The first address.\n B (address) - The second address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n address a,\n address b,\n string memory message\n ) internal returns (bool result) {\n return AssertAddress.notEqual(a, b, message);\n }\n\n /*\n Function: isZero(address)\n\n Assert that an address is zero.\n\n : addr == ADDRESS_NULL\n\n Params:\n addr (address) - The address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(address addr, string memory message) internal returns (bool result) {\n return AssertAddress.isZero(addr, message);\n }\n\n /*\n Function: isNotZero(address)\n\n Assert that an address is not zero.\n\n : addr != ADDRESS_NULL\n\n Params:\n addr (address) - The address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(address addr, string memory message) internal returns (bool result) {\n return AssertAddress.isNotZero(addr, message);\n }\n\n // ************************************** bool **************************************\n\n /*\n Function: isTrue\n\n Assert that a boolean is 'true'.\n\n : b == true\n\n Params:\n b (bool) - The boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isTrue(bool b, string memory message) internal returns (bool result) {\n return AssertBool.isTrue(b, message);\n }\n\n /*\n Function: isFalse\n\n Assert that a boolean is 'false'.\n\n : b == false\n\n Params:\n b (bool) - The boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isFalse(bool b, string memory message) internal returns (bool result) {\n return AssertBool.isFalse(b, message);\n }\n\n /*\n Function: equal(bool)\n\n Assert that two booleans are equal.\n\n : A == B\n\n Params:\n A (bool) - The first boolean.\n B (bool) - The second boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n bool a,\n bool b,\n string memory message\n ) internal returns (bool result) {\n return AssertBool.equal(a, b, message);\n }\n\n /*\n Function: notEqual(bool)\n\n Assert that two booleans are not equal.\n\n : A != B\n\n Params:\n A (bool) - The first boolean.\n B (bool) - The second boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n bool a,\n bool b,\n string memory message\n ) internal returns (bool result) {\n return AssertBool.notEqual(a, b, message);\n }\n\n // ************************************** uint **************************************\n\n /*\n Function: equal(uint)\n\n Assert that two (256 bit) unsigned integers are equal.\n\n : A == B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n uint256 a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertUint.equal(a, b, message);\n }\n\n /*\n Function: notEqual(uint)\n\n Assert that two (256 bit) unsigned integers are not equal.\n\n : A != B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n uint256 a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertUint.notEqual(a, b, message);\n }\n\n /*\n Function: isAbove(uint)\n\n Assert that the uint 'A' is greater than the uint 'B'.\n\n : A > B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAbove(\n uint256 a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertUint.isAbove(a, b, message);\n }\n\n /*\n Function: isAtLeast(uint)\n\n Assert that the uint 'A' is greater than or equal to the uint 'B'.\n\n : A >= B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtLeast(\n uint256 a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertUint.isAtLeast(a, b, message);\n }\n\n /*\n Function: isBelow(uint)\n\n Assert that the uint 'A' is lesser than the uint 'B'.\n\n : A < B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isBelow(\n uint256 a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertUint.isBelow(a, b, message);\n }\n\n /*\n Function: isAtMost(uint)\n\n Assert that the uint 'A' is lesser than or equal to the uint 'B'.\n\n : A <= B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtMost(\n uint256 a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertUint.isAtMost(a, b, message);\n }\n\n /*\n Function: isZero(uint)\n\n Assert that a (256 bit) unsigned integer is 0.\n\n : number == 0\n\n Params:\n number (uint) - The uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(uint256 number, string memory message) internal returns (bool result) {\n return AssertUint.isZero(number, message);\n }\n\n /*\n Function: isNotZero(uint)\n\n Assert that a (256 bit) unsigned integer is not 0.\n\n : number != 0\n\n Params:\n number (uint) - The uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(uint256 number, string memory message) internal returns (bool result) {\n return AssertUint.isNotZero(number, message);\n }\n\n // ************************************** int **************************************\n\n /*\n Function: equal(int)\n\n Assert that two (256 bit) signed integers are equal.\n\n : A == B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n int256 a,\n int256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertInt.equal(a, b, message);\n }\n\n /*\n Function: notEqual(int)\n\n Assert that two (256 bit) signed integers are not equal.\n\n : A != B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n int256 a,\n int256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertInt.notEqual(a, b, message);\n }\n\n /*\n Function: isAbove(int)\n\n Assert that the int 'A' is greater than the int 'B'.\n\n : A > B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAbove(\n int256 a,\n int256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertInt.isAbove(a, b, message);\n }\n\n /*\n Function: isAtLeast(int)\n\n Assert that the int 'A' is greater than or equal to the int 'B'.\n\n : A >= B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtLeast(\n int256 a,\n int256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertInt.isAtLeast(a, b, message);\n }\n\n /*\n Function: isBelow(int)\n\n Assert that the int 'A' is lesser than the int 'B'.\n\n : A < B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isBelow(\n int256 a,\n int256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertInt.isBelow(a, b, message);\n }\n\n /*\n Function: isAtMost(int)\n\n Assert that the int 'A' is lesser than or equal to the int 'B'.\n\n : A <= B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtMost(\n int256 a,\n int256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertInt.isAtMost(a, b, message);\n }\n\n /*\n Function: isZero(int)\n\n Assert that a (256 bit) signed integer is 0.\n\n : number == 0\n\n Params:\n number (int) - The int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(int256 number, string memory message) internal returns (bool result) {\n return AssertInt.isZero(number, message);\n }\n\n /*\n Function: isNotZero(int)\n\n Assert that a (256 bit) signed integer is not 0.\n\n : number != 0\n\n Params:\n number (int) - The int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(int256 number, string memory message) internal returns (bool result) {\n return AssertInt.isNotZero(number, message);\n }\n\n // ************************************** uint[] **************************************\n\n /*\n Function: equal(uint[])\n\n Assert that two 'uint[ ]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (uint[]) - The first array.\n B (uint[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n uint256[] memory arrA,\n uint256[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertUintArray.equal(arrA, arrB, message);\n }\n\n /*\n Function: notEqual(uint[])\n\n Assert that two 'uint[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (uint[]) - The first string.\n B (uint[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n uint256[] memory arrA,\n uint256[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertUintArray.notEqual(arrA, arrB, message);\n }\n\n /*\n Function: lengthEqual(uint[])\n\n Assert that the length of a 'uint[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (uint[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n uint256[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertUintArray.lengthEqual(arr, length, message);\n }\n\n /*\n Function: lengthNotEqual(uint[])\n\n Assert that the length of a 'uint[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (uint[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n uint256[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertUintArray.lengthNotEqual(arr, length, message);\n }\n\n // ************************************** int[] **************************************\n\n /*\n Function: equal(int[])\n\n Assert that two 'int[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (int[]) - The first array.\n B (int[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n int256[] memory arrA,\n int256[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertIntArray.equal(arrA, arrB, message);\n }\n\n /*\n Function: notEqual(int[])\n\n Assert that two 'int[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (int[]) - The first string.\n B (int[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n int256[] memory arrA,\n int256[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertIntArray.notEqual(arrA, arrB, message);\n }\n\n /*\n Function: lengthEqual(int[])\n\n Assert that the length of an 'int[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (int[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n int256[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertIntArray.lengthEqual(arr, length, message);\n }\n\n /*\n Function: lengthNotEqual(int[])\n\n Assert that the length of an 'int[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (int[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n int256[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertIntArray.lengthNotEqual(arr, length, message);\n }\n\n // ************************************** address[] **************************************\n\n /*\n Function: equal(address[])\n\n Assert that two 'address[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (address[]) - The first array.\n B (address[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n address[] memory arrA,\n address[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertAddressArray.equal(arrA, arrB, message);\n }\n\n /*\n Function: notEqual(address[])\n\n Assert that two 'address[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (address[]) - The first string.\n B (address[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n address[] memory arrA,\n address[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertAddressArray.notEqual(arrA, arrB, message);\n }\n\n /*\n Function: lengthEqual(address[])\n\n Assert that the length of an 'address[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (address[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n address[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertAddressArray.lengthEqual(arr, length, message);\n }\n\n /*\n Function: lengthNotEqual(address[])\n\n Assert that the length of an 'address[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (address[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n address[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertAddressArray.lengthNotEqual(arr, length, message);\n }\n\n // ************************************** address payable[] **************************************\n\n /*\n Function: equal(address payable[])\n\n Assert that two 'address payable[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (address payable[]) - The first array.\n B (address payable[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n // function equal(address payable[] memory arrA, address payable[] memory arrB, string memory message) internal returns (bool result) {\n // return AssertAddressPayableArray.equal(arrA, arrB, message);\n // }\n\n /*\n Function: notEqual(address payable[])\n\n Assert that two 'address payable[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (address payable[]) - The first string.\n B (address payable[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n // function notEqual(address payable[] memory arrA, address payable[] memory arrB, string memory message) internal returns (bool result) {\n // return AssertAddressPayableArray.notEqual(arrA, arrB, message);\n // }\n\n /*\n Function: lengthEqual(address payable[])\n\n Assert that the length of an 'address payable[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (address payable[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n // function lengthEqual(address payable[] memory arr, uint length, string memory message) internal returns (bool result) {\n // return AssertAddressPayableArray.lengthEqual(arr, length, message);\n // }\n\n /*\n Function: lengthNotEqual(address payable[])\n\n Assert that the length of an 'address payable[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (address payable[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n // function lengthNotEqual(address payable[] memory arr, uint length, string memory message) internal returns (bool result) {\n // return AssertAddressPayableArray.lengthNotEqual(arr, length, message);\n // }\n\n // ************************************** bytes32[] **************************************\n\n /*\n Function: equal(bytes32[])\n\n Assert that two 'bytes32[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (bytes32[]) - The first array.\n B (bytes32[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n bytes32[] memory arrA,\n bytes32[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertBytes32Array.equal(arrA, arrB, message);\n }\n\n /*\n Function: notEqual(bytes32[])\n\n Assert that two 'bytes32[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (bytes32[]) - The first string.\n B (bytes32[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n bytes32[] memory arrA,\n bytes32[] memory arrB,\n string memory message\n ) internal returns (bool result) {\n return AssertBytes32Array.notEqual(arrA, arrB, message);\n }\n\n /*\n Function: lengthEqual(bytes32[])\n\n Assert that the length of an 'bytes32[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (bytes32[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n bytes32[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertBytes32Array.lengthEqual(arr, length, message);\n }\n\n /*\n Function: lengthNotEqual(bytes32[])\n\n Assert that the length of an 'bytes32[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (bytes32[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n bytes32[] memory arr,\n uint256 length,\n string memory message\n ) internal returns (bool result) {\n return AssertBytes32Array.lengthNotEqual(arr, length, message);\n }\n\n // ************************************** balances **************************************\n\n /*\n Function: balanceEqual\n\n Assert that the balance of an account 'A' is equal to a given number 'b'.\n\n : A.balance = b\n\n Params:\n A (address) - The first address.\n b (uint) - The balance.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceEqual(\n address a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertBalance.balanceEqual(a, b, message);\n }\n\n /*\n Function: balanceNotEqual\n\n Assert that the balance of an account 'A' is not equal to a given number 'b'.\n\n : A.balance != b\n\n Params:\n A (address) - The first address.\n b (uint) - The balance.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceNotEqual(\n address a,\n uint256 b,\n string memory message\n ) internal returns (bool result) {\n return AssertBalance.balanceNotEqual(a, b, message);\n }\n\n /*\n Function: balanceIsZero\n\n Assert that the balance of an account 'A' is zero.\n\n : A.balance == 0\n\n Params:\n A (address) - The first address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceIsZero(address a, string memory message) internal returns (bool result) {\n return AssertBalance.balanceIsZero(a, message);\n }\n\n /*\n Function: balanceIsNotZero\n\n Assert that the balance of an account 'A' is not zero.\n\n : A.balance != 0\n\n Params:\n A (address) - The first address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceIsNotZero(address a, string memory message) internal returns (bool result) {\n return AssertBalance.balanceIsNotZero(a, message);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertString.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertString {\n // Constant: STRING_NULL\n // The null string: \"\"\n string constant STRING_NULL = \"\";\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** strings **************************************\n\n /*\n Function: equal(string)\n\n Assert that two strings are equal.\n\n : _stringsEqual(A, B) == true\n\n Params:\n A (string) - The first string.\n B (string) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n string memory a,\n string memory b,\n string memory message\n ) public returns (bool result) {\n result = _stringsEqual(a, b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: notEqual(string)\n\n Assert that two strings are not equal.\n\n : _stringsEqual(A, B) == false\n\n Params:\n A (string) - The first string.\n B (string) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n string memory a,\n string memory b,\n string memory message\n ) public returns (bool result) {\n result = !_stringsEqual(a, b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isEmpty(string)\n\n Assert that a string is empty.\n\n : _stringsEqual(str, STRING_NULL) == true\n\n Params:\n str (string) - The string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isEmpty(string memory str, string memory message) public returns (bool result) {\n result = _stringsEqual(str, STRING_NULL);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(str, \"Tested\"), message));\n }\n\n /*\n Function: isNotEmpty(string)\n\n Assert that a string is not empty.\n\n : _stringsEqual(str, STRING_NULL) == false\n\n Params:\n str (string) - The string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotEmpty(string memory str, string memory message) public returns (bool result) {\n result = !_stringsEqual(str, STRING_NULL);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(str, \"Tested\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _stringsEqual\n\n Compares two strings. Taken from the StringUtils contract in the Ethereum Dapp-bin\n (https://github.com/ethereum/dapp-bin/blob/master/library/stringUtils.sol).\n\n Params:\n a (string) - The first string.\n b (string) - The second string.\n\n Returns:\n result (bool) - 'true' if the strings are equal, otherwise 'false'.\n */\n function _stringsEqual(string memory a, string memory b) internal pure returns (bool result) {\n bytes memory ba = bytes(a);\n bytes memory bb = bytes(b);\n\n if (ba.length != bb.length) return false;\n for (uint256 i = 0; i < ba.length; i++) {\n if (ba[i] != bb[i]) return false;\n }\n return true;\n }\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _appendTagged(string)\n\n Append a tagged value to a string.\n\n Params:\n tagged (string) - The tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged)\"\n */\n function _appendTagged(string memory tagged, string memory str) internal pure returns (string memory) {\n bytes memory taggedB = bytes(tagged);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 tl = taggedB.length;\n\n bytes memory newB = new bytes(sl + tl + 3);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < tl; i++) newB[j++] = taggedB[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertBytes32.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertBytes32 {\n // Constant: BYTES32_NULL\n // The null bytes32: 0\n bytes32 constant BYTES32_NULL = 0x0;\n\n bytes1 constant MINUS = bytes1(\"-\");\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** bytes32 **************************************\n\n /*\n Function: equal(bytes32)\n\n Assert that two 'bytes32' are equal.\n\n : A == B\n\n Params:\n A (bytes32) - The first 'bytes32'.\n B (bytes32) - The second 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n bytes32 a,\n bytes32 b,\n string memory message\n ) public returns (bool result) {\n result = (a == b);\n _report(result, message);\n }\n\n /*\n Function: notEqual(bytes32)\n\n Assert that two 'bytes32' are not equal.\n\n : A != B\n\n Params:\n A (bytes32) - The first 'bytes32'.\n B (bytes32) - The second 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n bytes32 a,\n bytes32 b,\n string memory message\n ) public returns (bool result) {\n result = (a != b);\n _report(result, message);\n }\n\n /*\n Function: isZero(bytes32)\n\n Assert that a 'bytes32' is zero.\n\n : bts == BYTES32_NULL\n\n Params:\n bts (bytes32) - The 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(bytes32 bts, string memory message) public returns (bool result) {\n result = (bts == BYTES32_NULL);\n _report(result, message);\n }\n\n /*\n Function: isNotZero(bytes32)\n\n Assert that a 'bytes32' is not zero.\n\n : bts != BYTES32_NULL\n\n Params:\n bts (bytes32) - The 'bytes32'.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(bytes32 bts, string memory message) public returns (bool result) {\n result = (bts != BYTES32_NULL);\n _report(result, message);\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertAddress.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertAddress {\n // Constant: ADDRESS_NULL\n // The null address: 0\n address constant ADDRESS_NULL = 0x0000000000000000000000000000000000000000;\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** address **************************************\n\n /*\n Function: equal(address)\n\n Assert that two addresses are equal.\n\n : A == B\n\n Params:\n A (address) - The first address.\n B (address) - The second address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n address a,\n address b,\n string memory message\n ) public returns (bool result) {\n result = (a == b);\n _report(result, message);\n }\n\n /*\n Function: notEqual(address)\n\n Assert that two addresses are not equal.\n\n : A != B\n\n Params:\n A (address) - The first address.\n B (address) - The second address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n address a,\n address b,\n string memory message\n ) public returns (bool result) {\n result = (a != b);\n _report(result, message);\n }\n\n /*\n Function: isZero(address)\n\n Assert that an address is zero.\n\n : addr == ADDRESS_NULL\n\n Params:\n addr (address) - The address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(address addr, string memory message) public returns (bool result) {\n result = (addr == ADDRESS_NULL);\n _report(result, message);\n }\n\n /*\n Function: isNotZero(address)\n\n Assert that an address is not zero.\n\n : addr != ADDRESS_NULL\n\n Params:\n addr (address) - The address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(address addr, string memory message) public returns (bool result) {\n result = (addr != ADDRESS_NULL);\n _report(result, message);\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertBool.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertBool {\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** bool **************************************\n\n /*\n Function: isTrue\n\n Assert that a boolean is 'true'.\n\n : b == true\n\n Params:\n b (bool) - The boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isTrue(bool b, string memory message) public returns (bool result) {\n result = b;\n _report(result, message);\n }\n\n /*\n Function: isFalse\n\n Assert that a boolean is 'false'.\n\n : b == false\n\n Params:\n b (bool) - The boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isFalse(bool b, string memory message) public returns (bool result) {\n result = !b;\n _report(result, message);\n }\n\n /*\n Function: equal(bool)\n\n Assert that two booleans are equal.\n\n : A == B\n\n Params:\n A (bool) - The first boolean.\n B (bool) - The second boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n bool a,\n bool b,\n string memory message\n ) public returns (bool result) {\n result = (a == b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: notEqual(bool)\n\n Assert that two booleans are not equal.\n\n : A != B\n\n Params:\n A (bool) - The first boolean.\n B (bool) - The second boolean.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n bool a,\n bool b,\n string memory message\n ) public returns (bool result) {\n result = (a != b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _ltoa\n\n Convert an boolean to a string.\n\n Params:\n val (bool) - The boolean.\n\n Returns:\n result (string) - \"true\" if true, \"false\" if false.\n */\n function _ltoa(bool val) internal pure returns (string memory) {\n bytes memory b;\n if (val) {\n b = new bytes(4);\n b[0] = \"t\";\n b[1] = \"r\";\n b[2] = \"u\";\n b[3] = \"e\";\n return string(b);\n } else {\n b = new bytes(5);\n b[0] = \"f\";\n b[1] = \"a\";\n b[2] = \"l\";\n b[3] = \"s\";\n b[4] = \"e\";\n return string(b);\n }\n }\n\n /*\n function htoa(address addr) constant returns (string) {\n bytes memory bts = new bytes(40);\n bytes20 addrBts = bytes20(addr);\n for (uint i = 0; i < 20; i++) {\n bts[2*i] = addrBts[i] % 16;\n bts[2*i + 1] = (addrBts[i] / 16) % 16;\n }\n return string(bts);\n }\n */\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(bool)\n\n Add a tag to a boolean.\n\n Params:\n value (bool) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _ltoa(value)\"\n */\n function _tag(bool value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _ltoa(value);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertUint.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertUint {\n uint8 constant ZERO = uint8(bytes1(\"0\"));\n uint8 constant A = uint8(bytes1(\"a\"));\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** uint **************************************\n\n /*\n Function: equal(uint)\n\n Assert that two (256 bit) unsigned integers are equal.\n\n : A == B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n uint256 a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a == b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: notEqual(uint)\n\n Assert that two (256 bit) unsigned integers are not equal.\n\n : A != B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n uint256 a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a != b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isAbove(uint)\n\n Assert that the uint 'A' is greater than the uint 'B'.\n\n : A > B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAbove(\n uint256 a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a > b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isAtLeast(uint)\n\n Assert that the uint 'A' is greater than or equal to the uint 'B'.\n\n : A >= B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtLeast(\n uint256 a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a >= b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isBelow(uint)\n\n Assert that the uint 'A' is lesser than the uint 'B'.\n\n : A < B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isBelow(\n uint256 a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a < b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isAtMost(uint)\n\n Assert that the uint 'A' is lesser than or equal to the uint 'B'.\n\n : A <= B\n\n Params:\n A (uint) - The first uint.\n B (uint) - The second uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtMost(\n uint256 a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a <= b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isZero(uint)\n\n Assert that a (256 bit) unsigned integer is 0.\n\n : number == 0\n\n Params:\n number (uint) - The uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(uint256 number, string memory message) public returns (bool result) {\n result = (number == 0);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(number, \"Tested\"), message));\n }\n\n /*\n Function: isNotZero(uint)\n\n Assert that a (256 bit) unsigned integer is not 0.\n\n : number != 0\n\n Params:\n number (uint) - The uint.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(uint256 number, string memory message) public returns (bool result) {\n result = (number != 0);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(number, \"Tested\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _utoa(uint)\n\n Convert an unsigned integer to a string.\n\n Params:\n n (uint) - The unsigned integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n\n Returns:\n result (string) - The resulting string.\n */\n function _utoa(uint256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n while (n > 0) {\n bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii.\n n /= radix;\n }\n // Reverse\n bytes memory rev = new bytes(i);\n for (uint256 j = 0; j < i; j++) rev[j] = bts[i - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint8)\n\n Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',\n numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.\n\n Params:\n u (uint8) - The unsigned 8-bit integer.\n\n Returns:\n result (string) - The ASCII byte.\n */\n function _utoa(uint8 u) internal pure returns (bytes1) {\n if (u < 10) return bytes1(u + ZERO);\n else if (u < 16) return bytes1(u - 10 + A);\n else return 0;\n }\n\n /*\n function htoa(address addr) constant returns (string) {\n bytes memory bts = new bytes(40);\n bytes20 addrBts = bytes20(addr);\n for (uint i = 0; i < 20; i++) {\n bts[2*i] = addrBts[i] % 16;\n bts[2*i + 1] = (addrBts[i] / 16) % 16;\n }\n return string(bts);\n }\n */\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(uint)\n\n Add a tag to an uint.\n\n Params:\n value (uint) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _utoa(value)\"\n */\n function _tag(uint256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _utoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string)\n\n Append a tagged value to a string.\n\n Params:\n tagged (string) - The tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged)\"\n */\n function _appendTagged(string memory tagged, string memory str) internal pure returns (string memory) {\n bytes memory taggedB = bytes(tagged);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 tl = taggedB.length;\n\n bytes memory newB = new bytes(sl + tl + 3);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < tl; i++) newB[j++] = taggedB[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertInt.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertInt {\n uint8 constant ZERO = uint8(bytes1(\"0\"));\n uint8 constant A = uint8(bytes1(\"a\"));\n\n bytes1 constant MINUS = bytes1(\"-\");\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** int **************************************\n\n /*\n Function: equal(int)\n\n Assert that two (256 bit) signed integers are equal.\n\n : A == B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n int256 a,\n int256 b,\n string memory message\n ) public returns (bool result) {\n result = (a == b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: notEqual(int)\n\n Assert that two (256 bit) signed integers are not equal.\n\n : A != B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n int256 a,\n int256 b,\n string memory message\n ) public returns (bool result) {\n result = (a != b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isAbove(int)\n\n Assert that the int 'A' is greater than the int 'B'.\n\n : A > B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAbove(\n int256 a,\n int256 b,\n string memory message\n ) public returns (bool result) {\n result = (a > b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isAtLeast(int)\n\n Assert that the int 'A' is greater than or equal to the int 'B'.\n\n : A >= B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtLeast(\n int256 a,\n int256 b,\n string memory message\n ) public returns (bool result) {\n result = (a >= b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isBelow(int)\n\n Assert that the int 'A' is lesser than the int 'B'.\n\n : A < B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isBelow(\n int256 a,\n int256 b,\n string memory message\n ) public returns (bool result) {\n result = (a < b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isAtMost(int)\n\n Assert that the int 'A' is lesser than or equal to the int 'B'.\n\n : A <= B\n\n Params:\n A (int) - The first int.\n B (int) - The second int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isAtMost(\n int256 a,\n int256 b,\n string memory message\n ) public returns (bool result) {\n result = (a <= b);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(a, \"Tested\"), _tag(b, \"Against\"), message));\n }\n\n /*\n Function: isZero(int)\n\n Assert that a (256 bit) signed integer is 0.\n\n : number == 0\n\n Params:\n number (int) - The int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isZero(int256 number, string memory message) public returns (bool result) {\n result = (number == 0);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(number, \"Tested\"), message));\n }\n\n /*\n Function: isNotZero(int)\n\n Assert that a (256 bit) signed integer is not 0.\n\n : number != 0\n\n Params:\n number (int) - The int.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function isNotZero(int256 number, string memory message) public returns (bool result) {\n result = (number != 0);\n if (result) _report(result, message);\n else _report(result, _appendTagged(_tag(number, \"Tested\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _itoa\n Convert a signed integer to a string. Negative numbers gets a '-' in front, e.g. \"-54\".\n Params:\n n (int) - The integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n Returns:\n result (string) - The resulting string.\n */\n function _itoa(int256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n bool neg = false;\n if (n < 0) {\n n = -n;\n neg = true;\n }\n while (n > 0) {\n bts[i++] = _utoa(uint8(uint256(n) % radix)); // Turn it to ascii.\n n = int256(uint256(n) / radix);\n }\n // Reverse\n uint256 size = i;\n uint256 j = 0;\n bytes memory rev;\n if (neg) {\n size++;\n j = 1;\n rev = new bytes(size);\n rev[0] = MINUS;\n } else rev = new bytes(size);\n\n for (; j < size; j++) rev[j] = bts[size - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint8)\n\n Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',\n numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.\n\n Params:\n u (uint8) - The unsigned 8-bit integer.\n\n Returns:\n result (string) - The ASCII byte.\n */\n function _utoa(uint8 u) internal pure returns (bytes1) {\n if (u < 10) return bytes1(u + ZERO);\n else if (u < 16) return bytes1(u - 10 + A);\n else return 0;\n }\n\n /*\n function htoa(address addr) constant returns (string) {\n bytes memory bts = new bytes(40);\n bytes20 addrBts = bytes20(addr);\n for (uint i = 0; i < 20; i++) {\n bts[2*i] = addrBts[i] % 16;\n bts[2*i + 1] = (addrBts[i] / 16) % 16;\n }\n return string(bts);\n }\n */\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(int)\n\n Add a tag to an int.\n\n Params:\n value (int) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _itoa(value)\"\n */\n function _tag(int256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _itoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string)\n\n Append a tagged value to a string.\n\n Params:\n tagged (string) - The tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged)\"\n */\n function _appendTagged(string memory tagged, string memory str) internal pure returns (string memory) {\n bytes memory taggedB = bytes(tagged);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 tl = taggedB.length;\n\n bytes memory newB = new bytes(sl + tl + 3);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < tl; i++) newB[j++] = taggedB[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertUintArray.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertUintArray {\n uint8 constant ZERO = uint8(bytes1(\"0\"));\n uint8 constant A = uint8(bytes1(\"a\"));\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** uint[] **************************************\n\n /*\n Function: equal(uint[])\n\n Assert that two 'uint[ ]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (uint[]) - The first array.\n B (uint[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n uint256[] memory arrA,\n uint256[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n _report(result, message);\n }\n\n /*\n Function: notEqual(uint[])\n\n Assert that two 'uint[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (uint[]) - The first string.\n B (uint[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n uint256[] memory arrA,\n uint256[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n result = !result;\n _report(result, message);\n }\n\n /*\n Function: lengthEqual(uint[])\n\n Assert that the length of a 'uint[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (uint[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n uint256[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength == length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /*\n Function: lengthNotEqual(uint[])\n\n Assert that the length of a 'uint[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (uint[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n uint256[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength != arr.length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _utoa(uint)\n\n Convert an unsigned integer to a string.\n\n Params:\n n (uint) - The unsigned integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n\n Returns:\n result (string) - The resulting string.\n */\n function _utoa(uint256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n while (n > 0) {\n bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii.\n n /= radix;\n }\n // Reverse\n bytes memory rev = new bytes(i);\n for (uint256 j = 0; j < i; j++) rev[j] = bts[i - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint8)\n\n Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',\n numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.\n\n Params:\n u (uint8) - The unsigned 8-bit integer.\n\n Returns:\n result (string) - The ASCII byte.\n */\n function _utoa(uint8 u) internal pure returns (bytes1) {\n if (u < 10) return bytes1(u + ZERO);\n else if (u < 16) return bytes1(u - 10 + A);\n else return 0;\n }\n\n /*\n function htoa(address addr) constant returns (string) {\n bytes memory bts = new bytes(40);\n bytes20 addrBts = bytes20(addr);\n for (uint i = 0; i < 20; i++) {\n bts[2*i] = addrBts[i] % 16;\n bts[2*i + 1] = (addrBts[i] / 16) % 16;\n }\n return string(bts);\n }\n */\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(uint)\n\n Add a tag to an uint.\n\n Params:\n value (uint) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _utoa(value)\"\n */\n function _tag(uint256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _utoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string)\n\n Append a tagged value to a string.\n\n Params:\n tagged (string) - The tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged)\"\n */\n function _appendTagged(string memory tagged, string memory str) internal pure returns (string memory) {\n bytes memory taggedB = bytes(tagged);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 tl = taggedB.length;\n\n bytes memory newB = new bytes(sl + tl + 3);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < tl; i++) newB[j++] = taggedB[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertIntArray.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertIntArray {\n uint8 constant ZERO = uint8(bytes1(\"0\"));\n uint8 constant A = uint8(bytes1(\"a\"));\n\n bytes1 constant MINUS = bytes1(\"-\");\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** int[] **************************************\n\n /*\n Function: equal(int[])\n\n Assert that two 'int[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (int[]) - The first array.\n B (int[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n int256[] memory arrA,\n int256[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n _report(result, message);\n }\n\n /*\n Function: notEqual(int[])\n\n Assert that two 'int[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (int[]) - The first string.\n B (int[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n int256[] memory arrA,\n int256[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n result = !result;\n _report(result, message);\n }\n\n /*\n Function: lengthEqual(int[])\n\n Assert that the length of an 'int[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (int[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n int256[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength == length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /*\n Function: lengthNotEqual(int[])\n\n Assert that the length of an 'int[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (int[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n int256[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength != arr.length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _itoa\n Convert a signed integer to a string. Negative numbers gets a '-' in front, e.g. \"-54\".\n Params:\n n (int) - The integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n Returns:\n result (string) - The resulting string.\n */\n function _itoa(int256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n bool neg = false;\n if (n < 0) {\n n = -n;\n neg = true;\n }\n while (n > 0) {\n bts[i++] = _utoa(uint8(uint256(n) % radix)); // Turn it to ascii.\n n = int256(uint256(n) / radix);\n }\n // Reverse\n uint256 size = i;\n uint256 j = 0;\n bytes memory rev;\n if (neg) {\n size++;\n j = 1;\n rev = new bytes(size);\n rev[0] = MINUS;\n } else rev = new bytes(size);\n\n for (; j < size; j++) rev[j] = bts[size - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint)\n\n Convert an unsigned integer to a string.\n\n Params:\n n (uint) - The unsigned integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n\n Returns:\n result (string) - The resulting string.\n */\n function _utoa(uint256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n while (n > 0) {\n bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii.\n n /= radix;\n }\n // Reverse\n bytes memory rev = new bytes(i);\n for (uint256 j = 0; j < i; j++) rev[j] = bts[i - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint8)\n\n Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',\n numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.\n\n Params:\n u (uint8) - The unsigned 8-bit integer.\n\n Returns:\n result (string) - The ASCII byte.\n */\n function _utoa(uint8 u) internal pure returns (bytes1) {\n if (u < 10) return bytes1(u + ZERO);\n else if (u < 16) return bytes1(u - 10 + A);\n else return 0;\n }\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(int)\n\n Add a tag to an int.\n\n Params:\n value (int) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _itoa(value)\"\n */\n function _tag(int256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _itoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _tag(uint)\n\n Add a tag to an uint.\n\n Params:\n value (uint) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _utoa(value)\"\n */\n function _tag(uint256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _utoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertAddressArray.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertAddressArray {\n uint8 constant ZERO = uint8(bytes1(\"0\"));\n uint8 constant A = uint8(bytes1(\"a\"));\n\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** address[] **************************************\n\n /*\n Function: equal(address[])\n\n Assert that two 'address[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (address[]) - The first array.\n B (address[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n address[] memory arrA,\n address[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n _report(result, message);\n }\n\n /*\n Function: notEqual(address[])\n\n Assert that two 'address[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (address[]) - The first string.\n B (address[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n address[] memory arrA,\n address[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n result = !result;\n _report(result, message);\n }\n\n /*\n Function: lengthEqual(address[])\n\n Assert that the length of an 'address[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (address[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n address[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength == length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /*\n Function: lengthNotEqual(address[])\n\n Assert that the length of an 'address[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (address[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n address[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength != arr.length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _utoa(uint)\n\n Convert an unsigned integer to a string.\n\n Params:\n n (uint) - The unsigned integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n\n Returns:\n result (string) - The resulting string.\n */\n function _utoa(uint256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n while (n > 0) {\n bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii.\n n /= radix;\n }\n // Reverse\n bytes memory rev = new bytes(i);\n for (uint256 j = 0; j < i; j++) rev[j] = bts[i - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint8)\n\n Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',\n numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.\n\n Params:\n u (uint8) - The unsigned 8-bit integer.\n\n Returns:\n result (string) - The ASCII byte.\n */\n function _utoa(uint8 u) internal pure returns (bytes1) {\n if (u < 10) return bytes1(u + ZERO);\n else if (u < 16) return bytes1(u - 10 + A);\n else return 0;\n }\n\n /*\n function htoa(address addr) constant returns (string) {\n bytes memory bts = new bytes(40);\n bytes20 addrBts = bytes20(addr);\n for (uint i = 0; i < 20; i++) {\n bts[2*i] = addrBts[i] % 16;\n bts[2*i + 1] = (addrBts[i] / 16) % 16;\n }\n return string(bts);\n }\n */\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(uint)\n\n Add a tag to an uint.\n\n Params:\n value (uint) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _utoa(value)\"\n */\n function _tag(uint256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _utoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertBytes32Array.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertBytes32Array {\n uint8 constant ZERO = uint8(bytes1(\"0\"));\n uint8 constant A = uint8(bytes1(\"a\"));\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** bytes32[] **************************************\n\n /*\n Function: equal(bytes32[])\n\n Assert that two 'bytes32[]' are equal.\n\n : arrA.length == arrB.length\n\n and, for all valid indices 'i'\n\n : arrA[i] == arrB[i]\n\n Params:\n A (bytes32[]) - The first array.\n B (bytes32[]) - The second array.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function equal(\n bytes32[] memory arrA,\n bytes32[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n _report(result, message);\n }\n\n /*\n Function: notEqual(bytes32[])\n\n Assert that two 'bytes32[]' are not equal.\n\n : arrA.length != arrB.length\n\n or, for some valid index 'i'\n\n : arrA[i] != arrB[i]\n\n Params:\n A (bytes32[]) - The first string.\n B (bytes32[]) - The second string.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function notEqual(\n bytes32[] memory arrA,\n bytes32[] memory arrB,\n string memory message\n ) public returns (bool result) {\n result = arrA.length == arrB.length;\n if (result) {\n for (uint256 i = 0; i < arrA.length; i++) {\n if (arrA[i] != arrB[i]) {\n result = false;\n break;\n }\n }\n }\n result = !result;\n _report(result, message);\n }\n\n /*\n Function: lengthEqual(bytes32[])\n\n Assert that the length of an 'bytes32[]' is equal to a given value.\n\n : arr.length == length\n\n Params:\n arr (bytes32[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthEqual(\n bytes32[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength == length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /*\n Function: lengthNotEqual(bytes32[])\n\n Assert that the length of an 'bytes32[]' is not equal to a given value.\n\n : arr.length != length\n\n Params:\n arr (bytes32[]) - The array.\n length (uint) - The length.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function lengthNotEqual(\n bytes32[] memory arr,\n uint256 length,\n string memory message\n ) public returns (bool result) {\n uint256 arrLength = arr.length;\n if (arrLength != arr.length) _report(result, \"\");\n else _report(result, _appendTagged(_tag(arrLength, \"Tested\"), _tag(length, \"Against\"), message));\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n\n /*\n Function: _utoa(uint)\n\n Convert an unsigned integer to a string.\n\n Params:\n n (uint) - The unsigned integer.\n radix (uint8) - A number between 2 and 16 (inclusive). Characters used are 0-9,a-f\n\n Returns:\n result (string) - The resulting string.\n */\n function _utoa(uint256 n, uint8 radix) internal pure returns (string memory) {\n if (n == 0 || radix < 2 || radix > 16) return \"0\";\n bytes memory bts = new bytes(256);\n uint256 i;\n while (n > 0) {\n bts[i++] = _utoa(uint8(n % radix)); // Turn it to ascii.\n n /= radix;\n }\n // Reverse\n bytes memory rev = new bytes(i);\n for (uint256 j = 0; j < i; j++) rev[j] = bts[i - j - 1];\n return string(rev);\n }\n\n /*\n Function: _utoa(uint8)\n\n Convert an unsigned 8-bit integer to its ASCII byte representation. Numbers 0-9 are converted to '0'-'9',\n numbers 10-16 to 'a'-'f'. Numbers larger then 16 return the null byte.\n\n Params:\n u (uint8) - The unsigned 8-bit integer.\n\n Returns:\n result (string) - The ASCII byte.\n */\n function _utoa(uint8 u) internal pure returns (bytes1) {\n if (u < 10) return bytes1(u + ZERO);\n else if (u < 16) return bytes1(u - 10 + A);\n else return 0;\n }\n\n /*\n function htoa(address addr) constant returns (string) {\n bytes memory bts = new bytes(40);\n bytes20 addrBts = bytes20(addr);\n for (uint i = 0; i < 20; i++) {\n bts[2*i] = addrBts[i] % 16;\n bts[2*i + 1] = (addrBts[i] / 16) % 16;\n }\n return string(bts);\n }\n \n */\n\n /*\n Function: _tag(string)\n\n Add a tag to a string. The 'value' and 'tag' strings are returned on the form \"tag: value\".\n\n Params:\n value (string) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: value\"\n */\n function _tag(string memory value, string memory tag) internal pure returns (string memory) {\n bytes memory valueB = bytes(value);\n bytes memory tagB = bytes(tag);\n\n uint256 vl = valueB.length;\n uint256 tl = tagB.length;\n\n bytes memory newB = new bytes(vl + tl + 2);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < tl; i++) newB[j++] = tagB[i];\n newB[j++] = \":\";\n newB[j++] = \" \";\n for (i = 0; i < vl; i++) newB[j++] = valueB[i];\n\n return string(newB);\n }\n\n /*\n Function: _tag(uint)\n\n Add a tag to an uint.\n\n Params:\n value (uint) - The value.\n tag (string) - The tag.\n\n Returns:\n result (string) - \"tag: _utoa(value)\"\n */\n function _tag(uint256 value, string memory tag) internal pure returns (string memory) {\n string memory nstr = _utoa(value, 10);\n return _tag(nstr, tag);\n }\n\n /*\n Function: _appendTagged(string, string)\n\n Append two tagged values to a string.\n\n Params:\n tagged0 (string) - The first tagged value.\n tagged1 (string) - The second tagged value.\n str (string) - The string.\n\n Returns:\n result (string) - \"str (tagged0, tagged1)\"\n */\n function _appendTagged(\n string memory tagged0,\n string memory tagged1,\n string memory str\n ) internal pure returns (string memory) {\n bytes memory tagged0B = bytes(tagged0);\n bytes memory tagged1B = bytes(tagged1);\n bytes memory strB = bytes(str);\n\n uint256 sl = strB.length;\n uint256 t0l = tagged0B.length;\n uint256 t1l = tagged1B.length;\n\n bytes memory newB = new bytes(sl + t0l + t1l + 5);\n\n uint256 i;\n uint256 j;\n\n for (i = 0; i < sl; i++) newB[j++] = strB[i];\n newB[j++] = \" \";\n newB[j++] = \"(\";\n for (i = 0; i < t0l; i++) newB[j++] = tagged0B[i];\n newB[j++] = \",\";\n newB[j++] = \" \";\n for (i = 0; i < t1l; i++) newB[j++] = tagged1B[i];\n newB[j++] = \")\";\n\n return string(newB);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertBalance.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertBalance {\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** balances **************************************\n\n /*\n Function: balanceEqual\n\n Assert that the balance of an account 'A' is equal to a given number 'b'.\n\n : A.balance = b\n\n Params:\n A (address) - The first address.\n b (uint) - The balance.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceEqual(\n address a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a.balance == b);\n _report(result, message);\n }\n\n /*\n Function: balanceNotEqual\n\n Assert that the balance of an account 'A' is not equal to a given number 'b'.\n\n : A.balance != b\n\n Params:\n A (address) - The first address.\n b (uint) - The balance.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceNotEqual(\n address a,\n uint256 b,\n string memory message\n ) public returns (bool result) {\n result = (a.balance != b);\n _report(result, message);\n }\n\n /*\n Function: balanceIsZero\n\n Assert that the balance of an account 'A' is zero.\n\n : A.balance == 0\n\n Params:\n A (address) - The first address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceIsZero(address a, string memory message) public returns (bool result) {\n result = (a.balance == 0);\n _report(result, message);\n }\n\n /*\n Function: balanceIsNotZero\n\n Assert that the balance of an account 'A' is not zero.\n\n : A.balance != 0\n\n Params:\n A (address) - The first address.\n message (string) - A message that is sent if the assertion fails.\n\n Returns:\n result (bool) - The result.\n */\n function balanceIsNotZero(address a, string memory message) public returns (bool result) {\n result = (a.balance != 0);\n _report(result, message);\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n}\n" + }, + "contracts/test/helpers/truffle/AssertGeneral.sol": { + "content": "//SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nlibrary AssertGeneral {\n /*\n Event: TestEvent\n\n Fired when an assertion is made.\n\n Params:\n result (bool) - Whether or not the assertion holds.\n message (string) - A message to display if the assertion does not hold.\n */\n event TestEvent(bool indexed result, string message);\n\n // ************************************** general **************************************\n\n /*\n Function: fail()\n\n Mark the test as failed.\n\n Params:\n message (string) - A message associated with the failure.\n\n Returns:\n result (bool) - false.\n */\n function fail(string memory message) public returns (bool result) {\n _report(false, message);\n return false;\n }\n\n /******************************** internal ********************************/\n\n /*\n Function: _report\n\n Internal function for triggering .\n\n Params:\n result (bool) - The test result (true or false).\n message (string) - The message that is sent if the assertion fails.\n */\n function _report(bool result, string memory message) internal {\n if (result) emit TestEvent(true, \"\");\n else emit TestEvent(false, message);\n }\n}\n" + }, + "contracts/test/TestSortedDoublyLLUpdateKey.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/SortedDoublyLLFixture.sol\";\nimport \"./helpers/RevertProxy.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestSortedDoublyLLUpdateKey {\n address[] ids = [address(1), address(2), address(3), address(4), address(5), address(6)];\n uint256[] keys = [uint256(13), uint256(11), uint256(9), uint256(7), uint256(5), uint256(3)];\n\n SortedDoublyLLFixture fixture;\n RevertProxy proxy;\n\n function beforeAll() public {\n proxy = new RevertProxy();\n }\n\n function beforeEach() public {\n fixture = new SortedDoublyLLFixture();\n fixture.setMaxSize(10);\n }\n\n function test_updateKey_missingId() public {\n SortedDoublyLLFixture(address(proxy)).updateKey(ids[3], 5, address(0), address(0));\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n\n function test_updateKey_increaseNoHint() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n uint256 newKey = keys[3] + 3;\n fixture.updateKey(ids[3], newKey, address(0), address(0));\n Assert.equal(fixture.getKey(ids[3]), newKey, \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[2], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[1], \"wrong prev\");\n Assert.equal(fixture.getNext(ids[1]), ids[3], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[2]), ids[3], \"wrong prev\");\n }\n\n function test_updateKey_decreaseNoHint() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n uint256 newKey = keys[3] - 3;\n fixture.updateKey(ids[3], newKey, address(0), address(0));\n Assert.equal(fixture.getKey(ids[3]), newKey, \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[5], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[4], \"wrong prev\");\n Assert.equal(fixture.getNext(ids[4]), ids[3], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[5]), ids[3], \"wrong prev\");\n }\n\n function test_updateKey_zeroNewKey() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n\n uint256 newKey = 0;\n fixture.updateKey(ids[2], newKey, address(0), address(0));\n Assert.isFalse(fixture.contains(ids[2]), \"list should not contain id after updating with newKey = 0\");\n }\n}\n" + }, + "contracts/test/mocks/SortedDoublyLLFixture.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../libraries/SortedDoublyLL.sol\";\n\ncontract SortedDoublyLLFixture {\n using SortedDoublyLL for SortedDoublyLL.Data;\n\n SortedDoublyLL.Data list;\n\n function setMaxSize(uint256 _size) public {\n list.setMaxSize(_size);\n }\n\n function insert(\n address _id,\n uint256 _key,\n address _prevId,\n address _nextId\n ) public {\n list.insert(_id, _key, _prevId, _nextId);\n }\n\n function remove(address _id) public {\n list.remove(_id);\n }\n\n function updateKey(\n address _id,\n uint256 _newKey,\n address _prevId,\n address _nextId\n ) public {\n list.updateKey(_id, _newKey, _prevId, _nextId);\n }\n\n function contains(address _id) public view returns (bool) {\n return list.contains(_id);\n }\n\n function getSize() public view returns (uint256) {\n return list.getSize();\n }\n\n function getMaxSize() public view returns (uint256) {\n return list.maxSize;\n }\n\n function getKey(address _id) public view returns (uint256) {\n return list.getKey(_id);\n }\n\n function getFirst() public view returns (address) {\n return list.getFirst();\n }\n\n function getLast() public view returns (address) {\n return list.getLast();\n }\n\n function getNext(address _id) public view returns (address) {\n return list.getNext(_id);\n }\n\n function getPrev(address _id) public view returns (address) {\n return list.getPrev(_id);\n }\n}\n" + }, + "contracts/test/helpers/RevertProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\ncontract RevertProxy {\n bytes data;\n\n fallback() external {\n data = msg.data;\n }\n\n // solium-disable security/no-low-level-calls\n function execute(address _target) external returns (bool) {\n (bool ok, ) = _target.call(data);\n return ok;\n }\n}\n" + }, + "contracts/test/TestSortedDoublyLLRemove.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/SortedDoublyLLFixture.sol\";\nimport \"./helpers/RevertProxy.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestSortedDoublyLLRemove {\n address[] ids = [address(1), address(2), address(3), address(4), address(5), address(6)];\n uint256[] keys = [uint256(13), uint256(11), uint256(9), uint256(7), uint256(5), uint256(3)];\n\n SortedDoublyLLFixture fixture;\n RevertProxy proxy;\n\n function beforeAll() public {\n proxy = new RevertProxy();\n }\n\n function beforeEach() public {\n fixture = new SortedDoublyLLFixture();\n fixture.setMaxSize(10);\n }\n\n function test_remove() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n\n fixture.remove(ids[1]);\n Assert.equal(fixture.contains(ids[1]), false, \"should not contain node\");\n Assert.equal(fixture.getSize(), 2, \"wrong size\");\n Assert.equal(fixture.getNext(ids[0]), ids[2], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[2]), ids[0], \"wrong prev\");\n }\n\n function test_remove_singleNode() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n\n fixture.remove(ids[0]);\n Assert.equal(fixture.contains(ids[0]), false, \"should not contain node\");\n Assert.equal(fixture.getSize(), 0, \"wrong size\");\n Assert.equal(fixture.getFirst(), address(0), \"wrong head\");\n Assert.equal(fixture.getLast(), address(0), \"wrong tail\");\n }\n\n function test_remove_head() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n\n fixture.remove(ids[0]);\n Assert.equal(fixture.contains(ids[0]), false, \"should not contain node\");\n Assert.equal(fixture.getSize(), 1, \"wrong size\");\n Assert.equal(fixture.getFirst(), ids[1], \"wrong head\");\n Assert.equal(fixture.getPrev(ids[1]), address(0), \"wrong prev\");\n }\n\n function test_remove_tail() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n\n fixture.remove(ids[1]);\n Assert.equal(fixture.contains(ids[1]), false, \"should not contain node\");\n Assert.equal(fixture.getSize(), 1, \"wrong size\");\n Assert.equal(fixture.getLast(), ids[0], \"wrong prev\");\n Assert.equal(fixture.getNext(ids[0]), address(0), \"wrong next\");\n }\n\n function test_remove_notInList() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n\n SortedDoublyLLFixture(address(proxy)).remove(ids[1]);\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n}\n" + }, + "contracts/test/TestSortedDoublyLLInsert.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/SortedDoublyLLFixture.sol\";\nimport \"./helpers/RevertProxy.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestSortedDoublyLLInsert {\n address[] ids = [address(1), address(2), address(3), address(4), address(5), address(6)];\n uint256[] keys = [uint256(13), uint256(11), uint256(9), uint256(7), uint256(5), uint256(5), uint256(3)];\n\n SortedDoublyLLFixture fixture;\n RevertProxy proxy;\n\n function beforeAll() public {\n proxy = new RevertProxy();\n }\n\n function beforeEach() public {\n fixture = new SortedDoublyLLFixture();\n fixture.setMaxSize(3);\n }\n\n function test_setMaxSize() public {\n Assert.equal(fixture.getMaxSize(), 3, \"wrong max size\");\n }\n\n function test_setMaxSize_update() public {\n fixture.setMaxSize(10);\n\n Assert.equal(fixture.getMaxSize(), 10, \"wrong max size\");\n }\n\n function test_setMaxSize_decreaseSize() public {\n SortedDoublyLLFixture(address(proxy)).setMaxSize(1);\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n\n function test_insert_empty() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n Assert.equal(fixture.getSize(), 1, \"wrong size\");\n Assert.equal(fixture.getFirst(), ids[0], \"wrong head\");\n Assert.equal(fixture.getLast(), ids[0], \"wrong tail\");\n Assert.equal(fixture.getKey(ids[0]), keys[0], \"wrong key\");\n Assert.equal(fixture.getNext(ids[0]), address(0), \"wrong next\");\n Assert.equal(fixture.getPrev(ids[0]), address(0), \"wrong prev\");\n }\n\n function test_insert_updateHead() public {\n fixture.insert(ids[1], keys[1], address(0), address(0));\n\n fixture.insert(ids[0], keys[0], address(0), ids[1]);\n Assert.equal(fixture.getSize(), 2, \"wrong size\");\n Assert.equal(fixture.getFirst(), ids[0], \"wrong head\");\n Assert.equal(fixture.getKey(ids[0]), keys[0], \"wrong key\");\n Assert.equal(fixture.getNext(ids[0]), ids[1], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[0]), address(0), \"wrong prev\");\n }\n\n function test_insert_updateTail() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n Assert.equal(fixture.getSize(), 2, \"wrong size\");\n Assert.equal(fixture.getLast(), ids[1], \"wrong tail\");\n Assert.equal(fixture.getKey(ids[1]), keys[1], \"wrong key\");\n Assert.equal(fixture.getNext(ids[1]), address(0), \"wrong next\");\n Assert.equal(fixture.getPrev(ids[1]), ids[0], \"wrong prev\");\n }\n\n function test_insert_atPosition() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[2], keys[2], ids[0], address(0));\n\n fixture.insert(ids[1], keys[1], ids[0], ids[2]);\n Assert.equal(fixture.getSize(), 3, \"wrong size\");\n Assert.equal(fixture.getKey(ids[1]), keys[1], \"wrong stake\");\n Assert.equal(fixture.getNext(ids[1]), ids[2], \"wrong next transcoder\");\n Assert.equal(fixture.getPrev(ids[1]), ids[0], \"wrong prev transcoder\");\n }\n\n function test_insert_full() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n\n SortedDoublyLLFixture(address(proxy)).insert(ids[3], keys[3], address(0), address(0));\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n\n function test_insert_containsId() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n\n SortedDoublyLLFixture(address(proxy)).insert(ids[0], keys[0], address(0), address(0));\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n\n function test_insert_null() public {\n SortedDoublyLLFixture(address(proxy)).insert(address(0), keys[0], address(0), address(0));\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n\n function test_insert_zeroKey() public {\n SortedDoublyLLFixture(address(proxy)).insert(ids[0], 0, address(0), address(0));\n bool result = proxy.execute(address(fixture));\n Assert.isFalse(result, \"did not revert\");\n }\n}\n" + }, + "contracts/test/TestSortedDoublyLLFindWithHints2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/SortedDoublyLLFixture.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestSortedDoublyLLFindWithHints2 {\n address[] ids = [address(1), address(2), address(3), address(4), address(5), address(6)];\n uint256[] keys = [uint256(13), uint256(11), uint256(9), uint256(7), uint256(5), uint256(3)];\n\n SortedDoublyLLFixture fixture;\n\n function beforeEach() public {\n fixture = new SortedDoublyLLFixture();\n fixture.setMaxSize(10);\n }\n\n function test_insert_findWithHintPrevRemoved() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.remove(ids[2]);\n fixture.insert(ids[3], keys[3], ids[2], ids[4]);\n Assert.equal(fixture.getSize(), 5, \"wrong size\");\n Assert.equal(fixture.getKey(ids[3]), keys[3], \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[4], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[1], \"wrong prev\");\n }\n\n function test_insert_findWithHintPrevRemovedUpdateHead() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.remove(ids[0]);\n fixture.insert(ids[1], keys[1], ids[0], ids[2]);\n Assert.equal(fixture.getSize(), 5, \"wrong size\");\n Assert.equal(fixture.getFirst(), ids[1], \"wrong head\");\n Assert.equal(fixture.getKey(ids[1]), keys[1], \"wrong key\");\n Assert.equal(fixture.getNext(ids[1]), ids[2], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[1]), address(0), \"wrong prev\");\n }\n\n function test_insert_findWithHintPrevDecreased() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.updateKey(ids[2], 6, address(0), address(0));\n fixture.insert(ids[3], keys[3], ids[2], ids[4]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[3]), keys[3], \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[2], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[1], \"wrong prev\");\n }\n\n function test_insert_findWithHintNextRemoved() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.remove(ids[4]);\n fixture.insert(ids[3], keys[3], ids[2], ids[4]);\n Assert.equal(fixture.getSize(), 5, \"wrong size\");\n Assert.equal(fixture.getKey(ids[3]), keys[3], \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[5], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[2], \"wrong prev\");\n }\n\n function test_insert_findWithHintNextRemovedUpdateTail() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[3], address(0));\n\n fixture.remove(ids[5]);\n fixture.insert(ids[4], keys[4], ids[3], ids[5]);\n Assert.equal(fixture.getSize(), 5, \"wrong size\");\n Assert.equal(fixture.getLast(), ids[4], \"wrong tail\");\n Assert.equal(fixture.getKey(ids[4]), keys[4], \"wrong key\");\n Assert.equal(fixture.getNext(ids[4]), address(0), \"wrong next\");\n Assert.equal(fixture.getPrev(ids[4]), ids[3], \"wrong prev\");\n }\n\n function test_insert_findWithHintNextIncreased() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.updateKey(ids[4], 8, address(0), address(0));\n fixture.insert(ids[3], keys[3], ids[2], ids[4]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[3]), keys[3], \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[5], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[4], \"wrong prev\");\n }\n\n function test_insert_findWithHintNotTightBound() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[3], keys[3], ids[0], ids[5]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[3]), keys[3], \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[4], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[2], \"wrong prev\");\n }\n}\n" + }, + "contracts/test/TestSortedDoublyLLFindWithHints.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/SortedDoublyLLFixture.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestSortedDoublyLLFindWithHints {\n address[] ids = [address(1), address(2), address(3), address(4), address(5), address(6)];\n uint256[] keys = [uint256(13), uint256(11), uint256(9), uint256(7), uint256(5), uint256(3)];\n\n SortedDoublyLLFixture fixture;\n\n function beforeEach() public {\n fixture = new SortedDoublyLLFixture();\n fixture.setMaxSize(10);\n }\n\n function test_insert_findNoHintUpdateHead() public {\n fixture.insert(ids[1], keys[1], address(0), address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[0], keys[0], address(0), address(0));\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getFirst(), ids[0], \"wrong head\");\n Assert.equal(fixture.getKey(ids[0]), keys[0], \"wrong key\");\n Assert.equal(fixture.getNext(ids[0]), ids[1], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[0]), address(0), \"wrong prev\");\n }\n\n function test_insert_findNoHintUpdateTail() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n\n fixture.insert(ids[5], keys[5], address(0), address(0));\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getLast(), ids[5], \"wrong tail\");\n Assert.equal(fixture.getKey(ids[5]), keys[5], \"wrong key\");\n Assert.equal(fixture.getNext(ids[5]), address(0), \"wrong next transcoder\");\n Assert.equal(fixture.getPrev(ids[5]), ids[4], \"wrong prev transcoder\");\n }\n\n function test_insert_findNoHintAtPosition() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[3], keys[3], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[2], keys[2], address(0), address(0));\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[2]), keys[2], \"wrong\");\n Assert.equal(fixture.getNext(ids[2]), ids[3], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[2]), ids[1], \"wrong prev\");\n }\n\n function test_insert_findWithHintNextUpdateHead() public {\n fixture.insert(ids[1], keys[1], address(0), address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[0], keys[0], address(0), ids[2]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getFirst(), ids[0], \"wrong head\");\n Assert.equal(fixture.getKey(ids[0]), keys[0], \"wrong key\");\n Assert.equal(fixture.getNext(ids[0]), ids[1], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[0]), address(0), \"wrong prev\");\n }\n\n function test_insert_findWithHintNextUpdateTail() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[2], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[1], 3, address(0), ids[5]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getLast(), ids[1], \"wrong tail\");\n Assert.equal(fixture.getKey(ids[1]), 3, \"wrong key\");\n Assert.equal(fixture.getNext(ids[1]), address(0), \"wrong next\");\n Assert.equal(fixture.getPrev(ids[1]), ids[5], \"wrong prev\");\n }\n\n function test_insert_findWithHintNextAtPosition() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[3], keys[3], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[2], keys[2], address(0), ids[3]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[2]), keys[2], \"wrong key\");\n Assert.equal(fixture.getNext(ids[2]), ids[3], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[2]), ids[1], \"wrong prev\");\n }\n\n function test_insert_findWithHintPrevUpdateTail() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[3], keys[3], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n\n fixture.insert(ids[5], keys[5], ids[1], address(0));\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getLast(), ids[5], \"wrong tail\");\n Assert.equal(fixture.getKey(ids[5]), keys[5], \"wrong key\");\n Assert.equal(fixture.getNext(ids[5]), address(0), \"wrong next\");\n Assert.equal(fixture.getPrev(ids[5]), ids[4], \"wrong prev\");\n }\n\n function test_insert_findWithHintPrevAtPosition() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[3], keys[3], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[3], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[2], keys[2], ids[0], address(0));\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[2]), keys[2], \"wrong key\");\n Assert.equal(fixture.getNext(ids[2]), ids[3], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[2]), ids[1], \"wrong prev\");\n }\n\n function test_insert_findWithHint() public {\n fixture.insert(ids[0], keys[0], address(0), address(0));\n fixture.insert(ids[1], keys[1], ids[0], address(0));\n fixture.insert(ids[2], keys[2], ids[1], address(0));\n fixture.insert(ids[4], keys[4], ids[2], address(0));\n fixture.insert(ids[5], keys[5], ids[4], address(0));\n\n fixture.insert(ids[3], keys[3], ids[2], ids[4]);\n Assert.equal(fixture.getSize(), 6, \"wrong size\");\n Assert.equal(fixture.getKey(ids[3]), keys[3], \"wrong key\");\n Assert.equal(fixture.getNext(ids[3]), ids[4], \"wrong next\");\n Assert.equal(fixture.getPrev(ids[3]), ids[2], \"wrong prev\");\n }\n}\n" + }, + "contracts/test/TestPreciseMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../libraries/PreciseMathUtils.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestPreciseMathUtils {\n function test_validPerc() public {\n Assert.equal(PreciseMathUtils.validPerc(50), true, \"50 should be a valid percentage\");\n Assert.equal(PreciseMathUtils.validPerc(0), true, \"0 should be a valid percentage\");\n Assert.equal(PreciseMathUtils.validPerc(10**27), true, \"the max should be a valid percentage\");\n Assert.equal(\n PreciseMathUtils.validPerc(10**27 + 1),\n false,\n \"1 more than the max should not be valid percentage\"\n );\n }\n\n function test_percOf1() public {\n Assert.equal(PreciseMathUtils.percOf(100, 3, 4), 75, \"3/4 of 100 should be 75\");\n Assert.equal(PreciseMathUtils.percOf(100, 7, 9), 77, \"7/9 of 100 should be 77\");\n }\n\n function test_percOf2() public {\n Assert.equal(PreciseMathUtils.percOf(100, 3), 0, \".0000000000000000000000003% of 100 is 0\");\n Assert.equal(PreciseMathUtils.percOf(10**27, 1), 1, \".0000000000000000000000001% of 1000000000 is 1\");\n Assert.equal(PreciseMathUtils.percOf(100, 10**27 / 10), 10, \"10% of 100 is 10\");\n }\n\n function test_percPoints() public {\n Assert.equal(\n PreciseMathUtils.percPoints(3, 4),\n 750000000000000000000000000,\n \"3/4 should convert to valid percentage\"\n );\n Assert.equal(\n PreciseMathUtils.percPoints(100, 300),\n 333333333333333333333333333,\n \"100/300 should convert to valid percentage\"\n );\n }\n}\n" + }, + "contracts/test/TestEarningsPoolLIP36.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/EarningsPoolFixture.sol\";\nimport \"./helpers/truffle/Assert.sol\";\nimport \"../libraries/PreciseMathUtils.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\ncontract TestEarningsPoolLIP36 {\n using SafeMath for uint256;\n\n EarningsPoolFixture fixture;\n\n function beforeEach() public {\n fixture = new EarningsPoolFixture();\n fixture.setStake(1000);\n fixture.setCommission(500000, 500000);\n }\n\n function test_updateCumulativeFeeFactor_no_prevEarningsPool() public {\n uint256 fees = 1000;\n\n // earningsPool.cumulativeFeeFactor == 0\n // prevEarningsPool.cumulativeFeeFactor == 0\n // prevEarningsPool.cumulativeRewardFactor == 0\n fixture.updateCumulativeFeeFactor(fees);\n uint256 expFeeFactor = PreciseMathUtils.percPoints(fees, fixture.getTotalStake());\n Assert.equal(fixture.getCumulativeFeeFactor(), expFeeFactor, \"should set cumulativeFeeFactor\");\n\n // earningsPool.cumulativeFeeFactor != 0\n fixture.updateCumulativeFeeFactor(fees);\n expFeeFactor = expFeeFactor.add(PreciseMathUtils.percPoints(fees, fixture.getTotalStake()));\n Assert.equal(fixture.getCumulativeFeeFactor(), expFeeFactor, \"should update cumulativeFeeFactor\");\n }\n\n function test_updateCumulativeFeeFactor_prevEarningsPool() public {\n uint256 fees = 200;\n\n // prevEarningsPool.cumulativeFeeFactor = 2\n // prevEarningsPool.cumulativeRewardFactor = 3\n uint256 prevFeeFactor = 2;\n uint256 prevRewFactor = 3;\n fixture.setPrevPoolEarningsFactors(prevFeeFactor, prevRewFactor);\n\n // earningsPool.cumulativeFeeFactor == 0\n fixture.updateCumulativeFeeFactor(fees);\n uint256 expFeeFactor = prevFeeFactor.add(PreciseMathUtils.percOf(prevRewFactor, fees, fixture.getTotalStake()));\n Assert.equal(fixture.getCumulativeFeeFactor(), expFeeFactor, \"should update cumulativeFeeFactor\");\n\n // earningsPool.cumulativeFeeFactor != 0\n fixture.updateCumulativeFeeFactor(fees);\n expFeeFactor = expFeeFactor.add(PreciseMathUtils.percOf(prevRewFactor, fees, fixture.getTotalStake()));\n }\n\n function test_updateCumulativeRewardFactor() public {\n uint256 rewards = 1000;\n\n // prevEarningsPool.cumulativeRewardFactor == 0\n uint256 expRewardFactor = PreciseMathUtils.percPoints(1, 1).add(\n PreciseMathUtils.percOf(PreciseMathUtils.percPoints(1, 1), rewards, fixture.getTotalStake())\n );\n fixture.updateCumulativeRewardFactor(1000);\n Assert.equal(expRewardFactor, fixture.getCumulativeRewardFactor(), \"incorrect cumulative reward factor\");\n\n // prevEarningsPool.cumulativeRewardFactor != 0\n fixture.setPrevPoolEarningsFactors(0, expRewardFactor);\n expRewardFactor = expRewardFactor.add(\n PreciseMathUtils.percOf(expRewardFactor, rewards, fixture.getTotalStake())\n );\n fixture.updateCumulativeRewardFactor(1000);\n Assert.equal(expRewardFactor, fixture.getCumulativeRewardFactor(), \"incorrect cumulative reward factor\");\n }\n}\n" + }, + "contracts/test/mocks/EarningsPoolFixture.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../libraries/MathUtils.sol\";\nimport \"../../bonding/libraries/EarningsPool.sol\";\nimport \"../../bonding/libraries/EarningsPoolLIP36.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\ncontract EarningsPoolFixture {\n using SafeMath for uint256;\n using EarningsPool for EarningsPool.Data;\n using EarningsPoolLIP36 for EarningsPool.Data;\n\n EarningsPool.Data prevPool;\n EarningsPool.Data pool;\n\n function setCommission(uint256 _rewardCut, uint256 _feeShare) public {\n pool.setCommission(_rewardCut, _feeShare);\n }\n\n function setStake(uint256 _stake) public {\n pool.setStake(_stake);\n }\n\n function updateCumulativeFeeFactor(uint256 _fees) public {\n pool.updateCumulativeFeeFactor(prevPool, _fees);\n }\n\n function updateCumulativeRewardFactor(uint256 _rewards) public {\n pool.updateCumulativeRewardFactor(prevPool, _rewards);\n }\n\n function setPrevPoolEarningsFactors(uint256 _cumulativeFeeFactor, uint256 _cumulativeRewardFactor) public {\n prevPool.cumulativeFeeFactor = _cumulativeFeeFactor;\n prevPool.cumulativeRewardFactor = _cumulativeRewardFactor;\n }\n\n function getTranscoderRewardCut() public view returns (uint256) {\n return pool.transcoderRewardCut;\n }\n\n function getTranscoderFeeShare() public view returns (uint256) {\n return pool.transcoderFeeShare;\n }\n\n function getTotalStake() public view returns (uint256) {\n return pool.totalStake;\n }\n\n function getCumulativeRewardFactor() public view returns (uint256) {\n return pool.cumulativeRewardFactor;\n }\n\n function getCumulativeFeeFactor() public view returns (uint256) {\n return pool.cumulativeFeeFactor;\n }\n}\n" + }, + "contracts/test/TestEarningsPool.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mocks/EarningsPoolFixture.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestEarningsPool {\n EarningsPoolFixture fixture;\n\n function beforeEach() public {\n fixture = new EarningsPoolFixture();\n fixture.setStake(1000);\n fixture.setCommission(500000, 500000);\n }\n\n function test_setCommission() public {\n fixture.setCommission(5, 10);\n uint256 transcoderRewardCut = fixture.getTranscoderRewardCut();\n uint256 transcoderFeeShare = fixture.getTranscoderFeeShare();\n Assert.equal(transcoderRewardCut, 5, \"wrong transcoderRewardCut\");\n Assert.equal(transcoderFeeShare, 10, \"wrong transcoderFeeShare\");\n }\n\n function test_setStake() public {\n fixture.setStake(5000);\n uint256 totalStake = fixture.getTotalStake();\n Assert.equal(totalStake, 5000, \"wrong totalStake\");\n }\n}\n" + }, + "contracts/test/TestMathUtils.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../libraries/MathUtils.sol\";\nimport \"./helpers/truffle/Assert.sol\";\n\ncontract TestMathUtils {\n function test_validPerc() public {\n Assert.equal(MathUtils.validPerc(50), true, \"50 should be a valid percentage\");\n Assert.equal(MathUtils.validPerc(0), true, \"0 should be a valid percentage\");\n Assert.equal(MathUtils.validPerc(1000000), true, \"the max should be a valid percentage\");\n Assert.equal(MathUtils.validPerc(1000001), false, \"1 more than the max should not be valid percentage\");\n }\n\n function test_percOf1() public {\n Assert.equal(MathUtils.percOf(100, 3, 4), 75, \"3/4 of 100 should be 75\");\n Assert.equal(MathUtils.percOf(100, 7, 9), 77, \"7/9 of 100 should be 77\");\n }\n\n function test_percOf2() public {\n Assert.equal(MathUtils.percOf(100, 3), 0, \".0003% of 100 is 0\");\n Assert.equal(MathUtils.percOf(100, 100000), 10, \"10% of 100 is 10\");\n }\n\n function test_percPoints() public {\n Assert.equal(MathUtils.percPoints(3, 4), 750000, \"3/4 should convert to valid percentage\");\n Assert.equal(MathUtils.percPoints(100, 300), 333333, \"100/300 should convert to valid percentage\");\n }\n}\n" + }, + "contracts/rounds/RoundsManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../ManagerProxyTarget.sol\";\nimport \"./IRoundsManager.sol\";\nimport \"../bonding/IBondingManager.sol\";\nimport \"../token/IMinter.sol\";\nimport \"../libraries/MathUtils.sol\";\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title RoundsManager\n * @notice Manages round progression and other blockchain time related operations of the Livepeer protocol\n */\ncontract RoundsManager is ManagerProxyTarget, IRoundsManager {\n using SafeMath for uint256;\n\n // Round length in blocks\n uint256 public roundLength;\n // Lock period of a round as a % of round length\n // Transcoders cannot join the transcoder pool or change their rates during the lock period at the end of a round\n // The lock period provides delegators time to review transcoder information without changes\n // # of blocks in the lock period = (roundLength * roundLockAmount) / PERC_DIVISOR\n uint256 public roundLockAmount;\n // Last initialized round. After first round, this is the last round during which initializeRound() was called\n uint256 public lastInitializedRound;\n // Round in which roundLength was last updated\n uint256 public lastRoundLengthUpdateRound;\n // Start block of the round in which roundLength was last updated\n uint256 public lastRoundLengthUpdateStartBlock;\n\n // Mapping round number => block hash for the round\n mapping(uint256 => bytes32) internal _blockHashForRound;\n\n // LIP Upgrade Rounds\n // These can be used in conditionals to ensure backwards compatibility or skip such backwards compatibility logic\n // in case 'currentRound' > LIP-X upgrade round\n mapping(uint256 => uint256) public lipUpgradeRound; // mapping (LIP-number > round number)\n\n /**\n * @notice RoundsManager constructor. Only invokes constructor of base Manager contract with provided Controller address\n * @dev This constructor will not initialize any state variables besides `controller`. The following setter functions\n * should be used to initialize state variables post-deployment:\n * - setRoundLength()\n * - setRoundLockAmount()\n * @param _controller Address of Controller that this contract will be registered with\n */\n constructor(address _controller) Manager(_controller) {}\n\n /**\n * @notice Set round length. Only callable by the controller owner\n * @param _roundLength Round length in blocks\n */\n function setRoundLength(uint256 _roundLength) external onlyControllerOwner {\n require(_roundLength > 0, \"round length cannot be 0\");\n\n if (roundLength == 0) {\n // If first time initializing roundLength, set roundLength before\n // lastRoundLengthUpdateRound and lastRoundLengthUpdateStartBlock\n roundLength = _roundLength;\n lastRoundLengthUpdateRound = currentRound();\n lastRoundLengthUpdateStartBlock = currentRoundStartBlock();\n } else {\n // If updating roundLength, set roundLength after\n // lastRoundLengthUpdateRound and lastRoundLengthUpdateStartBlock\n lastRoundLengthUpdateRound = currentRound();\n lastRoundLengthUpdateStartBlock = currentRoundStartBlock();\n roundLength = _roundLength;\n }\n\n emit ParameterUpdate(\"roundLength\");\n }\n\n /**\n * @notice Set round lock amount. Only callable by the controller owner\n * @param _roundLockAmount Round lock amount as a % of the number of blocks in a round\n */\n function setRoundLockAmount(uint256 _roundLockAmount) external onlyControllerOwner {\n require(MathUtils.validPerc(_roundLockAmount), \"round lock amount must be a valid percentage\");\n\n roundLockAmount = _roundLockAmount;\n\n emit ParameterUpdate(\"roundLockAmount\");\n }\n\n /**\n * @notice Initialize the current round. Called once at the start of any round\n */\n function initializeRound() external whenSystemNotPaused {\n uint256 currRound = currentRound();\n\n // Check if already called for the current round\n require(lastInitializedRound < currRound, \"round already initialized\");\n\n // Set current round as initialized\n lastInitializedRound = currRound;\n // Store block hash for round\n bytes32 roundBlockHash = blockHash(blockNum().sub(1));\n _blockHashForRound[currRound] = roundBlockHash;\n // Set total active stake for the round\n bondingManager().setCurrentRoundTotalActiveStake();\n // Set mintable rewards for the round\n minter().setCurrentRewardTokens();\n\n emit NewRound(currRound, roundBlockHash);\n }\n\n /**\n * @notice setLIPUpgradeRound sets the round an LIP upgrade would become active.\n * @param _lip the LIP number.\n * @param _round (optional) the round in which the LIP becomes active\n */\n function setLIPUpgradeRound(uint256 _lip, uint256 _round) external onlyControllerOwner {\n require(lipUpgradeRound[_lip] == 0, \"LIP upgrade round already set\");\n lipUpgradeRound[_lip] = _round;\n }\n\n /**\n * @notice Return current block number\n */\n function blockNum() public view virtual returns (uint256) {\n return block.number;\n }\n\n /**\n * @notice Return blockhash for a block\n */\n function blockHash(uint256 _block) public view virtual returns (bytes32) {\n uint256 currentBlock = blockNum();\n require(_block < currentBlock, \"can only retrieve past block hashes\");\n require(currentBlock < 256 || _block >= currentBlock - 256, \"can only retrieve hashes for last 256 blocks\");\n\n return blockhash(_block);\n }\n\n /**\n * @notice Return blockhash for a round\n * @param _round Round number\n * @return Blockhash for `_round`\n */\n function blockHashForRound(uint256 _round) public view returns (bytes32) {\n return _blockHashForRound[_round];\n }\n\n /**\n * @notice Return current round\n */\n function currentRound() public view returns (uint256) {\n // Compute # of rounds since roundLength was last updated\n uint256 roundsSinceUpdate = blockNum().sub(lastRoundLengthUpdateStartBlock).div(roundLength);\n // Current round = round that roundLength was last updated + # of rounds since roundLength was last updated\n return lastRoundLengthUpdateRound.add(roundsSinceUpdate);\n }\n\n /**\n * @notice Return start block of current round\n */\n function currentRoundStartBlock() public view returns (uint256) {\n // Compute # of rounds since roundLength was last updated\n uint256 roundsSinceUpdate = blockNum().sub(lastRoundLengthUpdateStartBlock).div(roundLength);\n // Current round start block = start block of round that roundLength was last updated + (# of rounds since roundLenght was last updated * roundLength)\n return lastRoundLengthUpdateStartBlock.add(roundsSinceUpdate.mul(roundLength));\n }\n\n /**\n * @notice Check if current round is initialized\n */\n function currentRoundInitialized() public view returns (bool) {\n return lastInitializedRound == currentRound();\n }\n\n /**\n * @notice Check if we are in the lock period of the current round\n */\n function currentRoundLocked() public view returns (bool) {\n uint256 lockedBlocks = MathUtils.percOf(roundLength, roundLockAmount);\n return blockNum().sub(currentRoundStartBlock()) >= roundLength.sub(lockedBlocks);\n }\n\n /**\n * @dev Return BondingManager interface\n */\n function bondingManager() internal view returns (IBondingManager) {\n return IBondingManager(controller.getContract(keccak256(\"BondingManager\")));\n }\n\n /**\n * @dev Return Minter interface\n */\n function minter() internal view returns (IMinter) {\n return IMinter(controller.getContract(keccak256(\"Minter\")));\n }\n}\n" + }, + "contracts/pm/mixins/interfaces/MContractRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../../bonding/IBondingManager.sol\";\nimport \"../../../token/IMinter.sol\";\nimport \"../../../rounds/IRoundsManager.sol\";\n\nabstract contract MContractRegistry {\n /**\n * @notice Checks if the current round has been initialized\n * @dev Executes the 'currentRoundInitialized' modifier in 'MixinContractRegistry'\n */\n modifier currentRoundInitialized() virtual {\n _;\n }\n\n /**\n * @dev Returns an instance of the IBondingManager interface\n */\n function bondingManager() internal view virtual returns (IBondingManager);\n\n /**\n * @dev Returns an instance of the IMinter interface\n */\n function minter() internal view virtual returns (IMinter);\n\n /**\n * @dev Returns an instance of the IRoundsManager interface\n */\n function roundsManager() internal view virtual returns (IRoundsManager);\n}\n" + }, + "contracts/pm/mixins/MixinContractRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../ManagerProxyTarget.sol\";\nimport \"./interfaces/MContractRegistry.sol\";\n\nabstract contract MixinContractRegistry is MContractRegistry, ManagerProxyTarget {\n /**\n * @dev Checks if the current round has been initialized\n */\n modifier currentRoundInitialized() override {\n require(roundsManager().currentRoundInitialized(), \"current round is not initialized\");\n _;\n }\n\n constructor(address _controller) Manager(_controller) {}\n\n /**\n * @dev Returns an instance of the IBondingManager interface\n */\n function bondingManager() internal view override returns (IBondingManager) {\n return IBondingManager(controller.getContract(keccak256(\"BondingManager\")));\n }\n\n /**\n * @dev Returns an instance of the IMinter interface\n */\n function minter() internal view override returns (IMinter) {\n return IMinter(controller.getContract(keccak256(\"Minter\")));\n }\n\n /**\n * @dev Returns an instance of the IRoundsManager interface\n */\n function roundsManager() internal view override returns (IRoundsManager) {\n return IRoundsManager(controller.getContract(keccak256(\"RoundsManager\")));\n }\n}\n" + }, + "contracts/pm/TicketBroker.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./mixins/MixinContractRegistry.sol\";\nimport \"./mixins/MixinReserve.sol\";\nimport \"./mixins/MixinTicketBrokerCore.sol\";\nimport \"./mixins/MixinTicketProcessor.sol\";\nimport \"./mixins/MixinWrappers.sol\";\n\ncontract TicketBroker is\n MixinContractRegistry,\n MixinReserve,\n MixinTicketBrokerCore,\n MixinTicketProcessor,\n MixinWrappers\n{\n /**\n * @notice TicketBroker constructor. Only invokes constructor of base Manager contract with provided Controller address\n * @dev This constructor will not initialize any state variables besides `controller`. The following setter functions\n * should be used to initialize state variables post-deployment:\n * - setUnlockPeriod()\n * - setTicketValidityPeriod()\n * @param _controller Address of Controller that this contract will be registered with\n */\n constructor(address _controller)\n MixinContractRegistry(_controller)\n MixinReserve()\n MixinTicketBrokerCore()\n MixinTicketProcessor()\n {}\n\n /**\n * @notice Sets unlockPeriod value. Only callable by the Controller owner\n * @param _unlockPeriod Value for unlockPeriod\n */\n function setUnlockPeriod(uint256 _unlockPeriod) external onlyControllerOwner {\n unlockPeriod = _unlockPeriod;\n\n emit ParameterUpdate(\"unlockPeriod\");\n }\n\n /**\n * @notice Sets ticketValidityPeriod value. Only callable by the Controller owner\n * @param _ticketValidityPeriod Value for ticketValidityPeriod\n */\n function setTicketValidityPeriod(uint256 _ticketValidityPeriod) external onlyControllerOwner {\n require(_ticketValidityPeriod > 0, \"ticketValidityPeriod must be greater than 0\");\n\n ticketValidityPeriod = _ticketValidityPeriod;\n\n emit ParameterUpdate(\"ticketValidityPeriod\");\n }\n}\n" + }, + "contracts/pm/mixins/MixinReserve.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./interfaces/MReserve.sol\";\nimport \"./MixinContractRegistry.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nabstract contract MixinReserve is MixinContractRegistry, MReserve {\n using SafeMath for uint256;\n\n struct Reserve {\n uint256 funds; // Amount of funds in the reserve\n mapping(uint256 => uint256) claimedForRound; // Mapping of round => total amount claimed\n mapping(uint256 => mapping(address => uint256)) claimedByAddress; // Mapping of round => claimant address => amount claimed\n }\n\n // Mapping of address => reserve\n mapping(address => Reserve) internal reserves;\n\n /**\n * @dev Returns info about a reserve\n * @param _reserveHolder Address of reserve holder\n * @return info Info about the reserve for `_reserveHolder`\n */\n function getReserveInfo(address _reserveHolder) public view override returns (ReserveInfo memory info) {\n info.fundsRemaining = remainingReserve(_reserveHolder);\n info.claimedInCurrentRound = reserves[_reserveHolder].claimedForRound[roundsManager().currentRound()];\n }\n\n /**\n * @dev Returns the amount of funds claimable by a claimant from a reserve in the current round\n * @param _reserveHolder Address of reserve holder\n * @param _claimant Address of claimant\n * @return Amount of funds claimable by `_claimant` from the reserve for `_reserveHolder` in the current round\n */\n function claimableReserve(address _reserveHolder, address _claimant) public view returns (uint256) {\n Reserve storage reserve = reserves[_reserveHolder];\n\n uint256 currentRound = roundsManager().currentRound();\n\n if (!bondingManager().isActiveTranscoder(_claimant)) {\n return 0;\n }\n\n uint256 poolSize = bondingManager().getTranscoderPoolSize();\n if (poolSize == 0) {\n return 0;\n }\n\n // Total claimable funds = remaining funds + amount claimed for the round\n uint256 totalClaimable = reserve.funds.add(reserve.claimedForRound[currentRound]);\n return totalClaimable.div(poolSize).sub(reserve.claimedByAddress[currentRound][_claimant]);\n }\n\n /**\n * @dev Returns the amount of funds claimed by a claimant from a reserve in the current round\n * @param _reserveHolder Address of reserve holder\n * @param _claimant Address of claimant\n * @return Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder` in the current round\n */\n function claimedReserve(address _reserveHolder, address _claimant) public view override returns (uint256) {\n Reserve storage reserve = reserves[_reserveHolder];\n uint256 currentRound = roundsManager().currentRound();\n return reserve.claimedByAddress[currentRound][_claimant];\n }\n\n /**\n * @dev Adds funds to a reserve\n * @param _reserveHolder Address of reserve holder\n * @param _amount Amount of funds to add to reserve\n */\n function addReserve(address _reserveHolder, uint256 _amount) internal override {\n reserves[_reserveHolder].funds = reserves[_reserveHolder].funds.add(_amount);\n\n emit ReserveFunded(_reserveHolder, _amount);\n }\n\n /**\n * @dev Clears contract storage used for a reserve\n * @param _reserveHolder Address of reserve holder\n */\n function clearReserve(address _reserveHolder) internal override {\n // This delete operation will only clear reserve.funds and will not clear the storage for reserve.claimedForRound\n // reserve.claimedByAddress because these fields are mappings and the Solidity `delete` keyword will not modify mappings.\n // This *could* be a problem in the following scenario:\n //\n // 1) In round N, for address A, reserve.claimedForRound[N] > 0 and reserve.claimedByAddress[N][r_i] > 0 where r_i is\n // a member of the active set in round N\n // 2) This function is called by MixinTicketBrokerCore.withdraw() in round N\n // 3) Address A funds its reserve again\n //\n // After step 3, A has reserve.funds > 0, reserve.claimedForRound[N] > 0 and reserve.claimedByAddress[N][r_i] > 0\n // despite having funded a fresh reserve after previously withdrawing all of its funds in the same round.\n // We prevent this scenario by disallowing reserve claims starting at an address' withdraw round in\n // MixinTicketBrokerCore.redeemWinningTicket()\n delete reserves[_reserveHolder];\n }\n\n /**\n * @dev Claims funds from a reserve\n * @param _reserveHolder Address of reserve holder\n * @param _claimant Address of claimant\n * @param _amount Amount of funds to claim from the reserve\n * @return Amount of funds (<= `_amount`) claimed by `_claimant` from the reserve for `_reserveHolder`\n */\n function claimFromReserve(\n address _reserveHolder,\n address _claimant,\n uint256 _amount\n ) internal override returns (uint256) {\n uint256 claimableFunds = claimableReserve(_reserveHolder, _claimant);\n // If the given amount > claimableFunds then claim claimableFunds\n // If the given amount <= claimableFunds then claim the given amount\n uint256 claimAmount = _amount > claimableFunds ? claimableFunds : _amount;\n\n if (claimAmount > 0) {\n uint256 currentRound = roundsManager().currentRound();\n Reserve storage reserve = reserves[_reserveHolder];\n // Increase total amount claimed for the round\n reserve.claimedForRound[currentRound] = reserve.claimedForRound[currentRound].add(claimAmount);\n // Increase amount claimed by claimant for the round\n reserve.claimedByAddress[currentRound][_claimant] = reserve.claimedByAddress[currentRound][_claimant].add(\n claimAmount\n );\n // Decrease remaining reserve\n reserve.funds = reserve.funds.sub(claimAmount);\n\n emit ReserveClaimed(_reserveHolder, _claimant, claimAmount);\n }\n\n return claimAmount;\n }\n\n /**\n * @dev Returns the amount of funds remaining in a reserve\n * @param _reserveHolder Address of reserve holder\n * @return Amount of funds remaining in the reserve for `_reserveHolder`\n */\n function remainingReserve(address _reserveHolder) internal view override returns (uint256) {\n return reserves[_reserveHolder].funds;\n }\n}\n" + }, + "contracts/pm/mixins/MixinTicketBrokerCore.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./interfaces/MReserve.sol\";\nimport \"./interfaces/MTicketProcessor.sol\";\nimport \"./interfaces/MTicketBrokerCore.sol\";\nimport \"./MixinContractRegistry.sol\";\nimport \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nabstract contract MixinTicketBrokerCore is MixinContractRegistry, MReserve, MTicketProcessor, MTicketBrokerCore {\n using SafeMath for uint256;\n\n struct Sender {\n uint256 deposit; // Amount of funds deposited\n uint256 withdrawRound; // Round that sender can withdraw deposit & reserve\n }\n\n // Mapping of address => Sender\n mapping(address => Sender) internal senders;\n\n // Number of rounds before a sender can withdraw after requesting an unlock\n uint256 public unlockPeriod;\n\n // Mapping of ticket hashes => boolean indicating if ticket was redeemed\n mapping(bytes32 => bool) public usedTickets;\n\n // Checks if msg.value is equal to the given deposit and reserve amounts\n modifier checkDepositReserveETHValueSplit(uint256 _depositAmount, uint256 _reserveAmount) {\n require(\n msg.value == _depositAmount.add(_reserveAmount),\n \"msg.value does not equal sum of deposit amount and reserve amount\"\n );\n\n _;\n }\n\n // Process deposit funding\n modifier processDeposit(address _sender, uint256 _amount) {\n Sender storage sender = senders[_sender];\n sender.deposit = sender.deposit.add(_amount);\n // If the sender themselves funds their deposit, cancel the unlock\n if (msg.sender == _sender && _isUnlockInProgress(sender)) {\n _cancelUnlock(sender, _sender);\n }\n\n _;\n\n emit DepositFunded(_sender, _amount);\n }\n\n // Process reserve funding\n modifier processReserve(address _sender, uint256 _amount) {\n Sender storage sender = senders[_sender];\n addReserve(_sender, _amount);\n // If the sender themselves funds their reserve, cancel the unlock\n if (msg.sender == _sender && _isUnlockInProgress(sender)) {\n _cancelUnlock(sender, _sender);\n }\n\n _;\n }\n\n /**\n * @notice Adds ETH to the caller's deposit\n */\n function fundDeposit() external payable whenSystemNotPaused processDeposit(msg.sender, msg.value) {\n processFunding(msg.value);\n }\n\n /**\n * @notice Adds ETH to the caller's reserve\n */\n function fundReserve() external payable whenSystemNotPaused processReserve(msg.sender, msg.value) {\n processFunding(msg.value);\n }\n\n /**\n * @notice Adds ETH to the caller's deposit and reserve\n * @param _depositAmount Amount of ETH to add to the caller's deposit\n * @param _reserveAmount Amount of ETH to add to the caller's reserve\n */\n function fundDepositAndReserve(uint256 _depositAmount, uint256 _reserveAmount) external payable {\n fundDepositAndReserveFor(msg.sender, _depositAmount, _reserveAmount);\n }\n\n /**\n * @notice Adds ETH to the address' deposit and reserve\n * @param _depositAmount Amount of ETH to add to the address' deposit\n * @param _reserveAmount Amount of ETH to add to the address' reserve\n */\n function fundDepositAndReserveFor(\n address _addr,\n uint256 _depositAmount,\n uint256 _reserveAmount\n )\n public\n payable\n whenSystemNotPaused\n checkDepositReserveETHValueSplit(_depositAmount, _reserveAmount)\n processDeposit(_addr, _depositAmount)\n processReserve(_addr, _reserveAmount)\n {\n processFunding(msg.value);\n }\n\n /**\n * @notice Redeems a winning ticket that has been signed by a sender and reveals the\n recipient recipientRand that corresponds to the recipientRandHash included in the ticket\n * @param _ticket Winning ticket to be redeemed in order to claim payment\n * @param _sig Sender's signature over the hash of `_ticket`\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\n */\n function redeemWinningTicket(\n Ticket memory _ticket,\n bytes memory _sig,\n uint256 _recipientRand\n ) public whenSystemNotPaused currentRoundInitialized {\n bytes32 ticketHash = getTicketHash(_ticket);\n\n // Require a valid winning ticket for redemption\n requireValidWinningTicket(_ticket, ticketHash, _sig, _recipientRand);\n\n Sender storage sender = senders[_ticket.sender];\n\n // Require sender to be locked\n require(isLocked(sender), \"sender is unlocked\");\n // Require either a non-zero deposit or non-zero reserve for the sender\n require(sender.deposit > 0 || remainingReserve(_ticket.sender) > 0, \"sender deposit and reserve are zero\");\n\n // Mark ticket as used to prevent replay attacks involving redeeming\n // the same winning ticket multiple times\n usedTickets[ticketHash] = true;\n\n uint256 amountToTransfer;\n\n if (_ticket.faceValue > sender.deposit) {\n // If ticket face value > sender's deposit then claim from\n // the sender's reserve\n\n amountToTransfer = sender.deposit.add(\n claimFromReserve(_ticket.sender, _ticket.recipient, _ticket.faceValue.sub(sender.deposit))\n );\n\n sender.deposit = 0;\n } else {\n // If ticket face value <= sender's deposit then only deduct\n // from sender's deposit\n\n amountToTransfer = _ticket.faceValue;\n sender.deposit = sender.deposit.sub(_ticket.faceValue);\n }\n\n if (amountToTransfer > 0) {\n winningTicketTransfer(_ticket.recipient, amountToTransfer, _ticket.auxData);\n\n emit WinningTicketTransfer(_ticket.sender, _ticket.recipient, amountToTransfer);\n }\n\n emit WinningTicketRedeemed(\n _ticket.sender,\n _ticket.recipient,\n _ticket.faceValue,\n _ticket.winProb,\n _ticket.senderNonce,\n _recipientRand,\n _ticket.auxData\n );\n }\n\n /**\n * @notice Initiates the unlock period for the caller\n */\n function unlock() public whenSystemNotPaused {\n Sender storage sender = senders[msg.sender];\n\n require(sender.deposit > 0 || remainingReserve(msg.sender) > 0, \"sender deposit and reserve are zero\");\n require(!_isUnlockInProgress(sender), \"unlock already initiated\");\n\n uint256 currentRound = roundsManager().currentRound();\n sender.withdrawRound = currentRound.add(unlockPeriod);\n\n emit Unlock(msg.sender, currentRound, sender.withdrawRound);\n }\n\n /**\n * @notice Cancels the unlock period for the caller\n */\n function cancelUnlock() public whenSystemNotPaused {\n Sender storage sender = senders[msg.sender];\n\n _cancelUnlock(sender, msg.sender);\n }\n\n /**\n * @notice Withdraws all ETH from the caller's deposit and reserve\n */\n function withdraw() public whenSystemNotPaused {\n Sender storage sender = senders[msg.sender];\n\n uint256 deposit = sender.deposit;\n uint256 reserve = remainingReserve(msg.sender);\n\n require(deposit > 0 || reserve > 0, \"sender deposit and reserve are zero\");\n require(_isUnlockInProgress(sender), \"no unlock request in progress\");\n require(!isLocked(sender), \"account is locked\");\n\n sender.deposit = 0;\n clearReserve(msg.sender);\n\n withdrawTransfer(payable(msg.sender), deposit.add(reserve));\n\n emit Withdrawal(msg.sender, deposit, reserve);\n }\n\n /**\n * @notice Returns whether a sender is currently in the unlock period\n * @param _sender Address of sender\n * @return Boolean indicating whether `_sender` has an unlock in progress\n */\n function isUnlockInProgress(address _sender) public view returns (bool) {\n Sender memory sender = senders[_sender];\n return _isUnlockInProgress(sender);\n }\n\n /**\n * @notice Returns info about a sender\n * @param _sender Address of sender\n * @return sender Info about the sender for `_sender`\n * @return reserve Info about the reserve for `_sender`\n */\n function getSenderInfo(address _sender) public view returns (Sender memory sender, ReserveInfo memory reserve) {\n sender = senders[_sender];\n reserve = getReserveInfo(_sender);\n }\n\n /**\n * @dev Returns the hash of a ticket\n * @param _ticket Ticket to be hashed\n * @return keccak256 hash of `_ticket`\n */\n function getTicketHash(Ticket memory _ticket) public pure returns (bytes32) {\n return\n keccak256(\n abi.encodePacked(\n _ticket.recipient,\n _ticket.sender,\n _ticket.faceValue,\n _ticket.winProb,\n _ticket.senderNonce,\n _ticket.recipientRandHash,\n _ticket.auxData\n )\n );\n }\n\n /**\n * @dev Helper to cancel an unlock\n * @param _sender Sender that is cancelling an unlock\n * @param _senderAddress Address of sender\n */\n function _cancelUnlock(Sender storage _sender, address _senderAddress) internal {\n require(_isUnlockInProgress(_sender), \"no unlock request in progress\");\n\n _sender.withdrawRound = 0;\n\n emit UnlockCancelled(_senderAddress);\n }\n\n /**\n * @dev Validates a winning ticket, succeeds or reverts\n * @param _ticket Winning ticket to be validated\n * @param _ticketHash Hash of `_ticket`\n * @param _sig Sender's signature over `_ticketHash`\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\n */\n function requireValidWinningTicket(\n Ticket memory _ticket,\n bytes32 _ticketHash,\n bytes memory _sig,\n uint256 _recipientRand\n ) internal view {\n require(_ticket.recipient != address(0), \"ticket recipient is null address\");\n require(_ticket.sender != address(0), \"ticket sender is null address\");\n\n requireValidTicketAuxData(_ticket.auxData);\n\n require(\n keccak256(abi.encodePacked(_recipientRand)) == _ticket.recipientRandHash,\n \"recipientRand does not match recipientRandHash\"\n );\n\n require(!usedTickets[_ticketHash], \"ticket is used\");\n\n require(isValidTicketSig(_ticket.sender, _sig, _ticketHash), \"invalid signature over ticket hash\");\n\n require(isWinningTicket(_sig, _recipientRand, _ticket.winProb), \"ticket did not win\");\n }\n\n /**\n * @dev Returns whether a sender is locked\n * @param _sender Sender to check for locked status\n * @return Boolean indicating whether sender is currently locked\n */\n function isLocked(Sender memory _sender) internal view returns (bool) {\n return _sender.withdrawRound == 0 || roundsManager().currentRound() < _sender.withdrawRound;\n }\n\n /**\n * @dev Returns whether a signature over a ticket hash is valid for a sender\n * @param _sender Address of sender\n * @param _sig Signature over `_ticketHash`\n * @param _ticketHash Hash of the ticket\n * @return Boolean indicating whether `_sig` is valid signature over `_ticketHash` for `_sender`\n */\n function isValidTicketSig(\n address _sender,\n bytes memory _sig,\n bytes32 _ticketHash\n ) internal pure returns (bool) {\n require(_sig.length == 65, \"INVALID_SIGNATURE_LENGTH\");\n address signer = ECDSA.recover(ECDSA.toEthSignedMessageHash(_ticketHash), _sig);\n return signer != address(0) && _sender == signer;\n }\n\n /**\n * @dev Returns whether a ticket won\n * @param _sig Sender's signature over the ticket\n * @param _recipientRand The preimage for the recipientRandHash included in the ticket\n * @param _winProb The winning probability of the ticket\n * @return Boolean indicating whether the ticket won\n */\n function isWinningTicket(\n bytes memory _sig,\n uint256 _recipientRand,\n uint256 _winProb\n ) internal pure returns (bool) {\n return uint256(keccak256(abi.encodePacked(_sig, _recipientRand))) < _winProb;\n }\n\n /**\n * @dev Helper to check if a sender is currently in the unlock period\n * @param _sender Sender to check for an unlock\n * @return Boolean indicating whether the sender is currently in the unlock period\n */\n function _isUnlockInProgress(Sender memory _sender) internal pure returns (bool) {\n return _sender.withdrawRound > 0;\n }\n}\n" + }, + "contracts/pm/mixins/MixinTicketProcessor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./interfaces/MTicketProcessor.sol\";\nimport \"./MixinContractRegistry.sol\";\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\nabstract contract MixinTicketProcessor is MixinContractRegistry, MTicketProcessor {\n using SafeMath for uint256;\n\n // Number of rounds that a ticket is valid for starting from\n // its creationRound\n uint256 public ticketValidityPeriod;\n\n /**\n * @dev Process sent funds.\n * @param _amount Amount of funds sent\n */\n function processFunding(uint256 _amount) internal override {\n // Send funds to Minter\n minter().depositETH{ value: _amount }();\n }\n\n /**\n * @dev Transfer withdrawal funds for a ticket sender\n * @param _amount Amount of withdrawal funds\n */\n function withdrawTransfer(address payable _sender, uint256 _amount) internal override {\n // Ask Minter to send withdrawal funds to the ticket sender\n minter().trustedWithdrawETH(_sender, _amount);\n }\n\n /**\n * @dev Transfer funds for a recipient's winning ticket\n * @param _recipient Address of recipient\n * @param _amount Amount of funds for the winning ticket\n * @param _auxData Auxilary data for the winning ticket\n */\n function winningTicketTransfer(\n address _recipient,\n uint256 _amount,\n bytes memory _auxData\n ) internal override {\n (uint256 creationRound, ) = getCreationRoundAndBlockHash(_auxData);\n\n // Ask BondingManager to update fee pool for recipient with\n // winning ticket funds\n bondingManager().updateTranscoderWithFees(_recipient, _amount, creationRound);\n }\n\n /**\n * @dev Validates a ticket's auxilary data (succeeds or reverts)\n * @param _auxData Auxilary data inclueded in a ticket\n */\n function requireValidTicketAuxData(bytes memory _auxData) internal view override {\n (uint256 creationRound, bytes32 creationRoundBlockHash) = getCreationRoundAndBlockHash(_auxData);\n bytes32 blockHash = roundsManager().blockHashForRound(creationRound);\n\n require(blockHash != bytes32(0), \"ticket creationRound does not have a block hash\");\n require(creationRoundBlockHash == blockHash, \"ticket creationRoundBlockHash invalid for creationRound\");\n\n uint256 currRound = roundsManager().currentRound();\n\n require(creationRound.add(ticketValidityPeriod) > currRound, \"ticket is expired\");\n }\n\n /**\n * @dev Returns a ticket's creationRound and creationRoundBlockHash parsed from ticket auxilary data\n * @param _auxData Auxilary data for a ticket\n * @return creationRound and creationRoundBlockHash parsed from `_auxData`\n */\n function getCreationRoundAndBlockHash(bytes memory _auxData)\n internal\n pure\n returns (uint256 creationRound, bytes32 creationRoundBlockHash)\n {\n require(_auxData.length == 64, \"invalid length for ticket auxData: must be 64 bytes\");\n\n // _auxData format:\n // Bytes [0:31] = creationRound\n // Bytes [32:63] = creationRoundBlockHash\n assembly {\n creationRound := mload(add(_auxData, 32))\n creationRoundBlockHash := mload(add(_auxData, 64))\n }\n }\n}\n" + }, + "contracts/pm/mixins/MixinWrappers.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./interfaces/MTicketBrokerCore.sol\";\nimport \"./MixinContractRegistry.sol\";\n\nabstract contract MixinWrappers is MixinContractRegistry, MTicketBrokerCore {\n /**\n * @notice Redeems multiple winning tickets. The function will redeem all of the provided tickets and handle any failures gracefully without reverting the entire function\n * @param _tickets Array of winning tickets to be redeemed in order to claim payment\n * @param _sigs Array of sender signatures over the hash of tickets (`_sigs[i]` corresponds to `_tickets[i]`)\n * @param _recipientRands Array of preimages for the recipientRandHash included in each ticket (`_recipientRands[i]` corresponds to `_tickets[i]`)\n */\n function batchRedeemWinningTickets(\n Ticket[] memory _tickets,\n bytes[] memory _sigs,\n uint256[] memory _recipientRands\n ) public whenSystemNotPaused currentRoundInitialized {\n for (uint256 i = 0; i < _tickets.length; i++) {\n redeemWinningTicketNoRevert(_tickets[i], _sigs[i], _recipientRands[i]);\n }\n }\n\n /**\n * @dev Redeems a winning ticket that has been signed by a sender and reveals the\n recipient recipientRand that corresponds to the recipientRandHash included in the ticket\n This function wraps `redeemWinningTicket()` and returns false if the underlying call reverts\n * @param _ticket Winning ticket to be redeemed in order to claim payment\n * @param _sig Sender's signature over the hash of `_ticket`\n * @param _recipientRand The preimage for the recipientRandHash included in `_ticket`\n * @return success Boolean indicating whether the underlying `redeemWinningTicket()` call succeeded\n */\n function redeemWinningTicketNoRevert(\n Ticket memory _ticket,\n bytes memory _sig,\n uint256 _recipientRand\n ) internal returns (bool success) {\n // ABI encode calldata for `redeemWinningTicket()`\n // A tuple type is used to represent the Ticket struct in the function signature\n bytes memory redeemWinningTicketCalldata = abi.encodeWithSignature(\n \"redeemWinningTicket((address,address,uint256,uint256,uint256,bytes32,bytes),bytes,uint256)\",\n _ticket,\n _sig,\n _recipientRand\n );\n\n // Call `redeemWinningTicket()`\n // solium-disable-next-line\n (success, ) = address(this).call(redeemWinningTicketCalldata);\n }\n}\n" + }, + "contracts/pm/mixins/interfaces/MReserve.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nabstract contract MReserve {\n struct ReserveInfo {\n uint256 fundsRemaining; // Funds remaining in reserve\n uint256 claimedInCurrentRound; // Funds claimed from reserve in current round\n }\n\n // Emitted when funds are added to a reserve\n event ReserveFunded(address indexed reserveHolder, uint256 amount);\n // Emitted when funds are claimed from a reserve\n event ReserveClaimed(address indexed reserveHolder, address claimant, uint256 amount);\n\n /**\n * @notice Returns info about a reserve\n * @param _reserveHolder Address of reserve holder\n * @return info Info about the reserve for `_reserveHolder`\n */\n function getReserveInfo(address _reserveHolder) public view virtual returns (ReserveInfo memory info);\n\n /**\n * @notice Returns the amount of funds claimed by a claimant from a reserve\n * @param _reserveHolder Address of reserve holder\n * @param _claimant Address of claimant\n * @return Amount of funds claimed by `_claimant` from the reserve for `_reserveHolder`\n */\n function claimedReserve(address _reserveHolder, address _claimant) public view virtual returns (uint256);\n\n /**\n * @dev Adds funds to a reserve\n * @param _reserveHolder Address of reserve holder\n * @param _amount Amount of funds to add to reserve\n */\n function addReserve(address _reserveHolder, uint256 _amount) internal virtual;\n\n /**\n * @dev Clears contract storage used for a reserve\n * @param _reserveHolder Address of reserve holder\n */\n function clearReserve(address _reserveHolder) internal virtual;\n\n /**\n * @dev Claims funds from a reserve\n * @param _reserveHolder Address of reserve holder\n * @param _claimant Address of claimant\n * @param _amount Amount of funds to claim from the reserve\n * @return Amount of funds (<= `_amount`) claimed by `_claimant` from the reserve for `_reserveHolder`\n */\n function claimFromReserve(\n address _reserveHolder,\n address _claimant,\n uint256 _amount\n ) internal virtual returns (uint256);\n\n /**\n * @dev Returns the amount of funds remaining in a reserve\n * @param _reserveHolder Address of reserve holder\n * @return Amount of funds remaining in the reserve for `_reserveHolder`\n */\n function remainingReserve(address _reserveHolder) internal view virtual returns (uint256);\n}\n" + }, + "contracts/pm/mixins/interfaces/MTicketProcessor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nabstract contract MTicketProcessor {\n /**\n * @dev Process sent funds.\n * @param _amount Amount of funds sent\n */\n function processFunding(uint256 _amount) internal virtual;\n\n /**\n * @dev Transfer withdrawal funds for a ticket sender\n * @param _amount Amount of withdrawal funds\n */\n function withdrawTransfer(address payable _sender, uint256 _amount) internal virtual;\n\n /**\n * @dev Transfer funds for a recipient's winning ticket\n * @param _recipient Address of recipient\n * @param _amount Amount of funds for the winning ticket\n * @param _auxData Auxilary data for the winning ticket\n */\n function winningTicketTransfer(\n address _recipient,\n uint256 _amount,\n bytes memory _auxData\n ) internal virtual;\n\n /**\n * @dev Validates a ticket's auxilary data (succeeds or reverts)\n * @param _auxData Auxilary data inclueded in a ticket\n */\n function requireValidTicketAuxData(bytes memory _auxData) internal view virtual;\n}\n" + }, + "contracts/pm/mixins/interfaces/MTicketBrokerCore.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nabstract contract MTicketBrokerCore {\n struct Ticket {\n address recipient; // Address of ticket recipient\n address sender; // Address of ticket sender\n uint256 faceValue; // Face value of ticket paid to recipient if ticket wins\n uint256 winProb; // Probability ticket will win represented as winProb / (2^256 - 1)\n uint256 senderNonce; // Sender's monotonically increasing counter for each ticket\n bytes32 recipientRandHash; // keccak256 hash commitment to recipient's random value\n bytes auxData; // Auxilary data included in ticket used for additional validation\n }\n\n // Emitted when funds are added to a sender's deposit\n event DepositFunded(address indexed sender, uint256 amount);\n // Emitted when a winning ticket is redeemed\n event WinningTicketRedeemed(\n address indexed sender,\n address indexed recipient,\n uint256 faceValue,\n uint256 winProb,\n uint256 senderNonce,\n uint256 recipientRand,\n bytes auxData\n );\n // Emitted when a funds transfer for a winning ticket redemption is executed\n event WinningTicketTransfer(address indexed sender, address indexed recipient, uint256 amount);\n // Emitted when a sender requests an unlock\n event Unlock(address indexed sender, uint256 startRound, uint256 endRound);\n // Emitted when a sender cancels an unlock\n event UnlockCancelled(address indexed sender);\n // Emitted when a sender withdraws its deposit & reserve\n event Withdrawal(address indexed sender, uint256 deposit, uint256 reserve);\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/ECDSA.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../Strings.sol\";\n\n/**\n * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.\n *\n * These functions can be used to verify that a message was signed by the holder\n * of the private keys of a given address.\n */\nlibrary ECDSA {\n enum RecoverError {\n NoError,\n InvalidSignature,\n InvalidSignatureLength,\n InvalidSignatureS,\n InvalidSignatureV\n }\n\n function _throwError(RecoverError error) private pure {\n if (error == RecoverError.NoError) {\n return; // no error: do nothing\n } else if (error == RecoverError.InvalidSignature) {\n revert(\"ECDSA: invalid signature\");\n } else if (error == RecoverError.InvalidSignatureLength) {\n revert(\"ECDSA: invalid signature length\");\n } else if (error == RecoverError.InvalidSignatureS) {\n revert(\"ECDSA: invalid signature 's' value\");\n } else if (error == RecoverError.InvalidSignatureV) {\n revert(\"ECDSA: invalid signature 'v' value\");\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature` or error string. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n *\n * Documentation for signature generation:\n * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]\n * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]\n *\n * _Available since v4.3._\n */\n function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) {\n // Check the signature length\n // - case 65: r,s,v signature (standard)\n // - case 64: r,vs signature (cf https://eips.ethereum.org/EIPS/eip-2098) _Available since v4.1._\n if (signature.length == 65) {\n bytes32 r;\n bytes32 s;\n uint8 v;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n s := mload(add(signature, 0x40))\n v := byte(0, mload(add(signature, 0x60)))\n }\n return tryRecover(hash, v, r, s);\n } else if (signature.length == 64) {\n bytes32 r;\n bytes32 vs;\n // ecrecover takes the signature parameters, and the only way to get them\n // currently is to use assembly.\n assembly {\n r := mload(add(signature, 0x20))\n vs := mload(add(signature, 0x40))\n }\n return tryRecover(hash, r, vs);\n } else {\n return (address(0), RecoverError.InvalidSignatureLength);\n }\n }\n\n /**\n * @dev Returns the address that signed a hashed message (`hash`) with\n * `signature`. This address can then be used for verification purposes.\n *\n * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:\n * this function rejects them by requiring the `s` value to be in the lower\n * half order, and the `v` value to be either 27 or 28.\n *\n * IMPORTANT: `hash` _must_ be the result of a hash operation for the\n * verification to be secure: it is possible to craft signatures that\n * recover to arbitrary addresses for non-hashed data. A safe way to ensure\n * this is by receiving a hash of the original message (which may otherwise\n * be too long), and then calling {toEthSignedMessageHash} on it.\n */\n function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, signature);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.\n *\n * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address, RecoverError) {\n bytes32 s;\n uint8 v;\n assembly {\n s := and(vs, 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff)\n v := add(shr(255, vs), 27)\n }\n return tryRecover(hash, v, r, s);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.\n *\n * _Available since v4.2._\n */\n function recover(\n bytes32 hash,\n bytes32 r,\n bytes32 vs\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, r, vs);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Overload of {ECDSA-tryRecover} that receives the `v`,\n * `r` and `s` signature fields separately.\n *\n * _Available since v4.3._\n */\n function tryRecover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address, RecoverError) {\n // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature\n // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines\n // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most\n // signatures from current libraries generate a unique signature with an s-value in the lower half order.\n //\n // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value\n // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or\n // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept\n // these malleable signatures as well.\n if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {\n return (address(0), RecoverError.InvalidSignatureS);\n }\n if (v != 27 && v != 28) {\n return (address(0), RecoverError.InvalidSignatureV);\n }\n\n // If the signature is valid (and not malleable), return the signer address\n address signer = ecrecover(hash, v, r, s);\n if (signer == address(0)) {\n return (address(0), RecoverError.InvalidSignature);\n }\n\n return (signer, RecoverError.NoError);\n }\n\n /**\n * @dev Overload of {ECDSA-recover} that receives the `v`,\n * `r` and `s` signature fields separately.\n */\n function recover(\n bytes32 hash,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal pure returns (address) {\n (address recovered, RecoverError error) = tryRecover(hash, v, r, s);\n _throwError(error);\n return recovered;\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from a `hash`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {\n // 32 is the length in bytes of hash,\n // enforced by the type signature above\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n32\", hash));\n }\n\n /**\n * @dev Returns an Ethereum Signed Message, created from `s`. This\n * produces hash corresponding to the one signed with the\n * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`]\n * JSON-RPC method as part of EIP-191.\n *\n * See {recover}.\n */\n function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19Ethereum Signed Message:\\n\", Strings.toString(s.length), s));\n }\n\n /**\n * @dev Returns an Ethereum Signed Typed Data, created from a\n * `domainSeparator` and a `structHash`. This produces hash corresponding\n * to the one signed with the\n * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`]\n * JSON-RPC method as part of EIP-712.\n *\n * See {recover}.\n */\n function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32) {\n return keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _HEX_SYMBOLS = \"0123456789abcdef\";\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n // Inspired by OraclizeAPI's implementation - MIT licence\n // https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol\n\n if (value == 0) {\n return \"0\";\n }\n uint256 temp = value;\n uint256 digits;\n while (temp != 0) {\n digits++;\n temp /= 10;\n }\n bytes memory buffer = new bytes(digits);\n while (value != 0) {\n digits -= 1;\n buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));\n value /= 10;\n }\n return string(buffer);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n if (value == 0) {\n return \"0x00\";\n }\n uint256 temp = value;\n uint256 length = 0;\n while (temp != 0) {\n length++;\n temp >>= 8;\n }\n return toHexString(value, length);\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _HEX_SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n}\n" + }, + "contracts/test/mocks/TicketBrokerExtendedMock.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\nimport \"../../pm/TicketBroker.sol\";\n\ncontract TickerBrokerExtendedMock is TicketBroker {\n constructor(address _controller) TicketBroker(_controller) {}\n\n function checkResult(bytes calldata _sig, uint256 _recipientRand) external pure returns (uint256) {\n return uint256(keccak256(abi.encodePacked(_sig, _recipientRand)));\n }\n\n function validateAndCheckTicketOutcome(\n address _sender,\n bytes32 _ticketHash,\n bytes calldata _sig,\n uint256 _recipientRand,\n uint256 _winProb\n ) external pure returns (bool) {\n require(isValidTicketSig(_sender, _sig, _ticketHash), \"invalid signature over ticket hash\");\n return isWinningTicket(_sig, _recipientRand, _winProb);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/draft-EIP712.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/cryptography/draft-EIP712.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\n\n/**\n * @dev https://eips.ethereum.org/EIPS/eip-712[EIP 712] is a standard for hashing and signing of typed structured data.\n *\n * The encoding specified in the EIP is very generic, and such a generic implementation in Solidity is not feasible,\n * thus this contract does not implement the encoding itself. Protocols need to implement the type-specific encoding\n * they need in their contracts using a combination of `abi.encode` and `keccak256`.\n *\n * This contract implements the EIP 712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding\n * scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA\n * ({_hashTypedDataV4}).\n *\n * The implementation of the domain separator was designed to be as efficient as possible while still properly updating\n * the chain id to protect against replay attacks on an eventual fork of the chain.\n *\n * NOTE: This contract implements the version of the encoding known as \"v4\", as implemented by the JSON RPC method\n * https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].\n *\n * _Available since v3.4._\n */\nabstract contract EIP712 {\n /* solhint-disable var-name-mixedcase */\n // Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to\n // invalidate the cached domain separator if the chain id changes.\n bytes32 private immutable _CACHED_DOMAIN_SEPARATOR;\n uint256 private immutable _CACHED_CHAIN_ID;\n address private immutable _CACHED_THIS;\n\n bytes32 private immutable _HASHED_NAME;\n bytes32 private immutable _HASHED_VERSION;\n bytes32 private immutable _TYPE_HASH;\n\n /* solhint-enable var-name-mixedcase */\n\n /**\n * @dev Initializes the domain separator and parameter caches.\n *\n * The meaning of `name` and `version` is specified in\n * https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP 712]:\n *\n * - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.\n * - `version`: the current major version of the signing domain.\n *\n * NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart\n * contract upgrade].\n */\n constructor(string memory name, string memory version) {\n bytes32 hashedName = keccak256(bytes(name));\n bytes32 hashedVersion = keccak256(bytes(version));\n bytes32 typeHash = keccak256(\n \"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)\"\n );\n _HASHED_NAME = hashedName;\n _HASHED_VERSION = hashedVersion;\n _CACHED_CHAIN_ID = block.chainid;\n _CACHED_DOMAIN_SEPARATOR = _buildDomainSeparator(typeHash, hashedName, hashedVersion);\n _CACHED_THIS = address(this);\n _TYPE_HASH = typeHash;\n }\n\n /**\n * @dev Returns the domain separator for the current chain.\n */\n function _domainSeparatorV4() internal view returns (bytes32) {\n if (address(this) == _CACHED_THIS && block.chainid == _CACHED_CHAIN_ID) {\n return _CACHED_DOMAIN_SEPARATOR;\n } else {\n return _buildDomainSeparator(_TYPE_HASH, _HASHED_NAME, _HASHED_VERSION);\n }\n }\n\n function _buildDomainSeparator(\n bytes32 typeHash,\n bytes32 nameHash,\n bytes32 versionHash\n ) private view returns (bytes32) {\n return keccak256(abi.encode(typeHash, nameHash, versionHash, block.chainid, address(this)));\n }\n\n /**\n * @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this\n * function returns the hash of the fully encoded EIP712 message for this domain.\n *\n * This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:\n *\n * ```solidity\n * bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(\n * keccak256(\"Mail(address to,string contents)\"),\n * mailTo,\n * keccak256(bytes(mailContents))\n * )));\n * address signer = ECDSA.recover(digest, signature);\n * ```\n */\n function _hashTypedDataV4(bytes32 structHash) internal view virtual returns (bytes32) {\n return ECDSA.toTypedDataHash(_domainSeparatorV4(), structHash);\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-ERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./draft-IERC20Permit.sol\";\nimport \"../ERC20.sol\";\nimport \"../../../utils/cryptography/draft-EIP712.sol\";\nimport \"../../../utils/cryptography/ECDSA.sol\";\nimport \"../../../utils/Counters.sol\";\n\n/**\n * @dev Implementation 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 *\n * _Available since v3.4._\n */\nabstract contract ERC20Permit is ERC20, IERC20Permit, EIP712 {\n using Counters for Counters.Counter;\n\n mapping(address => Counters.Counter) private _nonces;\n\n // solhint-disable-next-line var-name-mixedcase\n bytes32 private immutable _PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC20 token name.\n */\n constructor(string memory name) EIP712(name, \"1\") {}\n\n /**\n * @dev See {IERC20Permit-permit}.\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 ) public virtual override {\n require(block.timestamp <= deadline, \"ERC20Permit: expired deadline\");\n\n bytes32 structHash = keccak256(abi.encode(_PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n require(signer == owner, \"ERC20Permit: invalid signature\");\n\n _approve(owner, spender, value);\n }\n\n /**\n * @dev See {IERC20Permit-nonces}.\n */\n function nonces(address owner) public view virtual override returns (uint256) {\n return _nonces[owner].current();\n }\n\n /**\n * @dev See {IERC20Permit-DOMAIN_SEPARATOR}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view override returns (bytes32) {\n return _domainSeparatorV4();\n }\n\n /**\n * @dev \"Consume a nonce\": return the current value and increment.\n *\n * _Available since v4.1._\n */\n function _useNonce(address owner) internal virtual returns (uint256 current) {\n Counters.Counter storage nonce = _nonces[owner];\n current = nonce.current();\n nonce.increment();\n }\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/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `recipient` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address recipient, uint256 amount) public virtual override returns (bool) {\n _transfer(_msgSender(), recipient, 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 * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n _approve(_msgSender(), 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 * Requirements:\n *\n * - `sender` and `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n * - the caller must have allowance for ``sender``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address sender,\n address recipient,\n uint256 amount\n ) public virtual override returns (bool) {\n _transfer(sender, recipient, amount);\n\n uint256 currentAllowance = _allowances[sender][_msgSender()];\n require(currentAllowance >= amount, \"ERC20: transfer amount exceeds allowance\");\n unchecked {\n _approve(sender, _msgSender(), currentAllowance - amount);\n }\n\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 _approve(_msgSender(), spender, _allowances[_msgSender()][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 uint256 currentAllowance = _allowances[_msgSender()][spender];\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `sender` to `recipient`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `sender` cannot be the zero address.\n * - `recipient` cannot be the zero address.\n * - `sender` must have a balance of at least `amount`.\n */\n function _transfer(\n address sender,\n address recipient,\n uint256 amount\n ) internal virtual {\n require(sender != address(0), \"ERC20: transfer from the zero address\");\n require(recipient != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(sender, recipient, amount);\n\n uint256 senderBalance = _balances[sender];\n require(senderBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[sender] = senderBalance - amount;\n }\n _balances[recipient] += amount;\n\n emit Transfer(sender, recipient, amount);\n\n _afterTokenTransfer(sender, recipient, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n _balances[account] += amount;\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n }\n _totalSupply -= amount;\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/utils/Counters.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Counters.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @title Counters\n * @author Matt Condon (@shrugs)\n * @dev Provides counters that can only be incremented, decremented or reset. This can be used e.g. to track the number\n * of elements in a mapping, issuing ERC721 ids, or counting request ids.\n *\n * Include with `using Counters for Counters.Counter;`\n */\nlibrary Counters {\n struct Counter {\n // This variable should never be directly accessed by users of the library: interactions must be restricted to\n // the library's function. As of Solidity v0.5.2, this cannot be enforced, though there is a proposal to add\n // this feature: see https://github.com/ethereum/solidity/issues/4637\n uint256 _value; // default: 0\n }\n\n function current(Counter storage counter) internal view returns (uint256) {\n return counter._value;\n }\n\n function increment(Counter storage counter) internal {\n unchecked {\n counter._value += 1;\n }\n }\n\n function decrement(Counter storage counter) internal {\n uint256 value = counter._value;\n require(value > 0, \"Counter: decrement overflow\");\n unchecked {\n counter._value = value - 1;\n }\n }\n\n function reset(Counter storage counter) internal {\n counter._value = 0;\n }\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/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Burnable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../ERC20.sol\";\nimport \"../../../utils/Context.sol\";\n\n/**\n * @dev Extension of {ERC20} that allows token holders to destroy both their own\n * tokens and those that they have an allowance for, in a way that can be\n * recognized off-chain (via event analysis).\n */\nabstract contract ERC20Burnable is Context, ERC20 {\n /**\n * @dev Destroys `amount` tokens from the caller.\n *\n * See {ERC20-_burn}.\n */\n function burn(uint256 amount) public virtual {\n _burn(_msgSender(), amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, deducting from the caller's\n * allowance.\n *\n * See {ERC20-_burn} and {ERC20-allowance}.\n *\n * Requirements:\n *\n * - the caller must have allowance for ``accounts``'s tokens of at least\n * `amount`.\n */\n function burnFrom(address account, uint256 amount) public virtual {\n uint256 currentAllowance = allowance(account, _msgSender());\n require(currentAllowance >= amount, \"ERC20: burn amount exceeds allowance\");\n unchecked {\n _approve(account, _msgSender(), currentAllowance - amount);\n }\n _burn(account, amount);\n }\n}\n" + }, + "@openzeppelin/contracts/access/AccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/AccessControl.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IAccessControl.sol\";\nimport \"../utils/Context.sol\";\nimport \"../utils/Strings.sol\";\nimport \"../utils/introspection/ERC165.sol\";\n\n/**\n * @dev Contract module that allows children to implement role-based access\n * control mechanisms. This is a lightweight version that doesn't allow enumerating role\n * members except through off-chain means by accessing the contract event logs. Some\n * applications may benefit from on-chain enumerability, for those cases see\n * {AccessControlEnumerable}.\n *\n * Roles are referred to by their `bytes32` identifier. These should be exposed\n * in the external API and be unique. The best way to achieve this is by\n * using `public constant` hash digests:\n *\n * ```\n * bytes32 public constant MY_ROLE = keccak256(\"MY_ROLE\");\n * ```\n *\n * Roles can be used to represent a set of permissions. To restrict access to a\n * function call, use {hasRole}:\n *\n * ```\n * function foo() public {\n * require(hasRole(MY_ROLE, msg.sender));\n * ...\n * }\n * ```\n *\n * Roles can be granted and revoked dynamically via the {grantRole} and\n * {revokeRole} functions. Each role has an associated admin role, and only\n * accounts that have a role's admin role can call {grantRole} and {revokeRole}.\n *\n * By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means\n * that only accounts with this role will be able to grant or revoke other\n * roles. More complex role relationships can be created by using\n * {_setRoleAdmin}.\n *\n * WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to\n * grant and revoke this role. Extra precautions should be taken to secure\n * accounts that have been granted it.\n */\nabstract contract AccessControl is Context, IAccessControl, ERC165 {\n struct RoleData {\n mapping(address => bool) members;\n bytes32 adminRole;\n }\n\n mapping(bytes32 => RoleData) private _roles;\n\n bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;\n\n /**\n * @dev Modifier that checks that an account has a specific role. Reverts\n * with a standardized message including the required role.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n *\n * _Available since v4.1._\n */\n modifier onlyRole(bytes32 role) {\n _checkRole(role, _msgSender());\n _;\n }\n\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);\n }\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) public view override returns (bool) {\n return _roles[role].members[account];\n }\n\n /**\n * @dev Revert with a standard message if `account` is missing `role`.\n *\n * The format of the revert reason is given by the following regular expression:\n *\n * /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/\n */\n function _checkRole(bytes32 role, address account) internal view {\n if (!hasRole(role, account)) {\n revert(\n string(\n abi.encodePacked(\n \"AccessControl: account \",\n Strings.toHexString(uint160(account), 20),\n \" is missing role \",\n Strings.toHexString(uint256(role), 32)\n )\n )\n );\n }\n }\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) public view override returns (bytes32) {\n return _roles[role].adminRole;\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _grantRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {\n _revokeRole(role, account);\n }\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been revoked `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) public virtual override {\n require(account == _msgSender(), \"AccessControl: can only renounce roles for self\");\n\n _revokeRole(role, account);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event. Note that unlike {grantRole}, this function doesn't perform any\n * checks on the calling account.\n *\n * [WARNING]\n * ====\n * This function should only be called from the constructor when setting\n * up the initial roles for the system.\n *\n * Using this function in any other way is effectively circumventing the admin\n * system imposed by {AccessControl}.\n * ====\n *\n * NOTE: This function is deprecated in favor of {_grantRole}.\n */\n function _setupRole(bytes32 role, address account) internal virtual {\n _grantRole(role, account);\n }\n\n /**\n * @dev Sets `adminRole` as ``role``'s admin role.\n *\n * Emits a {RoleAdminChanged} event.\n */\n function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {\n bytes32 previousAdminRole = getRoleAdmin(role);\n _roles[role].adminRole = adminRole;\n emit RoleAdminChanged(role, previousAdminRole, adminRole);\n }\n\n /**\n * @dev Grants `role` to `account`.\n *\n * Internal function without access restriction.\n */\n function _grantRole(bytes32 role, address account) internal virtual {\n if (!hasRole(role, account)) {\n _roles[role].members[account] = true;\n emit RoleGranted(role, account, _msgSender());\n }\n }\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * Internal function without access restriction.\n */\n function _revokeRole(bytes32 role, address account) internal virtual {\n if (hasRole(role, account)) {\n _roles[role].members[account] = false;\n emit RoleRevoked(role, account, _msgSender());\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/IAccessControl.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev External interface of AccessControl declared to support ERC165 detection.\n */\ninterface IAccessControl {\n /**\n * @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`\n *\n * `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite\n * {RoleAdminChanged} not being emitted signaling this.\n *\n * _Available since v3.1._\n */\n event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);\n\n /**\n * @dev Emitted when `account` is granted `role`.\n *\n * `sender` is the account that originated the contract call, an admin role\n * bearer except when using {AccessControl-_setupRole}.\n */\n event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Emitted when `account` is revoked `role`.\n *\n * `sender` is the account that originated the contract call:\n * - if using `revokeRole`, it is the admin role bearer\n * - if using `renounceRole`, it is the role bearer (i.e. `account`)\n */\n event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);\n\n /**\n * @dev Returns `true` if `account` has been granted `role`.\n */\n function hasRole(bytes32 role, address account) external view returns (bool);\n\n /**\n * @dev Returns the admin role that controls `role`. See {grantRole} and\n * {revokeRole}.\n *\n * To change a role's admin, use {AccessControl-_setRoleAdmin}.\n */\n function getRoleAdmin(bytes32 role) external view returns (bytes32);\n\n /**\n * @dev Grants `role` to `account`.\n *\n * If `account` had not been already granted `role`, emits a {RoleGranted}\n * event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function grantRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from `account`.\n *\n * If `account` had been granted `role`, emits a {RoleRevoked} event.\n *\n * Requirements:\n *\n * - the caller must have ``role``'s admin role.\n */\n function revokeRole(bytes32 role, address account) external;\n\n /**\n * @dev Revokes `role` from the calling account.\n *\n * Roles are often managed via {grantRole} and {revokeRole}: this function's\n * purpose is to provide a mechanism for accounts to lose their privileges\n * if they are compromised (such as when a trusted device is misplaced).\n *\n * If the calling account had been granted `role`, emits a {RoleRevoked}\n * event.\n *\n * Requirements:\n *\n * - the caller must be `account`.\n */\n function renounceRole(bytes32 role, address account) external;\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/ERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC165.sol\";\n\n/**\n * @dev Implementation of the {IERC165} interface.\n *\n * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check\n * for the additional interface id that will be supported. For example:\n *\n * ```solidity\n * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);\n * }\n * ```\n *\n * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.\n */\nabstract contract ERC165 is IERC165 {\n /**\n * @dev See {IERC165-supportsInterface}.\n */\n function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {\n return interfaceId == type(IERC165).interfaceId;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/introspection/IERC165.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC165 standard, as defined in the\n * https://eips.ethereum.org/EIPS/eip-165[EIP].\n *\n * Implementers can declare support of contract interfaces, which can then be\n * queried by others ({ERC165Checker}).\n *\n * For an implementation, see {ERC165}.\n */\ninterface IERC165 {\n /**\n * @dev Returns true if this contract implements the interface defined by\n * `interfaceId`. See the corresponding\n * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]\n * to learn more about how these ids are created.\n *\n * This function call must use less than 30 000 gas.\n */\n function supportsInterface(bytes4 interfaceId) external view returns (bool);\n}\n" + }, + "contracts/token/LivepeerToken.sol": { + "content": "//SPDX-License-Identifier: MIT\n// solhint-disable-next-line\npragma solidity 0.8.9;\n\nimport { AccessControl } from \"@openzeppelin/contracts/access/AccessControl.sol\";\nimport { ERC20, ERC20Permit } from \"@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol\";\nimport { ERC20Burnable } from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol\";\n\n// Copy of https://github.com/livepeer/arbitrum-lpt-bridge/blob/main/contracts/L2/token/LivepeerToken.sol\n// Tests at https://github.com/livepeer/arbitrum-lpt-bridge/blob/main/test/unit/L2/livepeerToken.test.ts\ncontract LivepeerToken is AccessControl, ERC20Burnable, ERC20Permit {\n bytes32 private immutable MINTER_ROLE = keccak256(\"MINTER_ROLE\");\n bytes32 private immutable BURNER_ROLE = keccak256(\"BURNER_ROLE\");\n\n event Mint(address indexed to, uint256 amount);\n event Burn(address indexed burner, uint256 amount);\n\n constructor() ERC20(\"Livepeer Token\", \"LPT\") ERC20Permit(\"Livepeer Token\") {\n _grantRole(DEFAULT_ADMIN_ROLE, msg.sender);\n }\n\n /**\n * @notice Function to mint tokens\n * @dev Only callable by addreses with MINTER_ROLE\n * @param _to The address that will receive the minted tokens.\n * @param _amount The amount of tokens to mint.\n */\n function mint(address _to, uint256 _amount) external onlyRole(MINTER_ROLE) {\n _mint(_to, _amount);\n emit Mint(_to, _amount);\n }\n\n /**\n * @notice Burns a specific amount of msg.sender's tokens\n * @dev Only callable by addresses with BURNER_ROLE\n * @param _amount The amount of tokens to be burned\n */\n function burn(uint256 _amount) public override onlyRole(BURNER_ROLE) {\n super.burn(_amount);\n emit Burn(msg.sender, _amount);\n }\n\n /**\n * @notice Burns a specific amount of an address' tokens\n * @dev Only callable by addresses with BURNER_ROLE. Requires the address to approve the caller to burn the amount\n * @param _from Address to burn tokens for\n * @param _amount The amount of tokens to be burned\n */\n function burnFrom(address _from, uint256 _amount) public override onlyRole(BURNER_ROLE) {\n super.burnFrom(_from, _amount);\n emit Burn(_from, _amount);\n }\n}\n" + }, + "contracts/token/LivepeerTokenFaucet.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./ILivepeerToken.sol\";\n\nimport \"../zeppelin/Ownable.sol\";\n\n/**\n * @title Faucet for the Livepeer Token\n */\ncontract LivepeerTokenFaucet is Ownable {\n // Token\n ILivepeerToken public token;\n\n // Amount of token sent to sender for a request\n uint256 public requestAmount;\n\n // Amount of time a sender must wait between requests\n uint256 public requestWait;\n\n // sender => timestamp at which sender can make another request\n mapping(address => uint256) public nextValidRequest;\n\n // Whitelist addresses that can bypass faucet request rate limit\n mapping(address => bool) public isWhitelisted;\n\n // Checks if a request is valid (sender is whitelisted or has waited the rate limit time)\n modifier validRequest() {\n require(isWhitelisted[msg.sender] || block.timestamp >= nextValidRequest[msg.sender]);\n _;\n }\n\n event Request(address indexed to, uint256 amount);\n\n /**\n * @notice LivepeerTokenFacuet constructor\n * @param _token Address of LivepeerToken\n * @param _requestAmount Amount of token sent to sender for a request\n * @param _requestWait Amount of time a sender must wait between request (denominated in hours)\n */\n constructor(\n address _token,\n uint256 _requestAmount,\n uint256 _requestWait\n ) {\n token = ILivepeerToken(_token);\n requestAmount = _requestAmount;\n requestWait = _requestWait;\n }\n\n /**\n * @notice Add an address to the whitelist\n * @param _addr Address to be whitelisted\n */\n function addToWhitelist(address _addr) external onlyOwner {\n isWhitelisted[_addr] = true;\n }\n\n /**\n * @notice Remove an address from the whitelist\n * @param _addr Address to be removed from whitelist\n */\n function removeFromWhitelist(address _addr) external onlyOwner {\n isWhitelisted[_addr] = false;\n }\n\n /**\n * @notice Request an amount of token to be sent to sender\n */\n function request() external validRequest {\n if (!isWhitelisted[msg.sender]) {\n nextValidRequest[msg.sender] = block.timestamp + requestWait * 1 hours;\n }\n\n token.transfer(msg.sender, requestAmount);\n\n emit Request(msg.sender, requestAmount);\n }\n}\n" + }, + "contracts/Controller.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./IController.sol\";\nimport \"./IManager.sol\";\n\nimport \"./zeppelin/Pausable.sol\";\n\ncontract Controller is Pausable, IController {\n // Track information about a registered contract\n struct ContractInfo {\n address contractAddress; // Address of contract\n bytes20 gitCommitHash; // SHA1 hash of head Git commit during registration of this contract\n }\n\n // Track contract ids and contract info\n mapping(bytes32 => ContractInfo) private registry;\n\n constructor() {\n // Start system as paused\n paused = true;\n }\n\n /**\n * @notice Register contract id and mapped address\n * @param _id Contract id (keccak256 hash of contract name)\n * @param _contractAddress Contract address\n */\n function setContractInfo(\n bytes32 _id,\n address _contractAddress,\n bytes20 _gitCommitHash\n ) external override onlyOwner {\n registry[_id].contractAddress = _contractAddress;\n registry[_id].gitCommitHash = _gitCommitHash;\n\n emit SetContractInfo(_id, _contractAddress, _gitCommitHash);\n }\n\n /**\n * @notice Update contract's controller\n * @param _id Contract id (keccak256 hash of contract name)\n * @param _controller Controller address\n */\n function updateController(bytes32 _id, address _controller) external override onlyOwner {\n return IManager(registry[_id].contractAddress).setController(_controller);\n }\n\n /**\n * @notice Return contract info for a given contract id\n * @param _id Contract id (keccak256 hash of contract name)\n */\n function getContractInfo(bytes32 _id) public view returns (address, bytes20) {\n return (registry[_id].contractAddress, registry[_id].gitCommitHash);\n }\n\n /**\n * @notice Get contract address for an id\n * @param _id Contract id\n */\n function getContract(bytes32 _id) public view override returns (address) {\n return registry[_id].contractAddress;\n }\n}\n" + }, + "contracts/snapshots/MerkleSnapshot.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../zeppelin/MerkleProof.sol\";\nimport \"../Manager.sol\";\n\ncontract MerkleSnapshot is Manager {\n mapping(bytes32 => bytes32) public snapshot;\n\n constructor(address _controller) Manager(_controller) {}\n\n function setSnapshot(bytes32 _id, bytes32 _root) external onlyControllerOwner {\n snapshot[_id] = _root;\n }\n\n function verify(\n bytes32 _id,\n bytes32[] calldata _proof,\n bytes32 _leaf\n ) external view returns (bool) {\n return MerkleProof.verify(_proof, snapshot[_id], _leaf);\n }\n}\n" + }, + "contracts/zeppelin/MerkleProof.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\n/**\n * @dev These functions deal with verification of Merkle trees (hash trees),\n */\nlibrary MerkleProof {\n /**\n * @dev Returns true if a `leaf` can be proved to be a part of a Merkle tree\n * defined by `root`. For this, a `proof` must be provided, containing\n * sibling hashes on the branch from the leaf to the root of the tree. Each\n * pair of leaves and each pair of pre-images are assumed to be sorted.\n */\n function verify(\n bytes32[] memory proof,\n bytes32 root,\n bytes32 leaf\n ) internal pure returns (bool) {\n bytes32 computedHash = leaf;\n\n for (uint256 i = 0; i < proof.length; i++) {\n bytes32 proofElement = proof[i];\n\n if (computedHash <= proofElement) {\n // Hash(current computed hash + current element of the proof)\n computedHash = keccak256(abi.encodePacked(computedHash, proofElement));\n } else {\n // Hash(current element of the proof + current computed hash)\n computedHash = keccak256(abi.encodePacked(proofElement, computedHash));\n }\n }\n\n // Check if the computed hash (root) is equal to the provided root\n return computedHash == root;\n }\n}\n" + }, + "contracts/test/mocks/ManagerProxyTargetMockV3.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../ManagerProxyTarget.sol\";\n\ncontract ManagerProxyTargetMockV3 is ManagerProxyTarget {\n uint256 public initValue;\n uint8 public uint8Value;\n uint64 public uint64Value;\n uint256 public uint256Value;\n bytes32 public bytes32Value;\n address public addressValue;\n mapping(uint256 => uint256) public kvMap;\n\n constructor(address _controller) Manager(_controller) {}\n\n function setUint8(uint8 _value) external {\n uint8Value = _value;\n }\n\n function setUint64(uint64 _value) external {\n uint64Value = _value;\n }\n\n function setUint256(uint256 _value) external {\n uint256Value = _value;\n }\n\n function setBytes32(bytes32 _value) external {\n bytes32Value = _value;\n }\n\n function setAddress(address _value) external {\n addressValue = _value;\n }\n\n function setKv(uint256 _key, uint256 _value) external {\n kvMap[_key] = _value;\n }\n}\n" + }, + "contracts/test/mocks/ManagerProxyTargetMockV2.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../ManagerProxyTarget.sol\";\n\ncontract ManagerProxyTargetMockV2 is ManagerProxyTarget {\n uint256 public initValue;\n uint8 public uint8Value;\n uint64 public uint64Value;\n uint256 public uint256Value;\n bytes32 public bytes32Value;\n address public addressValue;\n\n constructor(address _controller) Manager(_controller) {}\n\n function setUint8(uint8 _value) external {\n uint8Value = _value + 5;\n }\n\n function setUint64(uint64 _value) external {\n uint64Value = _value + 5;\n }\n\n function setUint256(uint256 _value) external {\n uint256Value = _value + 5;\n }\n\n function setBytes32(bytes32 _value) external {\n bytes32Value = keccak256(abi.encodePacked(_value));\n }\n\n function setAddress(address _value) external {\n addressValue = _value; // to supress compilation warnings\n addressValue = address(0);\n }\n}\n" + }, + "contracts/test/mocks/ManagerProxyTargetMockV1.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"../../ManagerProxyTarget.sol\";\n\ncontract ManagerProxyTargetMockV1 is ManagerProxyTarget {\n uint256 public initValue;\n uint8 public uint8Value;\n uint64 public uint64Value;\n uint256 public uint256Value;\n bytes32 public bytes32Value;\n address public addressValue;\n string public stringValue;\n bytes public bytesValue;\n uint256 public tupleValue1;\n uint256 public tupleValue2;\n bytes32 public tupleValue3;\n\n constructor(address _controller) Manager(_controller) {}\n\n receive() external payable {}\n\n function setUint8(uint8 _value) external {\n uint8Value = _value;\n }\n\n function setUint64(uint64 _value) external {\n uint64Value = _value;\n }\n\n function setUint256(uint256 _value) external {\n uint256Value = _value;\n }\n\n function setBytes32(bytes32 _value) external {\n bytes32Value = _value;\n }\n\n function setAddress(address _value) external {\n addressValue = _value;\n }\n\n function setString(string calldata _value) external {\n stringValue = _value;\n }\n\n function setBytes(bytes calldata _value) external {\n bytesValue = _value;\n }\n\n function setTuple(\n uint256 _value1,\n uint256 _value2,\n bytes32 _value3\n ) external {\n tupleValue1 = _value1;\n tupleValue2 = _value2;\n tupleValue3 = _value3;\n }\n\n function getTuple()\n external\n view\n returns (\n uint256,\n uint256,\n bytes32\n )\n {\n return (tupleValue1, tupleValue2, tupleValue3);\n }\n}\n" + }, + "contracts/ServiceRegistry.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./ManagerProxyTarget.sol\";\n\n/**\n * @title ServiceRegistry\n * @notice Maintains a registry of service metadata associated with service provider addresses (transcoders/orchestrators)\n */\ncontract ServiceRegistry is ManagerProxyTarget {\n // Store service metadata\n struct Record {\n string serviceURI; // Service URI endpoint that can be used to send off-chain requests\n }\n\n // Track records for addresses\n mapping(address => Record) private records;\n\n // Event fired when a caller updates its service URI endpoint\n event ServiceURIUpdate(address indexed addr, string serviceURI);\n\n /**\n * @notice ServiceRegistry constructor. Only invokes constructor of base Manager contract with provided Controller address\n * @param _controller Address of a Controller that this contract will be registered with\n */\n constructor(address _controller) Manager(_controller) {}\n\n /**\n * @notice Stores service URI endpoint for the caller that can be used to send requests to the caller off-chain\n * @param _serviceURI Service URI endpoint for the caller\n */\n function setServiceURI(string calldata _serviceURI) external {\n records[msg.sender].serviceURI = _serviceURI;\n\n emit ServiceURIUpdate(msg.sender, _serviceURI);\n }\n\n /**\n * @notice Returns service URI endpoint stored for a given address\n * @param _addr Address for which a service URI endpoint is desired\n */\n function getServiceURI(address _addr) public view returns (string memory) {\n return records[_addr].serviceURI;\n }\n}\n" + }, + "contracts/ManagerProxy.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./ManagerProxyTarget.sol\";\n\n/**\n * @title ManagerProxy\n * @notice A proxy contract that uses delegatecall to execute function calls on a target contract using its own storage context.\n The target contract is a Manager contract that is registered with the Controller.\n * @dev Both this proxy contract and its target contract MUST inherit from ManagerProxyTarget in order to guarantee\n that both contracts have the same storage layout. Differing storage layouts in a proxy contract and target contract can\n potentially break the delegate proxy upgradeability mechanism. Since this proxy contract inherits from ManagerProxyTarget which inherits\n from Manager, it implements the setController() function. The target contract will also implement setController() since it also inherits\n from ManagerProxyTarget. Thus, any transaction sent to the proxy that calls setController() will execute against the proxy instead\n of the target. As a result, developers should keep in mind that the proxy will always execute the same logic for setController() regardless\n of the setController() implementation on the target contract. Generally, developers should not add any additional functions to this proxy contract\n because any function implemented on the proxy will always be executed against the proxy and the call **will not** be forwarded to the target contract\n */\ncontract ManagerProxy is ManagerProxyTarget {\n /**\n * @notice ManagerProxy constructor. Invokes constructor of base Manager contract with provided Controller address.\n * Also, sets the contract ID of the target contract that function calls will be executed on.\n * @param _controller Address of Controller that this contract will be registered with\n * @param _targetContractId contract ID of the target contract\n */\n constructor(address _controller, bytes32 _targetContractId) Manager(_controller) {\n targetContractId = _targetContractId;\n }\n\n /**\n * @notice Fallback function that delegates calls to target contract when there is no msg.data\n */\n receive() external payable {\n _fallback();\n }\n\n /**\n * @notice Fallback function that delegates calls to target contract when there is msg.data\n */\n fallback() external payable {\n _fallback();\n }\n\n /**\n * @dev Uses delegatecall to execute function calls on this proxy contract's target contract using its own storage context.\n This fallback function will look up the address of the target contract using the Controller and the target contract ID.\n It will then use the calldata for a function call as the data payload for a delegatecall on the target contract. The return value\n of the executed function call will also be returned\n */\n function _fallback() private {\n address target = controller.getContract(targetContractId);\n require(target != address(0), \"target contract must be registered\");\n\n assembly {\n // Solidity keeps a free memory pointer at position 0x40 in memory\n let freeMemoryPtrPosition := 0x40\n // Load the free memory pointer\n let calldataMemoryOffset := mload(freeMemoryPtrPosition)\n // Update free memory pointer to after memory space we reserve for calldata\n mstore(freeMemoryPtrPosition, add(calldataMemoryOffset, calldatasize()))\n // Copy calldata (method signature and params of the call) to memory\n calldatacopy(calldataMemoryOffset, 0x0, calldatasize())\n\n // Call method on target contract using calldata which is loaded into memory\n let ret := delegatecall(gas(), target, calldataMemoryOffset, calldatasize(), 0, 0)\n\n // Load the free memory pointer\n let returndataMemoryOffset := mload(freeMemoryPtrPosition)\n // Update free memory pointer to after memory space we reserve for returndata\n mstore(freeMemoryPtrPosition, add(returndataMemoryOffset, returndatasize()))\n // Copy returndata (result of the method invoked by the delegatecall) to memory\n returndatacopy(returndataMemoryOffset, 0x0, returndatasize())\n\n switch ret\n case 0 {\n // Method call failed - revert\n // Return any error message stored in mem[returndataMemoryOffset..(returndataMemoryOffset + returndatasize)]\n revert(returndataMemoryOffset, returndatasize())\n }\n default {\n // Return result of method call stored in mem[returndataMemoryOffset..(returndataMemoryOffset + returndatasize)]\n return(returndataMemoryOffset, returndatasize())\n }\n }\n }\n}\n" + }, + "contracts/rounds/AdjustableRoundsManager.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"./RoundsManager.sol\";\n\ncontract AdjustableRoundsManager is RoundsManager {\n uint256 public num;\n bytes32 public hash;\n\n constructor(address _controller) RoundsManager(_controller) {}\n\n function setBlockNum(uint256 _num) external {\n num = _num;\n }\n\n function setBlockHash(bytes32 _hash) external {\n hash = _hash;\n }\n\n function mineBlocks(uint256 _blocks) external {\n num += _blocks;\n }\n\n function blockNum() public view override returns (uint256) {\n return num;\n }\n\n function blockHash(uint256 _block) public view override returns (bytes32) {\n require(_block >= blockNum() - 256);\n\n return hash;\n }\n}\n" + }, + "contracts/governance/Governor.sol": { + "content": "// SPDX-License-Identifier: MIT\npragma solidity 0.8.9;\n\nimport \"@openzeppelin/contracts/utils/math/SafeMath.sol\";\n\n/**\n * @title Governor\n * @dev The Governor holds the rights to stage and execute contract calls i.e. changing Livepeer protocol parameters.\n */\ncontract Governor {\n using SafeMath for uint256;\n\n address public owner;\n\n /// @dev mapping of updateHash (keccak256(update) => executeBlock (block.number + delay)\n mapping(bytes32 => uint256) public updates;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n event UpdateStaged(Update update, uint256 delay);\n\n event UpdateExecuted(Update update);\n\n event UpdateCancelled(Update update);\n\n struct Update {\n address[] target;\n uint256[] value;\n bytes[] data;\n uint256 nonce;\n }\n\n /// @notice Throws if called by any account other than the owner.\n modifier onlyOwner() {\n require(msg.sender == owner, \"unauthorized: msg.sender not owner\");\n _;\n }\n\n /// @notice Throws if called by any account other than this contract.\n /// @dev Forces the `stage/execute` path to be used to call functions with this modifier instead of directly.\n modifier onlyThis() {\n require(msg.sender == address(this), \"unauthorized: msg.sender not Governor\");\n _;\n }\n\n /// @dev The Ownable constructor sets the original `owner` of the contract to the sender account.\n constructor() {\n owner = msg.sender;\n emit OwnershipTransferred(address(0), msg.sender);\n }\n\n /// @notice Allows the current owner to transfer control of the contract to a newOwner.\n /// @dev Can only be called through stage/execute, will revert if the caller is not this contract's address.\n /// @param newOwner The address to transfer ownership to.\n function transferOwnership(address newOwner) public onlyThis {\n require(newOwner != address(0), \"newOwner is a null address\");\n emit OwnershipTransferred(owner, newOwner);\n owner = newOwner;\n }\n\n /// @notice Stage a batch of updates to be executed.\n /// @dev Reverts if the 'msg.sender' is not the 'owner'\n /// @dev Reverts if an update is already staged\n /// @param _update Update to be staged.\n /// @param _delay (uint256) Delay (in number of blocks) for the update.\n function stage(Update memory _update, uint256 _delay) public onlyOwner {\n bytes32 updateHash = keccak256(abi.encode(_update));\n\n require(updates[updateHash] == 0, \"update already staged\");\n\n updates[updateHash] = block.number.add(_delay);\n\n emit UpdateStaged(_update, _delay);\n }\n\n /// @notice Execute a staged update.\n /// @dev Updates are authorized during staging.\n /// @dev Reverts if a transaction can not be executed.\n /// @param _update Update to be staged.\n function execute(Update memory _update) public payable {\n bytes32 updateHash = keccak256(abi.encode(_update));\n uint256 executeBlock = updates[updateHash];\n\n require(executeBlock != 0, \"update is not staged\");\n require(block.number >= executeBlock, \"delay for update not expired\");\n\n // prevent re-entry and replay\n delete updates[updateHash];\n for (uint256 i = 0; i < _update.target.length; i++) {\n /* solium-disable-next-line */\n (bool success, bytes memory returnData) = _update.target[i].call{ value: _update.value[i] }(\n _update.data[i]\n );\n require(success, string(returnData));\n }\n\n emit UpdateExecuted(_update);\n }\n\n /// @notice Cancel a staged update.\n /// @dev Reverts if an update does not exist.\n /// @dev Reverts if the 'msg.sender' is not the 'owner'\n /// @param _update Update to be cancelled.\n function cancel(Update memory _update) public onlyOwner {\n bytes32 updateHash = keccak256(abi.encode(_update));\n uint256 executeBlock = updates[updateHash];\n\n require(executeBlock != 0, \"update is not staged\");\n delete updates[updateHash];\n\n emit UpdateCancelled(_update);\n }\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 200 + }, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file