diff --git a/contracts/tokenWrappers/PointToken.sol b/contracts/tokenWrappers/PointToken.sol new file mode 100644 index 0000000..939ba6d --- /dev/null +++ b/contracts/tokenWrappers/PointToken.sol @@ -0,0 +1,75 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity ^0.8.7; + +import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import { ICore } from "../interfaces/ICore.sol"; +import "../utils/Errors.sol"; + +/// @title PointToken +/// @author Angle Labs, Inc. +/// @notice Reference contract for points systems within Merkl +contract PointToken is ERC20 { + mapping(address => bool) public minters; + mapping(address => bool) public whitelistedRecipients; + ICore public accessControlManager; + uint8 public allowedTransfers; + + constructor( + string memory name_, + string memory symbol_, + address _minter, + address _accessControlManager + ) ERC20(name_, symbol_) { + if (_accessControlManager == address(0) || _minter == address(0)) revert ZeroAddress(); + accessControlManager = ICore(_accessControlManager); + minters[_minter] = true; + } + + modifier onlyGovernorOrGuardian() { + if (!accessControlManager.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian(); + _; + } + + modifier onlyMinter() { + if (!minters[msg.sender]) revert NotTrusted(); + _; + } + + function mint(address account, uint256 amount) external onlyMinter { + _mint(account, amount); + } + + function burn(address account, uint256 amount) external onlyMinter { + _burn(account, amount); + } + + function mintBatch(address[] memory accounts, uint256[] memory amounts) external onlyMinter { + uint256 length = accounts.length; + for (uint256 i = 0; i < length; ++i) { + _mint(accounts[i], amounts[i]); + } + } + + function toggleMinter(address minter) external onlyGovernorOrGuardian { + minters[minter] = !minters[minter]; + } + + function toggleAllowedTransfers() external onlyGovernorOrGuardian { + allowedTransfers = 1 - allowedTransfers; + } + + function toggleWhitelistedRecipient(address recipient) external onlyGovernorOrGuardian { + whitelistedRecipients[recipient] = !whitelistedRecipients[recipient]; + } + + function _beforeTokenTransfer(address from, address to, uint256) internal view override { + if ( + allowedTransfers == 0 && + from != address(0) && + to != address(0) && + !whitelistedRecipients[from] && + !whitelistedRecipients[to] + ) revert NotAllowed(); + } +} diff --git a/contracts/utils/Errors.sol b/contracts/utils/Errors.sol index b2ddd9e..709e22b 100644 --- a/contracts/utils/Errors.sol +++ b/contracts/utils/Errors.sol @@ -17,6 +17,7 @@ error InvalidUninitializedRoot(); error InvalidReward(); error InvalidSignature(); error NoDispute(); +error NotAllowed(); error NotGovernor(); error NotGovernorOrGuardian(); error NotSigned(); diff --git a/deploy/pointToken.ts b/deploy/pointToken.ts new file mode 100644 index 0000000..5d40920 --- /dev/null +++ b/deploy/pointToken.ts @@ -0,0 +1,30 @@ +import { DeployFunction } from 'hardhat-deploy/types'; +import yargs from 'yargs'; + +const argv = yargs.env('').boolean('ci').parseSync(); + +const func: DeployFunction = async ({ deployments, ethers, network }) => { + const { deploy } = deployments; + const { deployer } = await ethers.getNamedSigners(); + let core: string; + + const implementationName = 'PointToken'; + + console.log(`Now deploying ${implementationName}`); + console.log('Starting with the implementation'); + + await deploy(implementationName, { + contract: implementationName, + from: deployer.address, + args: ["Angle Prots","agProts", "0xA9DdD91249DFdd450E81E1c56Ab60E1A62651701","0xFD0DFC837Fe7ED19B23df589b6F6Da5a775F99E0"], + log: !argv.ci, + }); + + const implementationAddress = (await ethers.getContract(implementationName)).address; + + console.log(`Successfully deployed the contract ${implementationName} at ${implementationAddress}`); + console.log(''); +}; + +func.tags = ['pointToken']; +export default func; diff --git a/deployments/gnosis/PointToken.json b/deployments/gnosis/PointToken.json new file mode 100644 index 0000000..24ff02a --- /dev/null +++ b/deployments/gnosis/PointToken.json @@ -0,0 +1,675 @@ +{ + "address": "0x1C6F6e2b226D99af2C34d875a03E055492914442", + "abi": [ + { + "inputs": [ + { + "internalType": "string", + "name": "name_", + "type": "string" + }, + { + "internalType": "string", + "name": "symbol_", + "type": "string" + }, + { + "internalType": "address", + "name": "_minter", + "type": "address" + }, + { + "internalType": "address", + "name": "_accessControlManager", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "NotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "NotGovernorOrGuardian", + "type": "error" + }, + { + "inputs": [], + "name": "NotTrusted", + "type": "error" + }, + { + "inputs": [], + "name": "ZeroAddress", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "inputs": [], + "name": "accessControlManager", + "outputs": [ + { + "internalType": "contract ICore", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + }, + { + "internalType": "address", + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "allowedTransfers", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "burn", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "decimals", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "subtractedValue", + "type": "uint256" + } + ], + "name": "decreaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "uint256", + "name": "addedValue", + "type": "uint256" + } + ], + "name": "increaseAllowance", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "mint", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "accounts", + "type": "address[]" + }, + { + "internalType": "uint256[]", + "name": "amounts", + "type": "uint256[]" + } + ], + "name": "mintBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "minters", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "name", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "symbol", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "toggleAllowedTransfers", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "minter", + "type": "address" + } + ], + "name": "toggleMinter", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "recipient", + "type": "address" + } + ], + "name": "toggleWhitelistedRecipient", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "name": "whitelistedRecipients", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "transactionHash": "0x58c5e7a41e299b578f1ff6d3d281461087416b9dca225df559fc7a5e34af395c", + "receipt": { + "to": null, + "from": "0xA9DdD91249DFdd450E81E1c56Ab60E1A62651701", + "contractAddress": "0x1C6F6e2b226D99af2C34d875a03E055492914442", + "transactionIndex": 0, + "gasUsed": "1462725", + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "blockHash": "0x2ee4ba893e1360d244c87663a623fb890323cc65a9efd17baeef2920f702809e", + "transactionHash": "0x58c5e7a41e299b578f1ff6d3d281461087416b9dca225df559fc7a5e34af395c", + "logs": [], + "blockNumber": 33988388, + "cumulativeGasUsed": "1462725", + "status": 1, + "byzantium": true + }, + "args": [ + "Angle Prots", + "agProts", + "0xA9DdD91249DFdd450E81E1c56Ab60E1A62651701", + "0xFD0DFC837Fe7ED19B23df589b6F6Da5a775F99E0" + ], + "numDeployments": 1, + "solcInputHash": "b99467b2e21e4446428ea69147e12594", + "metadata": "{\"compiler\":{\"version\":\"0.8.17+commit.8df45f5f\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"string\",\"name\":\"name_\",\"type\":\"string\"},{\"internalType\":\"string\",\"name\":\"symbol_\",\"type\":\"string\"},{\"internalType\":\"address\",\"name\":\"_minter\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"_accessControlManager\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"NotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotGovernorOrGuardian\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"NotTrusted\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"ZeroAddress\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"accessControlManager\",\"outputs\":[{\"internalType\":\"contract ICore\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"allowedTransfers\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"burn\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"subtractedValue\",\"type\":\"uint256\"}],\"name\":\"decreaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"addedValue\",\"type\":\"uint256\"}],\"name\":\"increaseAllowance\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"mint\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"accounts\",\"type\":\"address[]\"},{\"internalType\":\"uint256[]\",\"name\":\"amounts\",\"type\":\"uint256[]\"}],\"name\":\"mintBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"minters\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"toggleAllowedTransfers\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"minter\",\"type\":\"address\"}],\"name\":\"toggleMinter\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"recipient\",\"type\":\"address\"}],\"name\":\"toggleWhitelistedRecipient\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"amount\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"whitelistedRecipients\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"author\":\"Angle Labs, Inc.\",\"kind\":\"dev\",\"methods\":{\"allowance(address,address)\":{\"details\":\"See {IERC20-allowance}.\"},\"approve(address,uint256)\":{\"details\":\"See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address.\"},\"balanceOf(address)\":{\"details\":\"See {IERC20-balanceOf}.\"},\"decimals()\":{\"details\":\"Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}.\"},\"decreaseAllowance(address,uint256)\":{\"details\":\"Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`.\"},\"increaseAllowance(address,uint256)\":{\"details\":\"Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address.\"},\"name()\":{\"details\":\"Returns the name of the token.\"},\"symbol()\":{\"details\":\"Returns the symbol of the token, usually a shorter version of the name.\"},\"totalSupply()\":{\"details\":\"See {IERC20-totalSupply}.\"},\"transfer(address,uint256)\":{\"details\":\"See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`.\"},\"transferFrom(address,address,uint256)\":{\"details\":\"See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`.\"}},\"title\":\"PointToken\",\"version\":1},\"userdoc\":{\"kind\":\"user\",\"methods\":{},\"notice\":\"Reference contract for points systems within Merkl\",\"version\":1}},\"settings\":{\"compilationTarget\":{\"contracts/tokenWrappers/PointToken.sol\":\"PointToken\"},\"evmVersion\":\"london\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\",\"useLiteralContent\":true},\"optimizer\":{\"enabled\":true,\"runs\":100000},\"remappings\":[]},\"sources\":{\"@openzeppelin/contracts/token/ERC20/ERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\nimport \\\"./IERC20.sol\\\";\\nimport \\\"./extensions/IERC20Metadata.sol\\\";\\nimport \\\"../../utils/Context.sol\\\";\\n\\n/**\\n * @dev Implementation of the {IERC20} interface.\\n *\\n * This implementation is agnostic to the way tokens are created. This means\\n * that a supply mechanism has to be added in a derived contract using {_mint}.\\n * For a generic mechanism see {ERC20PresetMinterPauser}.\\n *\\n * TIP: For a detailed writeup see our guide\\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\\n * to implement supply mechanisms].\\n *\\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\\n * instead returning `false` on failure. This behavior is nonetheless\\n * conventional and does not conflict with the expectations of ERC20\\n * applications.\\n *\\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\\n * This allows applications to reconstruct the allowance for all accounts just\\n * by listening to said events. Other implementations of the EIP may not emit\\n * these events, as it isn't required by the specification.\\n *\\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\\n * functions have been added to mitigate the well-known issues around setting\\n * allowances. See {IERC20-approve}.\\n */\\ncontract ERC20 is Context, IERC20, IERC20Metadata {\\n mapping(address => uint256) private _balances;\\n\\n mapping(address => mapping(address => uint256)) private _allowances;\\n\\n uint256 private _totalSupply;\\n\\n string private _name;\\n string private _symbol;\\n\\n /**\\n * @dev Sets the values for {name} and {symbol}.\\n *\\n * The default value of {decimals} is 18. To select a different value for\\n * {decimals} you should overload it.\\n *\\n * All two of these values are immutable: they can only be set once during\\n * construction.\\n */\\n constructor(string memory name_, string memory symbol_) {\\n _name = name_;\\n _symbol = symbol_;\\n }\\n\\n /**\\n * @dev Returns the name of the token.\\n */\\n function name() public view virtual override returns (string memory) {\\n return _name;\\n }\\n\\n /**\\n * @dev Returns the symbol of the token, usually a shorter version of the\\n * name.\\n */\\n function symbol() public view virtual override returns (string memory) {\\n return _symbol;\\n }\\n\\n /**\\n * @dev Returns the number of decimals used to get its user representation.\\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\\n *\\n * Tokens usually opt for a value of 18, imitating the relationship between\\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\\n * overridden;\\n *\\n * NOTE: This information is only used for _display_ purposes: it in\\n * no way affects any of the arithmetic of the contract, including\\n * {IERC20-balanceOf} and {IERC20-transfer}.\\n */\\n function decimals() public view virtual override returns (uint8) {\\n return 18;\\n }\\n\\n /**\\n * @dev See {IERC20-totalSupply}.\\n */\\n function totalSupply() public view virtual override returns (uint256) {\\n return _totalSupply;\\n }\\n\\n /**\\n * @dev See {IERC20-balanceOf}.\\n */\\n function balanceOf(address account) public view virtual override returns (uint256) {\\n return _balances[account];\\n }\\n\\n /**\\n * @dev See {IERC20-transfer}.\\n *\\n * Requirements:\\n *\\n * - `to` cannot be the zero address.\\n * - the caller must have a balance of at least `amount`.\\n */\\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _transfer(owner, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-allowance}.\\n */\\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\\n return _allowances[owner][spender];\\n }\\n\\n /**\\n * @dev See {IERC20-approve}.\\n *\\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\\n * `transferFrom`. This is semantically equivalent to an infinite approval.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, amount);\\n return true;\\n }\\n\\n /**\\n * @dev See {IERC20-transferFrom}.\\n *\\n * Emits an {Approval} event indicating the updated allowance. This is not\\n * required by the EIP. See the note at the beginning of {ERC20}.\\n *\\n * NOTE: Does not update the allowance if the current allowance\\n * is the maximum `uint256`.\\n *\\n * Requirements:\\n *\\n * - `from` and `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n * - the caller must have allowance for ``from``'s tokens of at least\\n * `amount`.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) public virtual override returns (bool) {\\n address spender = _msgSender();\\n _spendAllowance(from, spender, amount);\\n _transfer(from, to, amount);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically increases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n */\\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n _approve(owner, spender, allowance(owner, spender) + addedValue);\\n return true;\\n }\\n\\n /**\\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\\n *\\n * This is an alternative to {approve} that can be used as a mitigation for\\n * problems described in {IERC20-approve}.\\n *\\n * Emits an {Approval} event indicating the updated allowance.\\n *\\n * Requirements:\\n *\\n * - `spender` cannot be the zero address.\\n * - `spender` must have allowance for the caller of at least\\n * `subtractedValue`.\\n */\\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\\n address owner = _msgSender();\\n uint256 currentAllowance = allowance(owner, spender);\\n require(currentAllowance >= subtractedValue, \\\"ERC20: decreased allowance below zero\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - subtractedValue);\\n }\\n\\n return true;\\n }\\n\\n /**\\n * @dev Moves `amount` of tokens from `from` to `to`.\\n *\\n * This internal function is equivalent to {transfer}, and can be used to\\n * e.g. implement automatic token fees, slashing mechanisms, etc.\\n *\\n * Emits a {Transfer} event.\\n *\\n * Requirements:\\n *\\n * - `from` cannot be the zero address.\\n * - `to` cannot be the zero address.\\n * - `from` must have a balance of at least `amount`.\\n */\\n function _transfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {\\n require(from != address(0), \\\"ERC20: transfer from the zero address\\\");\\n require(to != address(0), \\\"ERC20: transfer to the zero address\\\");\\n\\n _beforeTokenTransfer(from, to, amount);\\n\\n uint256 fromBalance = _balances[from];\\n require(fromBalance >= amount, \\\"ERC20: transfer amount exceeds balance\\\");\\n unchecked {\\n _balances[from] = fromBalance - amount;\\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\\n // decrementing then incrementing.\\n _balances[to] += amount;\\n }\\n\\n emit Transfer(from, to, amount);\\n\\n _afterTokenTransfer(from, to, amount);\\n }\\n\\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\\n * the total supply.\\n *\\n * Emits a {Transfer} event with `from` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n */\\n function _mint(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: mint to the zero address\\\");\\n\\n _beforeTokenTransfer(address(0), account, amount);\\n\\n _totalSupply += amount;\\n unchecked {\\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\\n _balances[account] += amount;\\n }\\n emit Transfer(address(0), account, amount);\\n\\n _afterTokenTransfer(address(0), account, amount);\\n }\\n\\n /**\\n * @dev Destroys `amount` tokens from `account`, reducing the\\n * total supply.\\n *\\n * Emits a {Transfer} event with `to` set to the zero address.\\n *\\n * Requirements:\\n *\\n * - `account` cannot be the zero address.\\n * - `account` must have at least `amount` tokens.\\n */\\n function _burn(address account, uint256 amount) internal virtual {\\n require(account != address(0), \\\"ERC20: burn from the zero address\\\");\\n\\n _beforeTokenTransfer(account, address(0), amount);\\n\\n uint256 accountBalance = _balances[account];\\n require(accountBalance >= amount, \\\"ERC20: burn amount exceeds balance\\\");\\n unchecked {\\n _balances[account] = accountBalance - amount;\\n // Overflow not possible: amount <= accountBalance <= totalSupply.\\n _totalSupply -= amount;\\n }\\n\\n emit Transfer(account, address(0), amount);\\n\\n _afterTokenTransfer(account, address(0), amount);\\n }\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\\n *\\n * This internal function is equivalent to `approve`, and can be used to\\n * e.g. set automatic allowances for certain subsystems, etc.\\n *\\n * Emits an {Approval} event.\\n *\\n * Requirements:\\n *\\n * - `owner` cannot be the zero address.\\n * - `spender` cannot be the zero address.\\n */\\n function _approve(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n require(owner != address(0), \\\"ERC20: approve from the zero address\\\");\\n require(spender != address(0), \\\"ERC20: approve to the zero address\\\");\\n\\n _allowances[owner][spender] = amount;\\n emit Approval(owner, spender, amount);\\n }\\n\\n /**\\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\\n *\\n * Does not update the allowance amount in case of infinite allowance.\\n * Revert if not enough allowance is available.\\n *\\n * Might emit an {Approval} event.\\n */\\n function _spendAllowance(\\n address owner,\\n address spender,\\n uint256 amount\\n ) internal virtual {\\n uint256 currentAllowance = allowance(owner, spender);\\n if (currentAllowance != type(uint256).max) {\\n require(currentAllowance >= amount, \\\"ERC20: insufficient allowance\\\");\\n unchecked {\\n _approve(owner, spender, currentAllowance - amount);\\n }\\n }\\n }\\n\\n /**\\n * @dev Hook that is called before any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * will be transferred to `to`.\\n * - when `from` is zero, `amount` tokens will be minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _beforeTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n\\n /**\\n * @dev Hook that is called after any transfer of tokens. This includes\\n * minting and burning.\\n *\\n * Calling conditions:\\n *\\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\\n * has been transferred to `to`.\\n * - when `from` is zero, `amount` tokens have been minted for `to`.\\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\\n * - `from` and `to` are never both zero.\\n *\\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\\n */\\n function _afterTokenTransfer(\\n address from,\\n address to,\\n uint256 amount\\n ) internal virtual {}\\n}\\n\",\"keccak256\":\"0x4ffc0547c02ad22925310c585c0f166f8759e2648a09e9b489100c42f15dd98d\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/IERC20.sol\":{\"content\":\"// SPDX-License-Identifier: MIT\\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\\n\\npragma solidity ^0.8.0;\\n\\n/**\\n * @dev Interface of the ERC20 standard as defined in the EIP.\\n */\\ninterface IERC20 {\\n /**\\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\\n * another (`to`).\\n *\\n * Note that `value` may be zero.\\n */\\n event Transfer(address indexed from, address indexed to, uint256 value);\\n\\n /**\\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\\n * a call to {approve}. `value` is the new allowance.\\n */\\n event Approval(address indexed owner, address indexed spender, uint256 value);\\n\\n /**\\n * @dev Returns the amount of tokens in existence.\\n */\\n function totalSupply() external view returns (uint256);\\n\\n /**\\n * @dev Returns the amount of tokens owned by `account`.\\n */\\n function balanceOf(address account) external view returns (uint256);\\n\\n /**\\n * @dev Moves `amount` tokens from the caller's account to `to`.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transfer(address to, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Returns the remaining number of tokens that `spender` will be\\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\\n * zero by default.\\n *\\n * This value changes when {approve} or {transferFrom} are called.\\n */\\n function allowance(address owner, address spender) external view returns (uint256);\\n\\n /**\\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\\n * that someone may use both the old and the new allowance by unfortunate\\n * transaction ordering. One possible solution to mitigate this race\\n * condition is to first reduce the spender's allowance to 0 and set the\\n * desired value afterwards:\\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\\n *\\n * Emits an {Approval} event.\\n */\\n function approve(address spender, uint256 amount) external returns (bool);\\n\\n /**\\n * @dev Moves `amount` tokens from `from` to `to` using the\\n * allowance mechanism. `amount` is then deducted from the caller's\\n * allowance.\\n *\\n * Returns a boolean value indicating whether the operation succeeded.\\n *\\n * Emits a {Transfer} event.\\n */\\n function transferFrom(\\n address from,\\n address to,\\n uint256 amount\\n ) external returns (bool);\\n}\\n\",\"keccak256\":\"0x9750c6b834f7b43000631af5cc30001c5f547b3ceb3635488f140f60e897ea6b\",\"license\":\"MIT\"},\"@openzeppelin/contracts/token/ERC20/extensions/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\",\"keccak256\":\"0x8de418a5503946cabe331f35fe242d3201a73f67f77aaeb7110acb1f30423aca\",\"license\":\"MIT\"},\"@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\",\"keccak256\":\"0xe2e337e6dde9ef6b680e07338c493ebea1b5fd09b43424112868e9cc1706bca7\",\"license\":\"MIT\"},\"contracts/interfaces/ICore.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.17;\\n\\n/// @title ICore\\n/// @author Angle Labs, Inc.\\n/// @notice Interface for the `Core` contracts of smart contract modules used in Angle Labs contracts\\ninterface ICore {\\n /// @notice Checks whether an address is governor\\n /// @param admin Address to check\\n /// @return Whether the address has the `GOVERNOR_ROLE` or not\\n function isGovernor(address admin) external view returns (bool);\\n\\n /// @notice Checks whether an address is a governor or a guardian of a module\\n /// @param admin Address to check\\n /// @return Whether the address has the `GUARDIAN_ROLE` or not\\n /// @dev Governance should make sure when adding a governor to also give this governor the guardian\\n /// role by calling the `addGovernor` function\\n function isGovernorOrGuardian(address admin) external view returns (bool);\\n}\\n\",\"keccak256\":\"0x11e92b745193d16934aaeb873c0388041dce2ef3e359a9c3315b668b05903100\",\"license\":\"GPL-3.0\"},\"contracts/tokenWrappers/PointToken.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.7;\\n\\nimport \\\"@openzeppelin/contracts/token/ERC20/ERC20.sol\\\";\\nimport { ICore } from \\\"../interfaces/ICore.sol\\\";\\nimport \\\"../utils/Errors.sol\\\";\\n\\n/// @title PointToken\\n/// @author Angle Labs, Inc.\\n/// @notice Reference contract for points systems within Merkl\\ncontract PointToken is ERC20 {\\n mapping(address => bool) public minters;\\n mapping(address => bool) public whitelistedRecipients;\\n ICore public accessControlManager;\\n uint8 public allowedTransfers;\\n\\n constructor(\\n string memory name_,\\n string memory symbol_,\\n address _minter,\\n address _accessControlManager\\n ) ERC20(name_, symbol_) {\\n if (_accessControlManager == address(0) || _minter == address(0)) revert ZeroAddress();\\n accessControlManager = ICore(_accessControlManager);\\n minters[_minter] = true;\\n }\\n\\n modifier onlyGovernorOrGuardian() {\\n if (!accessControlManager.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\\n _;\\n }\\n\\n modifier onlyMinter() {\\n if (!minters[msg.sender]) revert NotTrusted();\\n _;\\n }\\n\\n function mint(address account, uint256 amount) external onlyMinter {\\n _mint(account, amount);\\n }\\n\\n function burn(address account, uint256 amount) external onlyMinter {\\n _burn(account, amount);\\n }\\n\\n function mintBatch(address[] memory accounts, uint256[] memory amounts) external onlyMinter {\\n uint256 length = accounts.length;\\n for (uint256 i = 0; i < length; ++i) {\\n _mint(accounts[i], amounts[i]);\\n }\\n }\\n\\n function toggleMinter(address minter) external onlyGovernorOrGuardian {\\n minters[minter] = !minters[minter];\\n }\\n\\n function toggleAllowedTransfers() external onlyGovernorOrGuardian {\\n allowedTransfers = 1 - allowedTransfers;\\n }\\n\\n function toggleWhitelistedRecipient(address recipient) external onlyGovernorOrGuardian {\\n whitelistedRecipients[recipient] = !whitelistedRecipients[recipient];\\n }\\n\\n function _beforeTokenTransfer(address from, address to, uint256) internal view override {\\n if (\\n allowedTransfers == 0 &&\\n from != address(0) &&\\n to != address(0) &&\\n !whitelistedRecipients[from] &&\\n !whitelistedRecipients[to]\\n ) revert NotAllowed();\\n }\\n}\\n\",\"keccak256\":\"0xebdae093105cad08ac8b60220c547911e87ad35102aaddade5cd403f7412c17c\",\"license\":\"GPL-3.0\"},\"contracts/utils/Errors.sol\":{\"content\":\"// SPDX-License-Identifier: GPL-3.0\\n\\npragma solidity ^0.8.17;\\n\\nerror CampaignDoesNotExist();\\nerror CampaignAlreadyExists();\\nerror CampaignDurationBelowHour();\\nerror CampaignRewardTokenNotWhitelisted();\\nerror CampaignRewardTooLow();\\nerror CampaignSouldStartInFuture();\\nerror InvalidDispute();\\nerror InvalidLengths();\\nerror InvalidParam();\\nerror InvalidParams();\\nerror InvalidProof();\\nerror InvalidUninitializedRoot();\\nerror InvalidReward();\\nerror InvalidSignature();\\nerror NoDispute();\\nerror NotAllowed();\\nerror NotGovernor();\\nerror NotGovernorOrGuardian();\\nerror NotSigned();\\nerror NotTrusted();\\nerror NotWhitelisted();\\nerror UnresolvedDispute();\\nerror ZeroAddress();\\n\",\"keccak256\":\"0x9ec88f6c44321a26d21c7d67010d9969fffe585b80f2c5e549be4461289aaebb\",\"license\":\"GPL-3.0\"}},\"version\":1}", + "bytecode": "0x60806040523480156200001157600080fd5b5060405162001b7238038062001b728339810160408190526200003491620001b4565b83836003620000448382620002d2565b506004620000538282620002d2565b5050506001600160a01b03811615806200007457506001600160a01b038216155b15620000935760405163d92e233d60e01b815260040160405180910390fd5b600780546001600160a01b0319166001600160a01b03928316179055166000908152600560205260409020805460ff19166001179055506200039e9050565b634e487b7160e01b600052604160045260246000fd5b600082601f830112620000fa57600080fd5b81516001600160401b0380821115620001175762000117620000d2565b604051601f8301601f19908116603f01168101908282118183101715620001425762000142620000d2565b816040528381526020925086838588010111156200015f57600080fd5b600091505b8382101562000183578582018301518183018401529082019062000164565b600093810190920192909252949350505050565b80516001600160a01b0381168114620001af57600080fd5b919050565b60008060008060808587031215620001cb57600080fd5b84516001600160401b0380821115620001e357600080fd5b620001f188838901620000e8565b955060208701519150808211156200020857600080fd5b506200021787828801620000e8565b935050620002286040860162000197565b9150620002386060860162000197565b905092959194509250565b600181811c908216806200025857607f821691505b6020821081036200027957634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115620002cd57600081815260208120601f850160051c81016020861015620002a85750805b601f850160051c820191505b81811015620002c957828155600101620002b4565b5050505b505050565b81516001600160401b03811115620002ee57620002ee620000d2565b6200030681620002ff845462000243565b846200027f565b602080601f8311600181146200033e5760008415620003255750858301515b600019600386901b1c1916600185901b178555620002c9565b600085815260208120601f198616915b828110156200036f578886015182559484019460019091019084016200034e565b50858210156200038e5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b6117c480620003ae6000396000f3fe608060405234801561001057600080fd5b50600436106101775760003560e01c80637c88e3d9116100d8578063b3b964821161008c578063dd62ed3e11610066578063dd62ed3e14610351578063e3bf2d9514610397578063f46eccc4146103aa57600080fd5b8063b3b96482146102df578063b4a0bdf314610304578063dc98ce801461034957600080fd5b80639dc29fac116100bd5780639dc29fac146102a6578063a457c2d7146102b9578063a9059cbb146102cc57600080fd5b80637c88e3d91461028b57806395d89b411461029e57600080fd5b8063313ce5671161012f57806340c10f191161011457806340c10f191461022d57806362f6c9d51461024257806370a082311461025557600080fd5b8063313ce56714610205578063395093511461021a57600080fd5b806313c5d2521161016057806313c5d252146101bd57806318160ddd146101e057806323b872dd146101f257600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103cd565b604051610191919061133a565b60405180910390f35b6101ad6101a83660046113cf565b61045f565b6040519015158152602001610191565b6101ad6101cb3660046113f9565b60066020526000908152604090205460ff1681565b6002545b604051908152602001610191565b6101ad61020036600461141b565b610479565b60125b60405160ff9091168152602001610191565b6101ad6102283660046113cf565b61049d565b61024061023b3660046113cf565b6104e9565b005b6102406102503660046113f9565b610540565b6101e46102633660046113f9565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b610240610299366004611564565b61065c565b610184610704565b6102406102b43660046113cf565b610713565b6101ad6102c73660046113cf565b610766565b6101ad6102da3660046113cf565b61083c565b6007546102089074010000000000000000000000000000000000000000900460ff1681565b6007546103249073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b61024061084a565b6101e461035f366004611624565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6102406103a53660046113f9565b610957565b6101ad6103b83660046113f9565b60056020526000908152604090205460ff1681565b6060600380546103dc90611657565b80601f016020809104026020016040519081016040528092919081815260200182805461040890611657565b80156104555780601f1061042a57610100808354040283529160200191610455565b820191906000526020600020905b81548152906001019060200180831161043857829003601f168201915b5050505050905090565b60003361046d818585610a73565b60019150505b92915050565b600033610487858285610c27565b610492858585610cf8565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061046d90829086906104e49087906116d9565b610a73565b3360009081526005602052604090205460ff16610532576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61053c8282610f72565b5050565b6007546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156105ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d291906116ec565b610608576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b3360009081526005602052604090205460ff166106a5576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160005b818110156106fe576106ee8482815181106106c7576106c761170e565b60200260200101518483815181106106e1576106e161170e565b6020026020010151610f72565b6106f78161173d565b90506106aa565b50505050565b6060600480546103dc90611657565b3360009081526005602052604090205460ff1661075c576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61053c8282611071565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104928286868403610a73565b60003361046d818585610cf8565b6007546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156108b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dc91906116ec565b610912576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075461093b9074010000000000000000000000000000000000000000900460ff166001611775565b600760146101000a81548160ff021916908360ff160217905550565b6007546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156109c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e991906116ec565b610a1f576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b73ffffffffffffffffffffffffffffffffffffffff8316610b15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff8216610bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106fe5781811015610ceb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610826565b6106fe8484848403610a73565b73ffffffffffffffffffffffffffffffffffffffff8316610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff8216610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610826565b610e4983838361123e565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36106fe565b73ffffffffffffffffffffffffffffffffffffffff8216610fef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610826565b610ffb6000838361123e565b806002600082825461100d91906116d9565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216611114576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610826565b6111208260008361123e565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156111d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610c1a565b505050565b60075474010000000000000000000000000000000000000000900460ff1615801561127e575073ffffffffffffffffffffffffffffffffffffffff831615155b801561129f575073ffffffffffffffffffffffffffffffffffffffff821615155b80156112d1575073ffffffffffffffffffffffffffffffffffffffff831660009081526006602052604090205460ff16155b8015611303575073ffffffffffffffffffffffffffffffffffffffff821660009081526006602052604090205460ff16155b15611239576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208083528351808285015260005b818110156113675785810183015185820160400152820161134b565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113ca57600080fd5b919050565b600080604083850312156113e257600080fd5b6113eb836113a6565b946020939093013593505050565b60006020828403121561140b57600080fd5b611414826113a6565b9392505050565b60008060006060848603121561143057600080fd5b611439846113a6565b9250611447602085016113a6565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156114cd576114cd611457565b604052919050565b600067ffffffffffffffff8211156114ef576114ef611457565b5060051b60200190565b600082601f83011261150a57600080fd5b8135602061151f61151a836114d5565b611486565b82815260059290921b8401810191818101908684111561153e57600080fd5b8286015b848110156115595780358352918301918301611542565b509695505050505050565b6000806040838503121561157757600080fd5b823567ffffffffffffffff8082111561158f57600080fd5b818501915085601f8301126115a357600080fd5b813560206115b361151a836114d5565b82815260059290921b840181019181810190898411156115d257600080fd5b948201945b838610156115f7576115e8866113a6565b825294820194908201906115d7565b9650508601359250508082111561160d57600080fd5b5061161a858286016114f9565b9150509250929050565b6000806040838503121561163757600080fd5b611640836113a6565b915061164e602084016113a6565b90509250929050565b600181811c9082168061166b57607f821691505b6020821081036116a4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610473576104736116aa565b6000602082840312156116fe57600080fd5b8151801515811461141457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361176e5761176e6116aa565b5060010190565b60ff8281168282160390811115610473576104736116aa56fea264697066735822122019473afd61936f851acfc55759a5540e40a6621cfec37b4e032fa728f94e826364736f6c63430008110033", + "deployedBytecode": "0x608060405234801561001057600080fd5b50600436106101775760003560e01c80637c88e3d9116100d8578063b3b964821161008c578063dd62ed3e11610066578063dd62ed3e14610351578063e3bf2d9514610397578063f46eccc4146103aa57600080fd5b8063b3b96482146102df578063b4a0bdf314610304578063dc98ce801461034957600080fd5b80639dc29fac116100bd5780639dc29fac146102a6578063a457c2d7146102b9578063a9059cbb146102cc57600080fd5b80637c88e3d91461028b57806395d89b411461029e57600080fd5b8063313ce5671161012f57806340c10f191161011457806340c10f191461022d57806362f6c9d51461024257806370a082311461025557600080fd5b8063313ce56714610205578063395093511461021a57600080fd5b806313c5d2521161016057806313c5d252146101bd57806318160ddd146101e057806323b872dd146101f257600080fd5b806306fdde031461017c578063095ea7b31461019a575b600080fd5b6101846103cd565b604051610191919061133a565b60405180910390f35b6101ad6101a83660046113cf565b61045f565b6040519015158152602001610191565b6101ad6101cb3660046113f9565b60066020526000908152604090205460ff1681565b6002545b604051908152602001610191565b6101ad61020036600461141b565b610479565b60125b60405160ff9091168152602001610191565b6101ad6102283660046113cf565b61049d565b61024061023b3660046113cf565b6104e9565b005b6102406102503660046113f9565b610540565b6101e46102633660046113f9565b73ffffffffffffffffffffffffffffffffffffffff1660009081526020819052604090205490565b610240610299366004611564565b61065c565b610184610704565b6102406102b43660046113cf565b610713565b6101ad6102c73660046113cf565b610766565b6101ad6102da3660046113cf565b61083c565b6007546102089074010000000000000000000000000000000000000000900460ff1681565b6007546103249073ffffffffffffffffffffffffffffffffffffffff1681565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610191565b61024061084a565b6101e461035f366004611624565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260016020908152604080832093909416825291909152205490565b6102406103a53660046113f9565b610957565b6101ad6103b83660046113f9565b60056020526000908152604090205460ff1681565b6060600380546103dc90611657565b80601f016020809104026020016040519081016040528092919081815260200182805461040890611657565b80156104555780601f1061042a57610100808354040283529160200191610455565b820191906000526020600020905b81548152906001019060200180831161043857829003601f168201915b5050505050905090565b60003361046d818585610a73565b60019150505b92915050565b600033610487858285610c27565b610492858585610cf8565b506001949350505050565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716845290915281205490919061046d90829086906104e49087906116d9565b610a73565b3360009081526005602052604090205460ff16610532576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61053c8282610f72565b5050565b6007546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156105ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105d291906116ec565b610608576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b3360009081526005602052604090205460ff166106a5576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b815160005b818110156106fe576106ee8482815181106106c7576106c761170e565b60200260200101518483815181106106e1576106e161170e565b6020026020010151610f72565b6106f78161173d565b90506106aa565b50505050565b6060600480546103dc90611657565b3360009081526005602052604090205460ff1661075c576040517fc22a648e00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61053c8282611071565b33600081815260016020908152604080832073ffffffffffffffffffffffffffffffffffffffff871684529091528120549091908381101561082f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f7760448201527f207a65726f00000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6104928286868403610a73565b60003361046d818585610cf8565b6007546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156108b8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108dc91906116ec565b610912576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b60075461093b9074010000000000000000000000000000000000000000900460ff166001611775565b600760146101000a81548160ff021916908360ff160217905550565b6007546040517f521d4de900000000000000000000000000000000000000000000000000000000815233600482015273ffffffffffffffffffffffffffffffffffffffff9091169063521d4de990602401602060405180830381865afa1580156109c5573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109e991906116ec565b610a1f576040517f99e120bc00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff16600090815260066020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00811660ff90911615179055565b73ffffffffffffffffffffffffffffffffffffffff8316610b15576040517f08c379a0000000000000000000000000000000000000000000000000000000008152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f2061646460448201527f72657373000000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff8216610bb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f20616464726560448201527f73730000000000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526001602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92591015b60405180910390a3505050565b73ffffffffffffffffffffffffffffffffffffffff8381166000908152600160209081526040808320938616835292905220547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff81146106fe5781811015610ceb576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f45524332303a20696e73756666696369656e7420616c6c6f77616e63650000006044820152606401610826565b6106fe8484848403610a73565b73ffffffffffffffffffffffffffffffffffffffff8316610d9b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f20616460448201527f64726573730000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff8216610e3e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201527f65737300000000000000000000000000000000000000000000000000000000006064820152608401610826565b610e4983838361123e565b73ffffffffffffffffffffffffffffffffffffffff831660009081526020819052604090205481811015610eff576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e742065786365656473206260448201527f616c616e636500000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff848116600081815260208181526040808320878703905593871680835291849020805487019055925185815290927fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a36106fe565b73ffffffffffffffffffffffffffffffffffffffff8216610fef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f2061646472657373006044820152606401610826565b610ffb6000838361123e565b806002600082825461100d91906116d9565b909155505073ffffffffffffffffffffffffffffffffffffffff8216600081815260208181526040808320805486019055518481527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a35050565b73ffffffffffffffffffffffffffffffffffffffff8216611114576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f2061646472657360448201527f73000000000000000000000000000000000000000000000000000000000000006064820152608401610826565b6111208260008361123e565b73ffffffffffffffffffffffffffffffffffffffff8216600090815260208190526040902054818110156111d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e60448201527f63650000000000000000000000000000000000000000000000000000000000006064820152608401610826565b73ffffffffffffffffffffffffffffffffffffffff83166000818152602081815260408083208686039055600280548790039055518581529192917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9101610c1a565b505050565b60075474010000000000000000000000000000000000000000900460ff1615801561127e575073ffffffffffffffffffffffffffffffffffffffff831615155b801561129f575073ffffffffffffffffffffffffffffffffffffffff821615155b80156112d1575073ffffffffffffffffffffffffffffffffffffffff831660009081526006602052604090205460ff16155b8015611303575073ffffffffffffffffffffffffffffffffffffffff821660009081526006602052604090205460ff16155b15611239576040517f3d693ada00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060208083528351808285015260005b818110156113675785810183015185820160400152820161134b565b5060006040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b803573ffffffffffffffffffffffffffffffffffffffff811681146113ca57600080fd5b919050565b600080604083850312156113e257600080fd5b6113eb836113a6565b946020939093013593505050565b60006020828403121561140b57600080fd5b611414826113a6565b9392505050565b60008060006060848603121561143057600080fd5b611439846113a6565b9250611447602085016113a6565b9150604084013590509250925092565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff811182821017156114cd576114cd611457565b604052919050565b600067ffffffffffffffff8211156114ef576114ef611457565b5060051b60200190565b600082601f83011261150a57600080fd5b8135602061151f61151a836114d5565b611486565b82815260059290921b8401810191818101908684111561153e57600080fd5b8286015b848110156115595780358352918301918301611542565b509695505050505050565b6000806040838503121561157757600080fd5b823567ffffffffffffffff8082111561158f57600080fd5b818501915085601f8301126115a357600080fd5b813560206115b361151a836114d5565b82815260059290921b840181019181810190898411156115d257600080fd5b948201945b838610156115f7576115e8866113a6565b825294820194908201906115d7565b9650508601359250508082111561160d57600080fd5b5061161a858286016114f9565b9150509250929050565b6000806040838503121561163757600080fd5b611640836113a6565b915061164e602084016113a6565b90509250929050565b600181811c9082168061166b57607f821691505b6020821081036116a4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80820180821115610473576104736116aa565b6000602082840312156116fe57600080fd5b8151801515811461141457600080fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361176e5761176e6116aa565b5060010190565b60ff8281168282160390811115610473576104736116aa56fea264697066735822122019473afd61936f851acfc55759a5540e40a6621cfec37b4e032fa728f94e826364736f6c63430008110033", + "devdoc": { + "author": "Angle Labs, Inc.", + "kind": "dev", + "methods": { + "allowance(address,address)": { + "details": "See {IERC20-allowance}." + }, + "approve(address,uint256)": { + "details": "See {IERC20-approve}. NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on `transferFrom`. This is semantically equivalent to an infinite approval. Requirements: - `spender` cannot be the zero address." + }, + "balanceOf(address)": { + "details": "See {IERC20-balanceOf}." + }, + "decimals()": { + "details": "Returns the number of decimals used to get its user representation. For example, if `decimals` equals `2`, a balance of `505` tokens should be displayed to a user as `5.05` (`505 / 10 ** 2`). Tokens usually opt for a value of 18, imitating the relationship between Ether and Wei. This is the value {ERC20} uses, unless this function is overridden; NOTE: This information is only used for _display_ purposes: it in no way affects any of the arithmetic of the contract, including {IERC20-balanceOf} and {IERC20-transfer}." + }, + "decreaseAllowance(address,uint256)": { + "details": "Atomically decreases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address. - `spender` must have allowance for the caller of at least `subtractedValue`." + }, + "increaseAllowance(address,uint256)": { + "details": "Atomically increases the allowance granted to `spender` by the caller. This is an alternative to {approve} that can be used as a mitigation for problems described in {IERC20-approve}. Emits an {Approval} event indicating the updated allowance. Requirements: - `spender` cannot be the zero address." + }, + "name()": { + "details": "Returns the name of the token." + }, + "symbol()": { + "details": "Returns the symbol of the token, usually a shorter version of the name." + }, + "totalSupply()": { + "details": "See {IERC20-totalSupply}." + }, + "transfer(address,uint256)": { + "details": "See {IERC20-transfer}. Requirements: - `to` cannot be the zero address. - the caller must have a balance of at least `amount`." + }, + "transferFrom(address,address,uint256)": { + "details": "See {IERC20-transferFrom}. Emits an {Approval} event indicating the updated allowance. This is not required by the EIP. See the note at the beginning of {ERC20}. NOTE: Does not update the allowance if the current allowance is the maximum `uint256`. Requirements: - `from` and `to` cannot be the zero address. - `from` must have a balance of at least `amount`. - the caller must have allowance for ``from``'s tokens of at least `amount`." + } + }, + "title": "PointToken", + "version": 1 + }, + "userdoc": { + "kind": "user", + "methods": {}, + "notice": "Reference contract for points systems within Merkl", + "version": 1 + }, + "storageLayout": { + "storage": [ + { + "astId": 2010, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "_balances", + "offset": 0, + "slot": "0", + "type": "t_mapping(t_address,t_uint256)" + }, + { + "astId": 2016, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "_allowances", + "offset": 0, + "slot": "1", + "type": "t_mapping(t_address,t_mapping(t_address,t_uint256))" + }, + { + "astId": 2018, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "_totalSupply", + "offset": 0, + "slot": "2", + "type": "t_uint256" + }, + { + "astId": 2020, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "_name", + "offset": 0, + "slot": "3", + "type": "t_string_storage" + }, + { + "astId": 2022, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "_symbol", + "offset": 0, + "slot": "4", + "type": "t_string_storage" + }, + { + "astId": 11704, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "minters", + "offset": 0, + "slot": "5", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 11708, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "whitelistedRecipients", + "offset": 0, + "slot": "6", + "type": "t_mapping(t_address,t_bool)" + }, + { + "astId": 11711, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "accessControlManager", + "offset": 0, + "slot": "7", + "type": "t_contract(ICore)10172" + }, + { + "astId": 11713, + "contract": "contracts/tokenWrappers/PointToken.sol:PointToken", + "label": "allowedTransfers", + "offset": 20, + "slot": "7", + "type": "t_uint8" + } + ], + "types": { + "t_address": { + "encoding": "inplace", + "label": "address", + "numberOfBytes": "20" + }, + "t_bool": { + "encoding": "inplace", + "label": "bool", + "numberOfBytes": "1" + }, + "t_contract(ICore)10172": { + "encoding": "inplace", + "label": "contract ICore", + "numberOfBytes": "20" + }, + "t_mapping(t_address,t_bool)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => bool)", + "numberOfBytes": "32", + "value": "t_bool" + }, + "t_mapping(t_address,t_mapping(t_address,t_uint256))": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => mapping(address => uint256))", + "numberOfBytes": "32", + "value": "t_mapping(t_address,t_uint256)" + }, + "t_mapping(t_address,t_uint256)": { + "encoding": "mapping", + "key": "t_address", + "label": "mapping(address => uint256)", + "numberOfBytes": "32", + "value": "t_uint256" + }, + "t_string_storage": { + "encoding": "bytes", + "label": "string", + "numberOfBytes": "32" + }, + "t_uint256": { + "encoding": "inplace", + "label": "uint256", + "numberOfBytes": "32" + }, + "t_uint8": { + "encoding": "inplace", + "label": "uint8", + "numberOfBytes": "1" + } + } + } +} \ No newline at end of file diff --git a/deployments/gnosis/solcInputs/b99467b2e21e4446428ea69147e12594.json b/deployments/gnosis/solcInputs/b99467b2e21e4446428ea69147e12594.json new file mode 100644 index 0000000..45467a0 --- /dev/null +++ b/deployments/gnosis/solcInputs/b99467b2e21e4446428ea69147e12594.json @@ -0,0 +1,168 @@ +{ + "language": "Solidity", + "sources": { + "@openzeppelin/contracts-upgradeable/interfaces/draft-IERC1822Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (interfaces/draft-IERC1822.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev ERC1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified\n * proxy whose upgrades are fully controlled by the current implementation.\n */\ninterface IERC1822ProxiableUpgradeable {\n /**\n * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation\n * address.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy.\n */\n function proxiableUUID() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (proxy/beacon/IBeacon.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev This is the interface that {BeaconProxy} expects of its beacon.\n */\ninterface IBeaconUpgradeable {\n /**\n * @dev Must return an address that can be used as a delegate call target.\n *\n * {BeaconProxy} will check that this address is a contract.\n */\n function implementation() external view returns (address);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.5.0) (proxy/ERC1967/ERC1967Upgrade.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../beacon/IBeaconUpgradeable.sol\";\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../../utils/AddressUpgradeable.sol\";\nimport \"../../utils/StorageSlotUpgradeable.sol\";\nimport \"../utils/Initializable.sol\";\n\n/**\n * @dev This abstract contract provides getters and event emitting update functions for\n * https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.\n *\n * _Available since v4.1._\n *\n * @custom:oz-upgrades-unsafe-allow delegatecall\n */\nabstract contract ERC1967UpgradeUpgradeable is Initializable {\n function __ERC1967Upgrade_init() internal onlyInitializing {\n }\n\n function __ERC1967Upgrade_init_unchained() internal onlyInitializing {\n }\n // This is the keccak-256 hash of \"eip1967.proxy.rollback\" subtracted by 1\n bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;\n\n /**\n * @dev Storage slot with the address of the current implementation.\n * This is the keccak-256 hash of \"eip1967.proxy.implementation\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n\n /**\n * @dev Emitted when the implementation is upgraded.\n */\n event Upgraded(address indexed implementation);\n\n /**\n * @dev Returns the current implementation address.\n */\n function _getImplementation() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 implementation slot.\n */\n function _setImplementation(address newImplementation) private {\n require(AddressUpgradeable.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n }\n\n /**\n * @dev Perform implementation upgrade\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeTo(address newImplementation) internal {\n _setImplementation(newImplementation);\n emit Upgraded(newImplementation);\n }\n\n /**\n * @dev Perform implementation upgrade with additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCall(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n _upgradeTo(newImplementation);\n if (data.length > 0 || forceCall) {\n _functionDelegateCall(newImplementation, data);\n }\n }\n\n /**\n * @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.\n *\n * Emits an {Upgraded} event.\n */\n function _upgradeToAndCallUUPS(\n address newImplementation,\n bytes memory data,\n bool forceCall\n ) internal {\n // Upgrades from old implementations will perform a rollback test. This test requires the new\n // implementation to upgrade back to the old, non-ERC1822 compliant, implementation. Removing\n // this special case will break upgrade paths from old UUPS implementation to new ones.\n if (StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT).value) {\n _setImplementation(newImplementation);\n } else {\n try IERC1822ProxiableUpgradeable(newImplementation).proxiableUUID() returns (bytes32 slot) {\n require(slot == _IMPLEMENTATION_SLOT, \"ERC1967Upgrade: unsupported proxiableUUID\");\n } catch {\n revert(\"ERC1967Upgrade: new implementation is not UUPS\");\n }\n _upgradeToAndCall(newImplementation, data, forceCall);\n }\n }\n\n /**\n * @dev Storage slot with the admin of the contract.\n * This is the keccak-256 hash of \"eip1967.proxy.admin\" subtracted by 1, and is\n * validated in the constructor.\n */\n bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;\n\n /**\n * @dev Emitted when the admin account has changed.\n */\n event AdminChanged(address previousAdmin, address newAdmin);\n\n /**\n * @dev Returns the current admin.\n */\n function _getAdmin() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;\n }\n\n /**\n * @dev Stores a new address in the EIP1967 admin slot.\n */\n function _setAdmin(address newAdmin) private {\n require(newAdmin != address(0), \"ERC1967: new admin is the zero address\");\n StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;\n }\n\n /**\n * @dev Changes the admin of the proxy.\n *\n * Emits an {AdminChanged} event.\n */\n function _changeAdmin(address newAdmin) internal {\n emit AdminChanged(_getAdmin(), newAdmin);\n _setAdmin(newAdmin);\n }\n\n /**\n * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.\n * This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.\n */\n bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;\n\n /**\n * @dev Emitted when the beacon is upgraded.\n */\n event BeaconUpgraded(address indexed beacon);\n\n /**\n * @dev Returns the current beacon.\n */\n function _getBeacon() internal view returns (address) {\n return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;\n }\n\n /**\n * @dev Stores a new beacon in the EIP1967 beacon slot.\n */\n function _setBeacon(address newBeacon) private {\n require(AddressUpgradeable.isContract(newBeacon), \"ERC1967: new beacon is not a contract\");\n require(\n AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),\n \"ERC1967: beacon implementation is not a contract\"\n );\n StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;\n }\n\n /**\n * @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does\n * not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).\n *\n * Emits a {BeaconUpgraded} event.\n */\n function _upgradeBeaconToAndCall(\n address newBeacon,\n bytes memory data,\n bool forceCall\n ) internal {\n _setBeacon(newBeacon);\n emit BeaconUpgraded(newBeacon);\n if (data.length > 0 || forceCall) {\n _functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);\n }\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {\n require(AddressUpgradeable.isContract(target), \"Address: delegate call to non-contract\");\n\n // solhint-disable-next-line avoid-low-level-calls\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return AddressUpgradeable.verifyCallResult(success, returndata, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.1) (proxy/utils/Initializable.sol)\n\npragma solidity ^0.8.2;\n\nimport \"../../utils/AddressUpgradeable.sol\";\n\n/**\n * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed\n * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an\n * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer\n * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.\n *\n * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be\n * reused. This mechanism prevents re-execution of each \"step\" but allows the creation of new initialization steps in\n * case an upgrade adds a module that needs to be initialized.\n *\n * For example:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * contract MyToken is ERC20Upgradeable {\n * function initialize() initializer public {\n * __ERC20_init(\"MyToken\", \"MTK\");\n * }\n * }\n * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {\n * function initializeV2() reinitializer(2) public {\n * __ERC20Permit_init(\"MyToken\");\n * }\n * }\n * ```\n *\n * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as\n * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.\n *\n * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure\n * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.\n *\n * [CAUTION]\n * ====\n * Avoid leaving a contract uninitialized.\n *\n * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation\n * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke\n * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:\n *\n * [.hljs-theme-light.nopadding]\n * ```\n * /// @custom:oz-upgrades-unsafe-allow constructor\n * constructor() {\n * _disableInitializers();\n * }\n * ```\n * ====\n */\nabstract contract Initializable {\n /**\n * @dev Indicates that the contract has been initialized.\n * @custom:oz-retyped-from bool\n */\n uint8 private _initialized;\n\n /**\n * @dev Indicates that the contract is in the process of being initialized.\n */\n bool private _initializing;\n\n /**\n * @dev Triggered when the contract has been initialized or reinitialized.\n */\n event Initialized(uint8 version);\n\n /**\n * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,\n * `onlyInitializing` functions can be used to initialize parent contracts.\n *\n * Similar to `reinitializer(1)`, except that functions marked with `initializer` can be nested in the context of a\n * constructor.\n *\n * Emits an {Initialized} event.\n */\n modifier initializer() {\n bool isTopLevelCall = !_initializing;\n require(\n (isTopLevelCall && _initialized < 1) || (!AddressUpgradeable.isContract(address(this)) && _initialized == 1),\n \"Initializable: contract is already initialized\"\n );\n _initialized = 1;\n if (isTopLevelCall) {\n _initializing = true;\n }\n _;\n if (isTopLevelCall) {\n _initializing = false;\n emit Initialized(1);\n }\n }\n\n /**\n * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the\n * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be\n * used to initialize parent contracts.\n *\n * A reinitializer may be used after the original initialization step. This is essential to configure modules that\n * are added through upgrades and that require initialization.\n *\n * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`\n * cannot be nested. If one is invoked in the context of another, execution will revert.\n *\n * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in\n * a contract, executing them in the right order is up to the developer or operator.\n *\n * WARNING: setting the version to 255 will prevent any future reinitialization.\n *\n * Emits an {Initialized} event.\n */\n modifier reinitializer(uint8 version) {\n require(!_initializing && _initialized < version, \"Initializable: contract is already initialized\");\n _initialized = version;\n _initializing = true;\n _;\n _initializing = false;\n emit Initialized(version);\n }\n\n /**\n * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the\n * {initializer} and {reinitializer} modifiers, directly or indirectly.\n */\n modifier onlyInitializing() {\n require(_initializing, \"Initializable: contract is not initializing\");\n _;\n }\n\n /**\n * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.\n * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized\n * to any version. It is recommended to use this to lock implementation contracts that are designed to be called\n * through proxies.\n *\n * Emits an {Initialized} event the first time it is successfully executed.\n */\n function _disableInitializers() internal virtual {\n require(!_initializing, \"Initializable: contract is initializing\");\n if (_initialized < type(uint8).max) {\n _initialized = type(uint8).max;\n emit Initialized(type(uint8).max);\n }\n }\n\n /**\n * @dev Returns the highest version that has been initialized. See {reinitializer}.\n */\n function _getInitializedVersion() internal view returns (uint8) {\n return _initialized;\n }\n\n /**\n * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.\n */\n function _isInitializing() internal view returns (bool) {\n return _initializing;\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (proxy/utils/UUPSUpgradeable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../../interfaces/draft-IERC1822Upgradeable.sol\";\nimport \"../ERC1967/ERC1967UpgradeUpgradeable.sol\";\nimport \"./Initializable.sol\";\n\n/**\n * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an\n * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.\n *\n * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is\n * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing\n * `UUPSUpgradeable` with a custom implementation of upgrades.\n *\n * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.\n *\n * _Available since v4.1._\n */\nabstract contract UUPSUpgradeable is Initializable, IERC1822ProxiableUpgradeable, ERC1967UpgradeUpgradeable {\n function __UUPSUpgradeable_init() internal onlyInitializing {\n }\n\n function __UUPSUpgradeable_init_unchained() internal onlyInitializing {\n }\n /// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment\n address private immutable __self = address(this);\n\n /**\n * @dev Check that the execution is being performed through a delegatecall call and that the execution context is\n * a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case\n * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a\n * function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to\n * fail.\n */\n modifier onlyProxy() {\n require(address(this) != __self, \"Function must be called through delegatecall\");\n require(_getImplementation() == __self, \"Function must be called through active proxy\");\n _;\n }\n\n /**\n * @dev Check that the execution is not being performed through a delegate call. This allows a function to be\n * callable on the implementing contract but not through proxies.\n */\n modifier notDelegated() {\n require(address(this) == __self, \"UUPSUpgradeable: must not be called through delegatecall\");\n _;\n }\n\n /**\n * @dev Implementation of the ERC1822 {proxiableUUID} function. This returns the storage slot used by the\n * implementation. It is used to validate the implementation's compatibility when performing an upgrade.\n *\n * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks\n * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this\n * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.\n */\n function proxiableUUID() external view virtual override notDelegated returns (bytes32) {\n return _IMPLEMENTATION_SLOT;\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeTo(address newImplementation) external virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, new bytes(0), false);\n }\n\n /**\n * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call\n * encoded in `data`.\n *\n * Calls {_authorizeUpgrade}.\n *\n * Emits an {Upgraded} event.\n */\n function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {\n _authorizeUpgrade(newImplementation);\n _upgradeToAndCallUUPS(newImplementation, data, true);\n }\n\n /**\n * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by\n * {upgradeTo} and {upgradeToAndCall}.\n *\n * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.\n *\n * ```solidity\n * function _authorizeUpgrade(address) internal override onlyOwner {}\n * ```\n */\n function _authorizeUpgrade(address newImplementation) internal virtual;\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (security/ReentrancyGuard.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Contract module that helps prevent reentrant calls to a function.\n *\n * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier\n * available, which can be applied to functions to make sure there are no nested\n * (reentrant) calls to them.\n *\n * Note that because there is a single `nonReentrant` guard, functions marked as\n * `nonReentrant` may not call one another. This can be worked around by making\n * those functions `private`, and then adding `external` `nonReentrant` entry\n * points to them.\n *\n * TIP: If you would like to learn more about reentrancy and alternative ways\n * to protect against it, check out our blog post\n * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].\n */\nabstract contract ReentrancyGuardUpgradeable is Initializable {\n // Booleans are more expensive than uint256 or any type that takes up a full\n // word because each write operation emits an extra SLOAD to first read the\n // slot's contents, replace the bits taken up by the boolean, and then write\n // back. This is the compiler's defense against contract upgrades and\n // pointer aliasing, and it cannot be disabled.\n\n // The values being non-zero value makes deployment a bit more expensive,\n // but in exchange the refund on every call to nonReentrant will be lower in\n // amount. Since refunds are capped to a percentage of the total\n // transaction's gas, it is best to keep them low in cases like this one, to\n // increase the likelihood of the full refund coming into effect.\n uint256 private constant _NOT_ENTERED = 1;\n uint256 private constant _ENTERED = 2;\n\n uint256 private _status;\n\n function __ReentrancyGuard_init() internal onlyInitializing {\n __ReentrancyGuard_init_unchained();\n }\n\n function __ReentrancyGuard_init_unchained() internal onlyInitializing {\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev Prevents a contract from calling itself, directly or indirectly.\n * Calling a `nonReentrant` function from another `nonReentrant`\n * function is not supported. It is possible to prevent this from happening\n * by making the `nonReentrant` function external, and making it call a\n * `private` function that does the actual work.\n */\n modifier nonReentrant() {\n _nonReentrantBefore();\n _;\n _nonReentrantAfter();\n }\n\n function _nonReentrantBefore() private {\n // On the first call to nonReentrant, _status will be _NOT_ENTERED\n require(_status != _ENTERED, \"ReentrancyGuard: reentrant call\");\n\n // Any calls to nonReentrant after this point will fail\n _status = _ENTERED;\n }\n\n function _nonReentrantAfter() private {\n // By storing the original value once again, a refund is triggered (see\n // https://eips.ethereum.org/EIPS/eip-2200)\n _status = _NOT_ENTERED;\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[49] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20Upgradeable.sol\";\nimport \"./extensions/IERC20MetadataUpgradeable.sol\";\nimport \"../../utils/ContextUpgradeable.sol\";\nimport \"../../proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {\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 function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[45] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.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 \"../IERC20Upgradeable.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20MetadataUpgradeable is IERC20Upgradeable {\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-upgradeable/token/ERC20/IERC20Upgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20Upgradeable {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary AddressUpgradeable {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\nimport \"../proxy/utils/Initializable.sol\";\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 ContextUpgradeable is Initializable {\n function __Context_init() internal onlyInitializing {\n }\n\n function __Context_init_unchained() internal onlyInitializing {\n }\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 /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[50] private __gap;\n}\n" + }, + "@openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (utils/StorageSlot.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Library for reading and writing primitive types to specific storage slots.\n *\n * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.\n * This library helps with reading and writing to such slots without the need for inline assembly.\n *\n * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.\n *\n * Example usage to set ERC1967 implementation slot:\n * ```\n * contract ERC1967 {\n * bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;\n *\n * function _getImplementation() internal view returns (address) {\n * return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;\n * }\n *\n * function _setImplementation(address newImplementation) internal {\n * require(Address.isContract(newImplementation), \"ERC1967: new implementation is not a contract\");\n * StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;\n * }\n * }\n * ```\n *\n * _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._\n */\nlibrary StorageSlotUpgradeable {\n struct AddressSlot {\n address value;\n }\n\n struct BooleanSlot {\n bool value;\n }\n\n struct Bytes32Slot {\n bytes32 value;\n }\n\n struct Uint256Slot {\n uint256 value;\n }\n\n /**\n * @dev Returns an `AddressSlot` with member `value` located at `slot`.\n */\n function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `BooleanSlot` with member `value` located at `slot`.\n */\n function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.\n */\n function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n\n /**\n * @dev Returns an `Uint256Slot` with member `value` located at `slot`.\n */\n function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {\n /// @solidity memory-safe-assembly\n assembly {\n r.slot := slot\n }\n }\n}\n" + }, + "@openzeppelin/contracts/access/Ownable.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n address private _owner;\n\n event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n /**\n * @dev Initializes the contract setting the deployer as the initial owner.\n */\n constructor() {\n _transferOwnership(_msgSender());\n }\n\n /**\n * @dev Throws if called by any account other than the owner.\n */\n modifier onlyOwner() {\n _checkOwner();\n _;\n }\n\n /**\n * @dev Returns the address of the current owner.\n */\n function owner() public view virtual returns (address) {\n return _owner;\n }\n\n /**\n * @dev Throws if the sender is not the owner.\n */\n function _checkOwner() internal view virtual {\n require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n }\n\n /**\n * @dev Leaves the contract without owner. It will not be possible to call\n * `onlyOwner` functions anymore. Can only be called by the current owner.\n *\n * NOTE: Renouncing ownership will leave the contract without an owner,\n * thereby removing any functionality that is only available to the owner.\n */\n function renounceOwnership() public virtual onlyOwner {\n _transferOwnership(address(0));\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Can only be called by the current owner.\n */\n function transferOwnership(address newOwner) public virtual onlyOwner {\n require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n _transferOwnership(newOwner);\n }\n\n /**\n * @dev Transfers ownership of the contract to a new account (`newOwner`).\n * Internal function without access restriction.\n */\n function _transferOwnership(address newOwner) internal virtual {\n address oldOwner = _owner;\n _owner = newOwner;\n emit OwnershipTransferred(oldOwner, newOwner);\n }\n}\n" + }, + "@openzeppelin/contracts/interfaces/IERC1271.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (interfaces/IERC1271.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC1271 standard signature validation method for\n * contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].\n *\n * _Available since v4.1._\n */\ninterface IERC1271 {\n /**\n * @dev Should return whether the signature provided is valid for the provided data\n * @param hash Hash of the data to be signed\n * @param signature Signature byte array associated with _data\n */\n function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/ERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./IERC20.sol\";\nimport \"./extensions/IERC20Metadata.sol\";\nimport \"../../utils/Context.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n * For a generic mechanism see {ERC20PresetMinterPauser}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC20\n * applications.\n *\n * Additionally, an {Approval} event is emitted on calls to {transferFrom}.\n * This allows applications to reconstruct the allowance for all accounts just\n * by listening to said events. Other implementations of the EIP may not emit\n * these events, as it isn't required by the specification.\n *\n * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}\n * functions have been added to mitigate the well-known issues around setting\n * allowances. See {IERC20-approve}.\n */\ncontract ERC20 is Context, IERC20, IERC20Metadata {\n mapping(address => uint256) private _balances;\n\n mapping(address => mapping(address => uint256)) private _allowances;\n\n uint256 private _totalSupply;\n\n string private _name;\n string private _symbol;\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * The default value of {decimals} is 18. To select a different value for\n * {decimals} you should overload it.\n *\n * All two of these values are immutable: they can only be set once during\n * construction.\n */\n constructor(string memory name_, string memory symbol_) {\n _name = name_;\n _symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual override returns (string memory) {\n return _name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual override returns (string memory) {\n return _symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the value {ERC20} uses, unless this function is\n * overridden;\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual override returns (uint8) {\n return 18;\n }\n\n /**\n * @dev See {IERC20-totalSupply}.\n */\n function totalSupply() public view virtual override returns (uint256) {\n return _totalSupply;\n }\n\n /**\n * @dev See {IERC20-balanceOf}.\n */\n function balanceOf(address account) public view virtual override returns (uint256) {\n return _balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `amount`.\n */\n function transfer(address to, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-allowance}.\n */\n function allowance(address owner, address spender) public view virtual override returns (uint256) {\n return _allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 amount) public virtual override returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, amount);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Emits an {Approval} event indicating the updated allowance. This is not\n * required by the EIP. See the note at the beginning of {ERC20}.\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `amount`.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) public virtual override returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, amount);\n _transfer(from, to, amount);\n return true;\n }\n\n /**\n * @dev Atomically increases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, allowance(owner, spender) + addedValue);\n return true;\n }\n\n /**\n * @dev Atomically decreases the allowance granted to `spender` by the caller.\n *\n * This is an alternative to {approve} that can be used as a mitigation for\n * problems described in {IERC20-approve}.\n *\n * Emits an {Approval} event indicating the updated allowance.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `spender` must have allowance for the caller of at least\n * `subtractedValue`.\n */\n function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {\n address owner = _msgSender();\n uint256 currentAllowance = allowance(owner, spender);\n require(currentAllowance >= subtractedValue, \"ERC20: decreased allowance below zero\");\n unchecked {\n _approve(owner, spender, currentAllowance - subtractedValue);\n }\n\n return true;\n }\n\n /**\n * @dev Moves `amount` of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * Requirements:\n *\n * - `from` cannot be the zero address.\n * - `to` cannot be the zero address.\n * - `from` must have a balance of at least `amount`.\n */\n function _transfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {\n require(from != address(0), \"ERC20: transfer from the zero address\");\n require(to != address(0), \"ERC20: transfer to the zero address\");\n\n _beforeTokenTransfer(from, to, amount);\n\n uint256 fromBalance = _balances[from];\n require(fromBalance >= amount, \"ERC20: transfer amount exceeds balance\");\n unchecked {\n _balances[from] = fromBalance - amount;\n // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by\n // decrementing then incrementing.\n _balances[to] += amount;\n }\n\n emit Transfer(from, to, amount);\n\n _afterTokenTransfer(from, to, amount);\n }\n\n /** @dev Creates `amount` tokens and assigns them to `account`, increasing\n * the total supply.\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n */\n function _mint(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: mint to the zero address\");\n\n _beforeTokenTransfer(address(0), account, amount);\n\n _totalSupply += amount;\n unchecked {\n // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.\n _balances[account] += amount;\n }\n emit Transfer(address(0), account, amount);\n\n _afterTokenTransfer(address(0), account, amount);\n }\n\n /**\n * @dev Destroys `amount` tokens from `account`, reducing the\n * total supply.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * Requirements:\n *\n * - `account` cannot be the zero address.\n * - `account` must have at least `amount` tokens.\n */\n function _burn(address account, uint256 amount) internal virtual {\n require(account != address(0), \"ERC20: burn from the zero address\");\n\n _beforeTokenTransfer(account, address(0), amount);\n\n uint256 accountBalance = _balances[account];\n require(accountBalance >= amount, \"ERC20: burn amount exceeds balance\");\n unchecked {\n _balances[account] = accountBalance - amount;\n // Overflow not possible: amount <= accountBalance <= totalSupply.\n _totalSupply -= amount;\n }\n\n emit Transfer(account, address(0), amount);\n\n _afterTokenTransfer(account, address(0), amount);\n }\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n */\n function _approve(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n require(owner != address(0), \"ERC20: approve from the zero address\");\n require(spender != address(0), \"ERC20: approve to the zero address\");\n\n _allowances[owner][spender] = amount;\n emit Approval(owner, spender, amount);\n }\n\n /**\n * @dev Updates `owner` s allowance for `spender` based on spent `amount`.\n *\n * Does not update the allowance amount in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Might emit an {Approval} event.\n */\n function _spendAllowance(\n address owner,\n address spender,\n uint256 amount\n ) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance != type(uint256).max) {\n require(currentAllowance >= amount, \"ERC20: insufficient allowance\");\n unchecked {\n _approve(owner, spender, currentAllowance - amount);\n }\n }\n }\n\n /**\n * @dev Hook that is called before any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * will be transferred to `to`.\n * - when `from` is zero, `amount` tokens will be minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens will be burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _beforeTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n\n /**\n * @dev Hook that is called after any transfer of tokens. This includes\n * minting and burning.\n *\n * Calling conditions:\n *\n * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens\n * has been transferred to `to`.\n * - when `from` is zero, `amount` tokens have been minted for `to`.\n * - when `to` is zero, `amount` of ``from``'s tokens have been burned.\n * - `from` and `to` are never both zero.\n *\n * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].\n */\n function _afterTokenTransfer(\n address from,\n address to,\n uint256 amount\n ) internal virtual {}\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\ninterface IERC20Permit {\n /**\n * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,\n * given ``owner``'s signed approval.\n *\n * IMPORTANT: The same issues {IERC20-approve} has related to transaction\n * ordering also apply here.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n * - `deadline` must be a timestamp in the future.\n * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`\n * over the EIP712-formatted function arguments.\n * - the signature must use ``owner``'s current nonce (see {nonces}).\n *\n * For more information on the signature format, see the\n * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP\n * section].\n */\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) external;\n\n /**\n * @dev Returns the current nonce for `owner`. This value must be\n * included whenever a signature is generated for {permit}.\n *\n * Every successful call to {permit} increases ``owner``'s nonce by one. This\n * prevents a signature from being used multiple times.\n */\n function nonces(address owner) external view returns (uint256);\n\n /**\n * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.\n */\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\n\n/**\n * @dev Interface for the optional metadata functions from the ERC20 standard.\n *\n * _Available since v4.1._\n */\ninterface IERC20Metadata is IERC20 {\n /**\n * @dev Returns the name of the token.\n */\n function name() external view returns (string memory);\n\n /**\n * @dev Returns the symbol of the token.\n */\n function symbol() external view returns (string memory);\n\n /**\n * @dev Returns the decimals places of the token.\n */\n function decimals() external view returns (uint8);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/IERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n /**\n * @dev Emitted when `value` tokens are moved from one account (`from`) to\n * another (`to`).\n *\n * Note that `value` may be zero.\n */\n event Transfer(address indexed from, address indexed to, uint256 value);\n\n /**\n * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n * a call to {approve}. `value` is the new allowance.\n */\n event Approval(address indexed owner, address indexed spender, uint256 value);\n\n /**\n * @dev Returns the amount of tokens in existence.\n */\n function totalSupply() external view returns (uint256);\n\n /**\n * @dev Returns the amount of tokens owned by `account`.\n */\n function balanceOf(address account) external view returns (uint256);\n\n /**\n * @dev Moves `amount` tokens from the caller's account to `to`.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transfer(address to, uint256 amount) external returns (bool);\n\n /**\n * @dev Returns the remaining number of tokens that `spender` will be\n * allowed to spend on behalf of `owner` through {transferFrom}. This is\n * zero by default.\n *\n * This value changes when {approve} or {transferFrom} are called.\n */\n function allowance(address owner, address spender) external view returns (uint256);\n\n /**\n * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * IMPORTANT: Beware that changing an allowance with this method brings the risk\n * that someone may use both the old and the new allowance by unfortunate\n * transaction ordering. One possible solution to mitigate this race\n * condition is to first reduce the spender's allowance to 0 and set the\n * desired value afterwards:\n * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n *\n * Emits an {Approval} event.\n */\n function approve(address spender, uint256 amount) external returns (bool);\n\n /**\n * @dev Moves `amount` tokens from `from` to `to` using the\n * allowance mechanism. `amount` is then deducted from the caller's\n * allowance.\n *\n * Returns a boolean value indicating whether the operation succeeded.\n *\n * Emits a {Transfer} event.\n */\n function transferFrom(\n address from,\n address to,\n uint256 amount\n ) external returns (bool);\n}\n" + }, + "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/utils/SafeERC20.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../IERC20.sol\";\nimport \"../extensions/draft-IERC20Permit.sol\";\nimport \"../../../utils/Address.sol\";\n\n/**\n * @title SafeERC20\n * @dev Wrappers around ERC20 operations that throw on failure (when the token\n * contract returns false). Tokens that return no value (and instead revert or\n * throw on failure) are also supported, non-reverting calls are assumed to be\n * successful.\n * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract,\n * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.\n */\nlibrary SafeERC20 {\n using Address for address;\n\n function safeTransfer(\n IERC20 token,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));\n }\n\n function safeTransferFrom(\n IERC20 token,\n address from,\n address to,\n uint256 value\n ) internal {\n _callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));\n }\n\n /**\n * @dev Deprecated. This function has issues similar to the ones found in\n * {IERC20-approve}, and its usage is discouraged.\n *\n * Whenever possible, use {safeIncreaseAllowance} and\n * {safeDecreaseAllowance} instead.\n */\n function safeApprove(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n // safeApprove should only be called when setting an initial allowance,\n // or when resetting it to zero. To increase and decrease it, use\n // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'\n require(\n (value == 0) || (token.allowance(address(this), spender) == 0),\n \"SafeERC20: approve from non-zero to non-zero allowance\"\n );\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));\n }\n\n function safeIncreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n uint256 newAllowance = token.allowance(address(this), spender) + value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n\n function safeDecreaseAllowance(\n IERC20 token,\n address spender,\n uint256 value\n ) internal {\n unchecked {\n uint256 oldAllowance = token.allowance(address(this), spender);\n require(oldAllowance >= value, \"SafeERC20: decreased allowance below zero\");\n uint256 newAllowance = oldAllowance - value;\n _callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));\n }\n }\n\n function safePermit(\n IERC20Permit token,\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) internal {\n uint256 nonceBefore = token.nonces(owner);\n token.permit(owner, spender, value, deadline, v, r, s);\n uint256 nonceAfter = token.nonces(owner);\n require(nonceAfter == nonceBefore + 1, \"SafeERC20: permit did not succeed\");\n }\n\n /**\n * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement\n * on the return value: the return value is optional (but if data is returned, it must not be false).\n * @param token The token targeted by the call.\n * @param data The call data (encoded using abi.encode or one of its variants).\n */\n function _callOptionalReturn(IERC20 token, bytes memory data) private {\n // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since\n // we're implementing it ourselves. We use {Address-functionCall} to perform this call, which verifies that\n // the target address contains contract code and also asserts for success in the low-level call.\n\n bytes memory returndata = address(token).functionCall(data, \"SafeERC20: low-level call failed\");\n if (returndata.length > 0) {\n // Return data is optional\n require(abi.decode(returndata, (bool)), \"SafeERC20: ERC20 operation did not succeed\");\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Address.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Address.sol)\n\npragma solidity ^0.8.1;\n\n/**\n * @dev Collection of functions related to the address type\n */\nlibrary Address {\n /**\n * @dev Returns true if `account` is a contract.\n *\n * [IMPORTANT]\n * ====\n * It is unsafe to assume that an address for which this function returns\n * false is an externally-owned account (EOA) and not a contract.\n *\n * Among others, `isContract` will return false for the following\n * types of addresses:\n *\n * - an externally-owned account\n * - a contract in construction\n * - an address where a contract will be created\n * - an address where a contract lived, but was destroyed\n * ====\n *\n * [IMPORTANT]\n * ====\n * You shouldn't rely on `isContract` to protect against flash loan attacks!\n *\n * Preventing calls from contracts is highly discouraged. It breaks composability, breaks support for smart wallets\n * like Gnosis Safe, and does not provide security since it can be circumvented by calling from a contract\n * constructor.\n * ====\n */\n function isContract(address account) internal view returns (bool) {\n // This method relies on extcodesize/address.code.length, which returns 0\n // for contracts in construction, since the code is only stored at the end\n // of the constructor execution.\n\n return account.code.length > 0;\n }\n\n /**\n * @dev Replacement for Solidity's `transfer`: sends `amount` wei to\n * `recipient`, forwarding all available gas and reverting on errors.\n *\n * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost\n * of certain opcodes, possibly making contracts go over the 2300 gas limit\n * imposed by `transfer`, making them unable to receive funds via\n * `transfer`. {sendValue} removes this limitation.\n *\n * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].\n *\n * IMPORTANT: because control is transferred to `recipient`, care must be\n * taken to not create reentrancy vulnerabilities. Consider using\n * {ReentrancyGuard} or the\n * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].\n */\n function sendValue(address payable recipient, uint256 amount) internal {\n require(address(this).balance >= amount, \"Address: insufficient balance\");\n\n (bool success, ) = recipient.call{value: amount}(\"\");\n require(success, \"Address: unable to send value, recipient may have reverted\");\n }\n\n /**\n * @dev Performs a Solidity function call using a low level `call`. A\n * plain `call` is an unsafe replacement for a function call: use this\n * function instead.\n *\n * If `target` reverts with a revert reason, it is bubbled up by this\n * function (like regular Solidity function calls).\n *\n * Returns the raw returned data. To convert to the expected return value,\n * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].\n *\n * Requirements:\n *\n * - `target` must be a contract.\n * - calling `target` with `data` must not revert.\n *\n * _Available since v3.1._\n */\n function functionCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, \"Address: low-level call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with\n * `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, 0, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but also transferring `value` wei to `target`.\n *\n * Requirements:\n *\n * - the calling contract must have an ETH balance of at least `value`.\n * - the called Solidity function must be `payable`.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value\n ) internal returns (bytes memory) {\n return functionCallWithValue(target, data, value, \"Address: low-level call with value failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but\n * with `errorMessage` as a fallback revert reason when `target` reverts.\n *\n * _Available since v3.1._\n */\n function functionCallWithValue(\n address target,\n bytes memory data,\n uint256 value,\n string memory errorMessage\n ) internal returns (bytes memory) {\n require(address(this).balance >= value, \"Address: insufficient balance for call\");\n (bool success, bytes memory returndata) = target.call{value: value}(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {\n return functionStaticCall(target, data, \"Address: low-level static call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a static call.\n *\n * _Available since v3.3._\n */\n function functionStaticCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n (bool success, bytes memory returndata) = target.staticcall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {\n return functionDelegateCall(target, data, \"Address: low-level delegate call failed\");\n }\n\n /**\n * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],\n * but performing a delegate call.\n *\n * _Available since v3.4._\n */\n function functionDelegateCall(\n address target,\n bytes memory data,\n string memory errorMessage\n ) internal returns (bytes memory) {\n (bool success, bytes memory returndata) = target.delegatecall(data);\n return verifyCallResultFromTarget(target, success, returndata, errorMessage);\n }\n\n /**\n * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling\n * the revert reason or using the provided one) in case of unsuccessful call or if target was not a contract.\n *\n * _Available since v4.8._\n */\n function verifyCallResultFromTarget(\n address target,\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal view returns (bytes memory) {\n if (success) {\n if (returndata.length == 0) {\n // only check isContract if the call was successful and the return data is empty\n // otherwise we already know that it was a contract\n require(isContract(target), \"Address: call to non-contract\");\n }\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n /**\n * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the\n * revert reason or using the provided one.\n *\n * _Available since v4.3._\n */\n function verifyCallResult(\n bool success,\n bytes memory returndata,\n string memory errorMessage\n ) internal pure returns (bytes memory) {\n if (success) {\n return returndata;\n } else {\n _revert(returndata, errorMessage);\n }\n }\n\n function _revert(bytes memory returndata, string memory errorMessage) private pure {\n // Look for revert reason and bubble it up if present\n if (returndata.length > 0) {\n // The easiest way to bubble the revert reason is using memory via assembly\n /// @solidity memory-safe-assembly\n assembly {\n let returndata_size := mload(returndata)\n revert(add(32, returndata), returndata_size)\n }\n } else {\n revert(errorMessage);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Context.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n function _msgSender() internal view virtual returns (address) {\n return msg.sender;\n }\n\n function _msgData() internal view virtual returns (bytes calldata) {\n return msg.data;\n }\n}\n" + }, + "@openzeppelin/contracts/utils/cryptography/ECDSA.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (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 // Deprecated in v4.8\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 }\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 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 /// @solidity memory-safe-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 {\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 = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);\n uint8 v = uint8((uint256(vs) >> 255) + 27);\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\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/cryptography/SignatureChecker.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/cryptography/SignatureChecker.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./ECDSA.sol\";\nimport \"../Address.sol\";\nimport \"../../interfaces/IERC1271.sol\";\n\n/**\n * @dev Signature verification helper that can be used instead of `ECDSA.recover` to seamlessly support both ECDSA\n * signatures from externally owned accounts (EOAs) as well as ERC1271 signatures from smart contract wallets like\n * Argent and Gnosis Safe.\n *\n * _Available since v4.1._\n */\nlibrary SignatureChecker {\n /**\n * @dev Checks if a signature is valid for a given signer and data hash. If the signer is a smart contract, the\n * signature is validated against that smart contract using ERC1271, otherwise it's validated using `ECDSA.recover`.\n *\n * NOTE: Unlike ECDSA signatures, contract signatures are revocable, and the outcome of this function can thus\n * change through time. It could return true at block N and false at block N+1 (or the opposite).\n */\n function isValidSignatureNow(\n address signer,\n bytes32 hash,\n bytes memory signature\n ) internal view returns (bool) {\n (address recovered, ECDSA.RecoverError error) = ECDSA.tryRecover(hash, signature);\n if (error == ECDSA.RecoverError.NoError && recovered == signer) {\n return true;\n }\n\n (bool success, bytes memory result) = signer.staticcall(\n abi.encodeWithSelector(IERC1271.isValidSignature.selector, hash, signature)\n );\n return (success &&\n result.length == 32 &&\n abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/Math.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Standard math utilities missing in the Solidity language.\n */\nlibrary Math {\n enum Rounding {\n Down, // Toward negative infinity\n Up, // Toward infinity\n Zero // Toward zero\n }\n\n /**\n * @dev Returns the largest of two numbers.\n */\n function max(uint256 a, uint256 b) internal pure returns (uint256) {\n return a > b ? a : b;\n }\n\n /**\n * @dev Returns the smallest of two numbers.\n */\n function min(uint256 a, uint256 b) internal pure returns (uint256) {\n return a < b ? a : b;\n }\n\n /**\n * @dev Returns the average of two numbers. The result is rounded towards\n * zero.\n */\n function average(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b) / 2 can overflow.\n return (a & b) + (a ^ b) / 2;\n }\n\n /**\n * @dev Returns the ceiling of the division of two numbers.\n *\n * This differs from standard division with `/` in that it rounds up instead\n * of rounding down.\n */\n function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {\n // (a + b - 1) / b can overflow on addition, so we distribute.\n return a == 0 ? 0 : (a - 1) / b + 1;\n }\n\n /**\n * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0\n * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)\n * with further edits by Uniswap Labs also under MIT license.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator\n ) internal pure returns (uint256 result) {\n unchecked {\n // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use\n // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256\n // variables such that product = prod1 * 2^256 + prod0.\n uint256 prod0; // Least significant 256 bits of the product\n uint256 prod1; // Most significant 256 bits of the product\n assembly {\n let mm := mulmod(x, y, not(0))\n prod0 := mul(x, y)\n prod1 := sub(sub(mm, prod0), lt(mm, prod0))\n }\n\n // Handle non-overflow cases, 256 by 256 division.\n if (prod1 == 0) {\n return prod0 / denominator;\n }\n\n // Make sure the result is less than 2^256. Also prevents denominator == 0.\n require(denominator > prod1);\n\n ///////////////////////////////////////////////\n // 512 by 256 division.\n ///////////////////////////////////////////////\n\n // Make division exact by subtracting the remainder from [prod1 prod0].\n uint256 remainder;\n assembly {\n // Compute remainder using mulmod.\n remainder := mulmod(x, y, denominator)\n\n // Subtract 256 bit number from 512 bit number.\n prod1 := sub(prod1, gt(remainder, prod0))\n prod0 := sub(prod0, remainder)\n }\n\n // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.\n // See https://cs.stackexchange.com/q/138556/92363.\n\n // Does not overflow because the denominator cannot be zero at this stage in the function.\n uint256 twos = denominator & (~denominator + 1);\n assembly {\n // Divide denominator by twos.\n denominator := div(denominator, twos)\n\n // Divide [prod1 prod0] by twos.\n prod0 := div(prod0, twos)\n\n // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.\n twos := add(div(sub(0, twos), twos), 1)\n }\n\n // Shift in bits from prod1 into prod0.\n prod0 |= prod1 * twos;\n\n // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such\n // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for\n // four bits. That is, denominator * inv = 1 mod 2^4.\n uint256 inverse = (3 * denominator) ^ 2;\n\n // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works\n // in modular arithmetic, doubling the correct bits in each step.\n inverse *= 2 - denominator * inverse; // inverse mod 2^8\n inverse *= 2 - denominator * inverse; // inverse mod 2^16\n inverse *= 2 - denominator * inverse; // inverse mod 2^32\n inverse *= 2 - denominator * inverse; // inverse mod 2^64\n inverse *= 2 - denominator * inverse; // inverse mod 2^128\n inverse *= 2 - denominator * inverse; // inverse mod 2^256\n\n // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.\n // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is\n // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1\n // is no longer required.\n result = prod0 * inverse;\n return result;\n }\n }\n\n /**\n * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.\n */\n function mulDiv(\n uint256 x,\n uint256 y,\n uint256 denominator,\n Rounding rounding\n ) internal pure returns (uint256) {\n uint256 result = mulDiv(x, y, denominator);\n if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {\n result += 1;\n }\n return result;\n }\n\n /**\n * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.\n *\n * Inspired by Henry S. Warren, Jr.'s \"Hacker's Delight\" (Chapter 11).\n */\n function sqrt(uint256 a) internal pure returns (uint256) {\n if (a == 0) {\n return 0;\n }\n\n // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.\n //\n // We know that the \"msb\" (most significant bit) of our target number `a` is a power of 2 such that we have\n // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.\n //\n // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`\n // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`\n // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`\n //\n // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.\n uint256 result = 1 << (log2(a) >> 1);\n\n // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,\n // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at\n // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision\n // into the expected uint128 result.\n unchecked {\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n result = (result + a / result) >> 1;\n return min(result, a / result);\n }\n }\n\n /**\n * @notice Calculates sqrt(a), following the selected rounding direction.\n */\n function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = sqrt(a);\n return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 2, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 128;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 64;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 32;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 16;\n }\n if (value >> 8 > 0) {\n value >>= 8;\n result += 8;\n }\n if (value >> 4 > 0) {\n value >>= 4;\n result += 4;\n }\n if (value >> 2 > 0) {\n value >>= 2;\n result += 2;\n }\n if (value >> 1 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 2, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log2(value);\n return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 10, rounded down, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >= 10**64) {\n value /= 10**64;\n result += 64;\n }\n if (value >= 10**32) {\n value /= 10**32;\n result += 32;\n }\n if (value >= 10**16) {\n value /= 10**16;\n result += 16;\n }\n if (value >= 10**8) {\n value /= 10**8;\n result += 8;\n }\n if (value >= 10**4) {\n value /= 10**4;\n result += 4;\n }\n if (value >= 10**2) {\n value /= 10**2;\n result += 2;\n }\n if (value >= 10**1) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log10(value);\n return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);\n }\n }\n\n /**\n * @dev Return the log in base 256, rounded down, of a positive value.\n * Returns 0 if given 0.\n *\n * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.\n */\n function log256(uint256 value) internal pure returns (uint256) {\n uint256 result = 0;\n unchecked {\n if (value >> 128 > 0) {\n value >>= 128;\n result += 16;\n }\n if (value >> 64 > 0) {\n value >>= 64;\n result += 8;\n }\n if (value >> 32 > 0) {\n value >>= 32;\n result += 4;\n }\n if (value >> 16 > 0) {\n value >>= 16;\n result += 2;\n }\n if (value >> 8 > 0) {\n result += 1;\n }\n }\n return result;\n }\n\n /**\n * @dev Return the log in base 10, following the selected rounding direction, of a positive value.\n * Returns 0 if given 0.\n */\n function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {\n unchecked {\n uint256 result = log256(value);\n return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);\n }\n }\n}\n" + }, + "@openzeppelin/contracts/utils/math/SafeCast.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SafeCast.sol)\n// This file was procedurally generated from scripts/generate/templates/SafeCast.js.\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Wrappers over Solidity's uintXX/intXX casting operators with added overflow\n * checks.\n *\n * Downcasting from uint256/int256 in Solidity does not revert on overflow. This can\n * easily result in undesired exploitation or bugs, since developers usually\n * assume that overflows raise errors. `SafeCast` restores this intuition by\n * reverting the transaction when such an operation overflows.\n *\n * Using this library instead of the unchecked operations eliminates an entire\n * class of bugs, so it's recommended to use it always.\n *\n * Can be combined with {SafeMath} and {SignedSafeMath} to extend it to smaller types, by performing\n * all math on `uint256` and `int256` and then downcasting.\n */\nlibrary SafeCast {\n /**\n * @dev Returns the downcasted uint248 from uint256, reverting on\n * overflow (when the input is greater than largest uint248).\n *\n * Counterpart to Solidity's `uint248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toUint248(uint256 value) internal pure returns (uint248) {\n require(value <= type(uint248).max, \"SafeCast: value doesn't fit in 248 bits\");\n return uint248(value);\n }\n\n /**\n * @dev Returns the downcasted uint240 from uint256, reverting on\n * overflow (when the input is greater than largest uint240).\n *\n * Counterpart to Solidity's `uint240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toUint240(uint256 value) internal pure returns (uint240) {\n require(value <= type(uint240).max, \"SafeCast: value doesn't fit in 240 bits\");\n return uint240(value);\n }\n\n /**\n * @dev Returns the downcasted uint232 from uint256, reverting on\n * overflow (when the input is greater than largest uint232).\n *\n * Counterpart to Solidity's `uint232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toUint232(uint256 value) internal pure returns (uint232) {\n require(value <= type(uint232).max, \"SafeCast: value doesn't fit in 232 bits\");\n return uint232(value);\n }\n\n /**\n * @dev Returns the downcasted uint224 from uint256, reverting on\n * overflow (when the input is greater than largest uint224).\n *\n * Counterpart to Solidity's `uint224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.2._\n */\n function toUint224(uint256 value) internal pure returns (uint224) {\n require(value <= type(uint224).max, \"SafeCast: value doesn't fit in 224 bits\");\n return uint224(value);\n }\n\n /**\n * @dev Returns the downcasted uint216 from uint256, reverting on\n * overflow (when the input is greater than largest uint216).\n *\n * Counterpart to Solidity's `uint216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toUint216(uint256 value) internal pure returns (uint216) {\n require(value <= type(uint216).max, \"SafeCast: value doesn't fit in 216 bits\");\n return uint216(value);\n }\n\n /**\n * @dev Returns the downcasted uint208 from uint256, reverting on\n * overflow (when the input is greater than largest uint208).\n *\n * Counterpart to Solidity's `uint208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toUint208(uint256 value) internal pure returns (uint208) {\n require(value <= type(uint208).max, \"SafeCast: value doesn't fit in 208 bits\");\n return uint208(value);\n }\n\n /**\n * @dev Returns the downcasted uint200 from uint256, reverting on\n * overflow (when the input is greater than largest uint200).\n *\n * Counterpart to Solidity's `uint200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toUint200(uint256 value) internal pure returns (uint200) {\n require(value <= type(uint200).max, \"SafeCast: value doesn't fit in 200 bits\");\n return uint200(value);\n }\n\n /**\n * @dev Returns the downcasted uint192 from uint256, reverting on\n * overflow (when the input is greater than largest uint192).\n *\n * Counterpart to Solidity's `uint192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toUint192(uint256 value) internal pure returns (uint192) {\n require(value <= type(uint192).max, \"SafeCast: value doesn't fit in 192 bits\");\n return uint192(value);\n }\n\n /**\n * @dev Returns the downcasted uint184 from uint256, reverting on\n * overflow (when the input is greater than largest uint184).\n *\n * Counterpart to Solidity's `uint184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toUint184(uint256 value) internal pure returns (uint184) {\n require(value <= type(uint184).max, \"SafeCast: value doesn't fit in 184 bits\");\n return uint184(value);\n }\n\n /**\n * @dev Returns the downcasted uint176 from uint256, reverting on\n * overflow (when the input is greater than largest uint176).\n *\n * Counterpart to Solidity's `uint176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toUint176(uint256 value) internal pure returns (uint176) {\n require(value <= type(uint176).max, \"SafeCast: value doesn't fit in 176 bits\");\n return uint176(value);\n }\n\n /**\n * @dev Returns the downcasted uint168 from uint256, reverting on\n * overflow (when the input is greater than largest uint168).\n *\n * Counterpart to Solidity's `uint168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toUint168(uint256 value) internal pure returns (uint168) {\n require(value <= type(uint168).max, \"SafeCast: value doesn't fit in 168 bits\");\n return uint168(value);\n }\n\n /**\n * @dev Returns the downcasted uint160 from uint256, reverting on\n * overflow (when the input is greater than largest uint160).\n *\n * Counterpart to Solidity's `uint160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toUint160(uint256 value) internal pure returns (uint160) {\n require(value <= type(uint160).max, \"SafeCast: value doesn't fit in 160 bits\");\n return uint160(value);\n }\n\n /**\n * @dev Returns the downcasted uint152 from uint256, reverting on\n * overflow (when the input is greater than largest uint152).\n *\n * Counterpart to Solidity's `uint152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toUint152(uint256 value) internal pure returns (uint152) {\n require(value <= type(uint152).max, \"SafeCast: value doesn't fit in 152 bits\");\n return uint152(value);\n }\n\n /**\n * @dev Returns the downcasted uint144 from uint256, reverting on\n * overflow (when the input is greater than largest uint144).\n *\n * Counterpart to Solidity's `uint144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toUint144(uint256 value) internal pure returns (uint144) {\n require(value <= type(uint144).max, \"SafeCast: value doesn't fit in 144 bits\");\n return uint144(value);\n }\n\n /**\n * @dev Returns the downcasted uint136 from uint256, reverting on\n * overflow (when the input is greater than largest uint136).\n *\n * Counterpart to Solidity's `uint136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toUint136(uint256 value) internal pure returns (uint136) {\n require(value <= type(uint136).max, \"SafeCast: value doesn't fit in 136 bits\");\n return uint136(value);\n }\n\n /**\n * @dev Returns the downcasted uint128 from uint256, reverting on\n * overflow (when the input is greater than largest uint128).\n *\n * Counterpart to Solidity's `uint128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v2.5._\n */\n function toUint128(uint256 value) internal pure returns (uint128) {\n require(value <= type(uint128).max, \"SafeCast: value doesn't fit in 128 bits\");\n return uint128(value);\n }\n\n /**\n * @dev Returns the downcasted uint120 from uint256, reverting on\n * overflow (when the input is greater than largest uint120).\n *\n * Counterpart to Solidity's `uint120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toUint120(uint256 value) internal pure returns (uint120) {\n require(value <= type(uint120).max, \"SafeCast: value doesn't fit in 120 bits\");\n return uint120(value);\n }\n\n /**\n * @dev Returns the downcasted uint112 from uint256, reverting on\n * overflow (when the input is greater than largest uint112).\n *\n * Counterpart to Solidity's `uint112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toUint112(uint256 value) internal pure returns (uint112) {\n require(value <= type(uint112).max, \"SafeCast: value doesn't fit in 112 bits\");\n return uint112(value);\n }\n\n /**\n * @dev Returns the downcasted uint104 from uint256, reverting on\n * overflow (when the input is greater than largest uint104).\n *\n * Counterpart to Solidity's `uint104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toUint104(uint256 value) internal pure returns (uint104) {\n require(value <= type(uint104).max, \"SafeCast: value doesn't fit in 104 bits\");\n return uint104(value);\n }\n\n /**\n * @dev Returns the downcasted uint96 from uint256, reverting on\n * overflow (when the input is greater than largest uint96).\n *\n * Counterpart to Solidity's `uint96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.2._\n */\n function toUint96(uint256 value) internal pure returns (uint96) {\n require(value <= type(uint96).max, \"SafeCast: value doesn't fit in 96 bits\");\n return uint96(value);\n }\n\n /**\n * @dev Returns the downcasted uint88 from uint256, reverting on\n * overflow (when the input is greater than largest uint88).\n *\n * Counterpart to Solidity's `uint88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toUint88(uint256 value) internal pure returns (uint88) {\n require(value <= type(uint88).max, \"SafeCast: value doesn't fit in 88 bits\");\n return uint88(value);\n }\n\n /**\n * @dev Returns the downcasted uint80 from uint256, reverting on\n * overflow (when the input is greater than largest uint80).\n *\n * Counterpart to Solidity's `uint80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toUint80(uint256 value) internal pure returns (uint80) {\n require(value <= type(uint80).max, \"SafeCast: value doesn't fit in 80 bits\");\n return uint80(value);\n }\n\n /**\n * @dev Returns the downcasted uint72 from uint256, reverting on\n * overflow (when the input is greater than largest uint72).\n *\n * Counterpart to Solidity's `uint72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toUint72(uint256 value) internal pure returns (uint72) {\n require(value <= type(uint72).max, \"SafeCast: value doesn't fit in 72 bits\");\n return uint72(value);\n }\n\n /**\n * @dev Returns the downcasted uint64 from uint256, reverting on\n * overflow (when the input is greater than largest uint64).\n *\n * Counterpart to Solidity's `uint64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v2.5._\n */\n function toUint64(uint256 value) internal pure returns (uint64) {\n require(value <= type(uint64).max, \"SafeCast: value doesn't fit in 64 bits\");\n return uint64(value);\n }\n\n /**\n * @dev Returns the downcasted uint56 from uint256, reverting on\n * overflow (when the input is greater than largest uint56).\n *\n * Counterpart to Solidity's `uint56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toUint56(uint256 value) internal pure returns (uint56) {\n require(value <= type(uint56).max, \"SafeCast: value doesn't fit in 56 bits\");\n return uint56(value);\n }\n\n /**\n * @dev Returns the downcasted uint48 from uint256, reverting on\n * overflow (when the input is greater than largest uint48).\n *\n * Counterpart to Solidity's `uint48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toUint48(uint256 value) internal pure returns (uint48) {\n require(value <= type(uint48).max, \"SafeCast: value doesn't fit in 48 bits\");\n return uint48(value);\n }\n\n /**\n * @dev Returns the downcasted uint40 from uint256, reverting on\n * overflow (when the input is greater than largest uint40).\n *\n * Counterpart to Solidity's `uint40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toUint40(uint256 value) internal pure returns (uint40) {\n require(value <= type(uint40).max, \"SafeCast: value doesn't fit in 40 bits\");\n return uint40(value);\n }\n\n /**\n * @dev Returns the downcasted uint32 from uint256, reverting on\n * overflow (when the input is greater than largest uint32).\n *\n * Counterpart to Solidity's `uint32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v2.5._\n */\n function toUint32(uint256 value) internal pure returns (uint32) {\n require(value <= type(uint32).max, \"SafeCast: value doesn't fit in 32 bits\");\n return uint32(value);\n }\n\n /**\n * @dev Returns the downcasted uint24 from uint256, reverting on\n * overflow (when the input is greater than largest uint24).\n *\n * Counterpart to Solidity's `uint24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toUint24(uint256 value) internal pure returns (uint24) {\n require(value <= type(uint24).max, \"SafeCast: value doesn't fit in 24 bits\");\n return uint24(value);\n }\n\n /**\n * @dev Returns the downcasted uint16 from uint256, reverting on\n * overflow (when the input is greater than largest uint16).\n *\n * Counterpart to Solidity's `uint16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v2.5._\n */\n function toUint16(uint256 value) internal pure returns (uint16) {\n require(value <= type(uint16).max, \"SafeCast: value doesn't fit in 16 bits\");\n return uint16(value);\n }\n\n /**\n * @dev Returns the downcasted uint8 from uint256, reverting on\n * overflow (when the input is greater than largest uint8).\n *\n * Counterpart to Solidity's `uint8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v2.5._\n */\n function toUint8(uint256 value) internal pure returns (uint8) {\n require(value <= type(uint8).max, \"SafeCast: value doesn't fit in 8 bits\");\n return uint8(value);\n }\n\n /**\n * @dev Converts a signed int256 into an unsigned uint256.\n *\n * Requirements:\n *\n * - input must be greater than or equal to 0.\n *\n * _Available since v3.0._\n */\n function toUint256(int256 value) internal pure returns (uint256) {\n require(value >= 0, \"SafeCast: value must be positive\");\n return uint256(value);\n }\n\n /**\n * @dev Returns the downcasted int248 from int256, reverting on\n * overflow (when the input is less than smallest int248 or\n * greater than largest int248).\n *\n * Counterpart to Solidity's `int248` operator.\n *\n * Requirements:\n *\n * - input must fit into 248 bits\n *\n * _Available since v4.7._\n */\n function toInt248(int256 value) internal pure returns (int248 downcasted) {\n downcasted = int248(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 248 bits\");\n }\n\n /**\n * @dev Returns the downcasted int240 from int256, reverting on\n * overflow (when the input is less than smallest int240 or\n * greater than largest int240).\n *\n * Counterpart to Solidity's `int240` operator.\n *\n * Requirements:\n *\n * - input must fit into 240 bits\n *\n * _Available since v4.7._\n */\n function toInt240(int256 value) internal pure returns (int240 downcasted) {\n downcasted = int240(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 240 bits\");\n }\n\n /**\n * @dev Returns the downcasted int232 from int256, reverting on\n * overflow (when the input is less than smallest int232 or\n * greater than largest int232).\n *\n * Counterpart to Solidity's `int232` operator.\n *\n * Requirements:\n *\n * - input must fit into 232 bits\n *\n * _Available since v4.7._\n */\n function toInt232(int256 value) internal pure returns (int232 downcasted) {\n downcasted = int232(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 232 bits\");\n }\n\n /**\n * @dev Returns the downcasted int224 from int256, reverting on\n * overflow (when the input is less than smallest int224 or\n * greater than largest int224).\n *\n * Counterpart to Solidity's `int224` operator.\n *\n * Requirements:\n *\n * - input must fit into 224 bits\n *\n * _Available since v4.7._\n */\n function toInt224(int256 value) internal pure returns (int224 downcasted) {\n downcasted = int224(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 224 bits\");\n }\n\n /**\n * @dev Returns the downcasted int216 from int256, reverting on\n * overflow (when the input is less than smallest int216 or\n * greater than largest int216).\n *\n * Counterpart to Solidity's `int216` operator.\n *\n * Requirements:\n *\n * - input must fit into 216 bits\n *\n * _Available since v4.7._\n */\n function toInt216(int256 value) internal pure returns (int216 downcasted) {\n downcasted = int216(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 216 bits\");\n }\n\n /**\n * @dev Returns the downcasted int208 from int256, reverting on\n * overflow (when the input is less than smallest int208 or\n * greater than largest int208).\n *\n * Counterpart to Solidity's `int208` operator.\n *\n * Requirements:\n *\n * - input must fit into 208 bits\n *\n * _Available since v4.7._\n */\n function toInt208(int256 value) internal pure returns (int208 downcasted) {\n downcasted = int208(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 208 bits\");\n }\n\n /**\n * @dev Returns the downcasted int200 from int256, reverting on\n * overflow (when the input is less than smallest int200 or\n * greater than largest int200).\n *\n * Counterpart to Solidity's `int200` operator.\n *\n * Requirements:\n *\n * - input must fit into 200 bits\n *\n * _Available since v4.7._\n */\n function toInt200(int256 value) internal pure returns (int200 downcasted) {\n downcasted = int200(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 200 bits\");\n }\n\n /**\n * @dev Returns the downcasted int192 from int256, reverting on\n * overflow (when the input is less than smallest int192 or\n * greater than largest int192).\n *\n * Counterpart to Solidity's `int192` operator.\n *\n * Requirements:\n *\n * - input must fit into 192 bits\n *\n * _Available since v4.7._\n */\n function toInt192(int256 value) internal pure returns (int192 downcasted) {\n downcasted = int192(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 192 bits\");\n }\n\n /**\n * @dev Returns the downcasted int184 from int256, reverting on\n * overflow (when the input is less than smallest int184 or\n * greater than largest int184).\n *\n * Counterpart to Solidity's `int184` operator.\n *\n * Requirements:\n *\n * - input must fit into 184 bits\n *\n * _Available since v4.7._\n */\n function toInt184(int256 value) internal pure returns (int184 downcasted) {\n downcasted = int184(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 184 bits\");\n }\n\n /**\n * @dev Returns the downcasted int176 from int256, reverting on\n * overflow (when the input is less than smallest int176 or\n * greater than largest int176).\n *\n * Counterpart to Solidity's `int176` operator.\n *\n * Requirements:\n *\n * - input must fit into 176 bits\n *\n * _Available since v4.7._\n */\n function toInt176(int256 value) internal pure returns (int176 downcasted) {\n downcasted = int176(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 176 bits\");\n }\n\n /**\n * @dev Returns the downcasted int168 from int256, reverting on\n * overflow (when the input is less than smallest int168 or\n * greater than largest int168).\n *\n * Counterpart to Solidity's `int168` operator.\n *\n * Requirements:\n *\n * - input must fit into 168 bits\n *\n * _Available since v4.7._\n */\n function toInt168(int256 value) internal pure returns (int168 downcasted) {\n downcasted = int168(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 168 bits\");\n }\n\n /**\n * @dev Returns the downcasted int160 from int256, reverting on\n * overflow (when the input is less than smallest int160 or\n * greater than largest int160).\n *\n * Counterpart to Solidity's `int160` operator.\n *\n * Requirements:\n *\n * - input must fit into 160 bits\n *\n * _Available since v4.7._\n */\n function toInt160(int256 value) internal pure returns (int160 downcasted) {\n downcasted = int160(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 160 bits\");\n }\n\n /**\n * @dev Returns the downcasted int152 from int256, reverting on\n * overflow (when the input is less than smallest int152 or\n * greater than largest int152).\n *\n * Counterpart to Solidity's `int152` operator.\n *\n * Requirements:\n *\n * - input must fit into 152 bits\n *\n * _Available since v4.7._\n */\n function toInt152(int256 value) internal pure returns (int152 downcasted) {\n downcasted = int152(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 152 bits\");\n }\n\n /**\n * @dev Returns the downcasted int144 from int256, reverting on\n * overflow (when the input is less than smallest int144 or\n * greater than largest int144).\n *\n * Counterpart to Solidity's `int144` operator.\n *\n * Requirements:\n *\n * - input must fit into 144 bits\n *\n * _Available since v4.7._\n */\n function toInt144(int256 value) internal pure returns (int144 downcasted) {\n downcasted = int144(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 144 bits\");\n }\n\n /**\n * @dev Returns the downcasted int136 from int256, reverting on\n * overflow (when the input is less than smallest int136 or\n * greater than largest int136).\n *\n * Counterpart to Solidity's `int136` operator.\n *\n * Requirements:\n *\n * - input must fit into 136 bits\n *\n * _Available since v4.7._\n */\n function toInt136(int256 value) internal pure returns (int136 downcasted) {\n downcasted = int136(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 136 bits\");\n }\n\n /**\n * @dev Returns the downcasted int128 from int256, reverting on\n * overflow (when the input is less than smallest int128 or\n * greater than largest int128).\n *\n * Counterpart to Solidity's `int128` operator.\n *\n * Requirements:\n *\n * - input must fit into 128 bits\n *\n * _Available since v3.1._\n */\n function toInt128(int256 value) internal pure returns (int128 downcasted) {\n downcasted = int128(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 128 bits\");\n }\n\n /**\n * @dev Returns the downcasted int120 from int256, reverting on\n * overflow (when the input is less than smallest int120 or\n * greater than largest int120).\n *\n * Counterpart to Solidity's `int120` operator.\n *\n * Requirements:\n *\n * - input must fit into 120 bits\n *\n * _Available since v4.7._\n */\n function toInt120(int256 value) internal pure returns (int120 downcasted) {\n downcasted = int120(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 120 bits\");\n }\n\n /**\n * @dev Returns the downcasted int112 from int256, reverting on\n * overflow (when the input is less than smallest int112 or\n * greater than largest int112).\n *\n * Counterpart to Solidity's `int112` operator.\n *\n * Requirements:\n *\n * - input must fit into 112 bits\n *\n * _Available since v4.7._\n */\n function toInt112(int256 value) internal pure returns (int112 downcasted) {\n downcasted = int112(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 112 bits\");\n }\n\n /**\n * @dev Returns the downcasted int104 from int256, reverting on\n * overflow (when the input is less than smallest int104 or\n * greater than largest int104).\n *\n * Counterpart to Solidity's `int104` operator.\n *\n * Requirements:\n *\n * - input must fit into 104 bits\n *\n * _Available since v4.7._\n */\n function toInt104(int256 value) internal pure returns (int104 downcasted) {\n downcasted = int104(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 104 bits\");\n }\n\n /**\n * @dev Returns the downcasted int96 from int256, reverting on\n * overflow (when the input is less than smallest int96 or\n * greater than largest int96).\n *\n * Counterpart to Solidity's `int96` operator.\n *\n * Requirements:\n *\n * - input must fit into 96 bits\n *\n * _Available since v4.7._\n */\n function toInt96(int256 value) internal pure returns (int96 downcasted) {\n downcasted = int96(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 96 bits\");\n }\n\n /**\n * @dev Returns the downcasted int88 from int256, reverting on\n * overflow (when the input is less than smallest int88 or\n * greater than largest int88).\n *\n * Counterpart to Solidity's `int88` operator.\n *\n * Requirements:\n *\n * - input must fit into 88 bits\n *\n * _Available since v4.7._\n */\n function toInt88(int256 value) internal pure returns (int88 downcasted) {\n downcasted = int88(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 88 bits\");\n }\n\n /**\n * @dev Returns the downcasted int80 from int256, reverting on\n * overflow (when the input is less than smallest int80 or\n * greater than largest int80).\n *\n * Counterpart to Solidity's `int80` operator.\n *\n * Requirements:\n *\n * - input must fit into 80 bits\n *\n * _Available since v4.7._\n */\n function toInt80(int256 value) internal pure returns (int80 downcasted) {\n downcasted = int80(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 80 bits\");\n }\n\n /**\n * @dev Returns the downcasted int72 from int256, reverting on\n * overflow (when the input is less than smallest int72 or\n * greater than largest int72).\n *\n * Counterpart to Solidity's `int72` operator.\n *\n * Requirements:\n *\n * - input must fit into 72 bits\n *\n * _Available since v4.7._\n */\n function toInt72(int256 value) internal pure returns (int72 downcasted) {\n downcasted = int72(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 72 bits\");\n }\n\n /**\n * @dev Returns the downcasted int64 from int256, reverting on\n * overflow (when the input is less than smallest int64 or\n * greater than largest int64).\n *\n * Counterpart to Solidity's `int64` operator.\n *\n * Requirements:\n *\n * - input must fit into 64 bits\n *\n * _Available since v3.1._\n */\n function toInt64(int256 value) internal pure returns (int64 downcasted) {\n downcasted = int64(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 64 bits\");\n }\n\n /**\n * @dev Returns the downcasted int56 from int256, reverting on\n * overflow (when the input is less than smallest int56 or\n * greater than largest int56).\n *\n * Counterpart to Solidity's `int56` operator.\n *\n * Requirements:\n *\n * - input must fit into 56 bits\n *\n * _Available since v4.7._\n */\n function toInt56(int256 value) internal pure returns (int56 downcasted) {\n downcasted = int56(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 56 bits\");\n }\n\n /**\n * @dev Returns the downcasted int48 from int256, reverting on\n * overflow (when the input is less than smallest int48 or\n * greater than largest int48).\n *\n * Counterpart to Solidity's `int48` operator.\n *\n * Requirements:\n *\n * - input must fit into 48 bits\n *\n * _Available since v4.7._\n */\n function toInt48(int256 value) internal pure returns (int48 downcasted) {\n downcasted = int48(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 48 bits\");\n }\n\n /**\n * @dev Returns the downcasted int40 from int256, reverting on\n * overflow (when the input is less than smallest int40 or\n * greater than largest int40).\n *\n * Counterpart to Solidity's `int40` operator.\n *\n * Requirements:\n *\n * - input must fit into 40 bits\n *\n * _Available since v4.7._\n */\n function toInt40(int256 value) internal pure returns (int40 downcasted) {\n downcasted = int40(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 40 bits\");\n }\n\n /**\n * @dev Returns the downcasted int32 from int256, reverting on\n * overflow (when the input is less than smallest int32 or\n * greater than largest int32).\n *\n * Counterpart to Solidity's `int32` operator.\n *\n * Requirements:\n *\n * - input must fit into 32 bits\n *\n * _Available since v3.1._\n */\n function toInt32(int256 value) internal pure returns (int32 downcasted) {\n downcasted = int32(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 32 bits\");\n }\n\n /**\n * @dev Returns the downcasted int24 from int256, reverting on\n * overflow (when the input is less than smallest int24 or\n * greater than largest int24).\n *\n * Counterpart to Solidity's `int24` operator.\n *\n * Requirements:\n *\n * - input must fit into 24 bits\n *\n * _Available since v4.7._\n */\n function toInt24(int256 value) internal pure returns (int24 downcasted) {\n downcasted = int24(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 24 bits\");\n }\n\n /**\n * @dev Returns the downcasted int16 from int256, reverting on\n * overflow (when the input is less than smallest int16 or\n * greater than largest int16).\n *\n * Counterpart to Solidity's `int16` operator.\n *\n * Requirements:\n *\n * - input must fit into 16 bits\n *\n * _Available since v3.1._\n */\n function toInt16(int256 value) internal pure returns (int16 downcasted) {\n downcasted = int16(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 16 bits\");\n }\n\n /**\n * @dev Returns the downcasted int8 from int256, reverting on\n * overflow (when the input is less than smallest int8 or\n * greater than largest int8).\n *\n * Counterpart to Solidity's `int8` operator.\n *\n * Requirements:\n *\n * - input must fit into 8 bits\n *\n * _Available since v3.1._\n */\n function toInt8(int256 value) internal pure returns (int8 downcasted) {\n downcasted = int8(value);\n require(downcasted == value, \"SafeCast: value doesn't fit in 8 bits\");\n }\n\n /**\n * @dev Converts an unsigned uint256 into a signed int256.\n *\n * Requirements:\n *\n * - input must be less than or equal to maxInt256.\n *\n * _Available since v3.0._\n */\n function toInt256(uint256 value) internal pure returns (int256) {\n // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive\n require(value <= uint256(type(int256).max), \"SafeCast: value doesn't fit in an int256\");\n return int256(value);\n }\n}\n" + }, + "@openzeppelin/contracts/utils/Strings.sol": { + "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./math/Math.sol\";\n\n/**\n * @dev String operations.\n */\nlibrary Strings {\n bytes16 private constant _SYMBOLS = \"0123456789abcdef\";\n uint8 private constant _ADDRESS_LENGTH = 20;\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` decimal representation.\n */\n function toString(uint256 value) internal pure returns (string memory) {\n unchecked {\n uint256 length = Math.log10(value) + 1;\n string memory buffer = new string(length);\n uint256 ptr;\n /// @solidity memory-safe-assembly\n assembly {\n ptr := add(buffer, add(32, length))\n }\n while (true) {\n ptr--;\n /// @solidity memory-safe-assembly\n assembly {\n mstore8(ptr, byte(mod(value, 10), _SYMBOLS))\n }\n value /= 10;\n if (value == 0) break;\n }\n return buffer;\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.\n */\n function toHexString(uint256 value) internal pure returns (string memory) {\n unchecked {\n return toHexString(value, Math.log256(value) + 1);\n }\n }\n\n /**\n * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.\n */\n function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {\n bytes memory buffer = new bytes(2 * length + 2);\n buffer[0] = \"0\";\n buffer[1] = \"x\";\n for (uint256 i = 2 * length + 1; i > 1; --i) {\n buffer[i] = _SYMBOLS[value & 0xf];\n value >>= 4;\n }\n require(value == 0, \"Strings: hex length insufficient\");\n return string(buffer);\n }\n\n /**\n * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.\n */\n function toHexString(address addr) internal pure returns (string memory) {\n return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);\n }\n}\n" + }, + "contracts/deprecated/OldDistributor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\n/*\n * █ \n ***** ▓▓▓ \n * ▓▓▓▓▓▓▓ \n * ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓ \n ***** //////// ▓▓▓▓▓▓▓ \n * ///////////// ▓▓▓ \n ▓▓ ////////////////// █ ▓▓ \n ▓▓ ▓▓ /////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓ \n ▓▓ ,////////////////////////////////////// ▓▓ ▓▓ \n ▓▓ ////////////////////////////////////////// ▓▓ \n ▓▓ //////////////////////▓▓▓▓///////////////////// \n ,//////////////////////////////////////////////////// \n .////////////////////////////////////////////////////////// \n .//////////////////////////██.,//////////////////////////█ \n .//////////////////////████..,./////////////////////██ \n ...////////////////███████.....,.////////////////███ \n ,.,////////////████████ ........,///////////████ \n .,.,//////█████████ ,.......///////████ \n ,..//████████ ........./████ \n ..,██████ .....,███ \n .██ ,.,█ \n \n \n \n ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ \n ▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓ \n ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓ \n ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ \n*/\n\npragma solidity ^0.8.17;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport \"../utils/UUPSHelper.sol\";\n\nstruct MerkleTree {\n // Root of a Merkle tree which leaves are `(address user, address token, uint amount)`\n // representing an amount of tokens accumulated by `user`.\n // The Merkle tree is assumed to have only increasing amounts: that is to say if a user can claim 1,\n // then after the amount associated in the Merkle tree for this token should be x > 1\n bytes32 merkleRoot;\n // Ipfs hash of the tree data\n bytes32 ipfsHash;\n}\n\nstruct Claim {\n uint208 amount;\n uint48 timestamp;\n bytes32 merkleRoot;\n}\n\n/// @title Distributor\n/// @notice Allows LPs on AMMs with concentrated liquidity to claim the rewards that were distributed to them\n/// @author Angle Labs. Inc\ncontract OldDistributor is UUPSHelper {\n using SafeERC20 for IERC20;\n\n /// @notice Epoch duration\n uint32 internal constant _EPOCH_DURATION = 3600;\n\n // ================================= VARIABLES =================================\n\n /// @notice Tree of claimable tokens through this contract\n MerkleTree public tree;\n\n /// @notice Tree that was in place in the contract before the last `tree` update\n MerkleTree public lastTree;\n\n /// @notice Token to deposit to freeze the roots update\n IERC20 public disputeToken;\n\n /// @notice `Core` contract handling access control\n ICore public core;\n\n /// @notice Address which created the dispute\n /// @dev Used to store if there is an ongoing dispute\n address public disputer;\n\n /// @notice When the current tree will become valid\n uint48 public endOfDisputePeriod;\n\n /// @notice Time after which a change in a tree becomes effective, in EPOCH_DURATION\n uint48 public disputePeriod;\n\n /// @notice Amount to deposit to freeze the roots update\n uint256 public disputeAmount;\n\n /// @notice Mapping user -> token -> amount to track claimed amounts\n mapping(address => mapping(address => Claim)) public claimed;\n\n /// @notice Trusted EOAs to update the Merkle root\n mapping(address => uint256) public canUpdateMerkleRoot;\n\n /// @notice Whether or not to disable permissionless claiming\n mapping(address => uint256) public onlyOperatorCanClaim;\n\n /// @notice user -> operator -> authorisation to claim\n mapping(address => mapping(address => uint256)) public operators;\n\n uint256[38] private __gap;\n\n // =================================== EVENTS ==================================\n\n event Claimed(address indexed user, address indexed token, uint256 amount);\n event DisputeAmountUpdated(uint256 _disputeAmount);\n event Disputed(string reason);\n event DisputePeriodUpdated(uint48 _disputePeriod);\n event DisputeResolved(bool valid);\n event DisputeTokenUpdated(address indexed _disputeToken);\n event OperatorClaimingToggled(address indexed user, bool isEnabled);\n event OperatorToggled(address indexed user, address indexed operator, bool isWhitelisted);\n event Recovered(address indexed token, address indexed to, uint256 amount);\n event Revoked(); // With this event an indexer could maintain a table (timestamp, merkleRootUpdate)\n event TreeUpdated(bytes32 merkleRoot, bytes32 ipfsHash, uint48 endOfDisputePeriod);\n event TrustedToggled(address indexed eoa, bool trust);\n\n // ================================= MODIFIERS =================================\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernorOrGuardian() {\n if (!core.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n _;\n }\n\n /// @notice Checks whether the `msg.sender` is the `user` address or is a trusted address\n modifier onlyTrustedOrUser(address user) {\n if (user != msg.sender && canUpdateMerkleRoot[msg.sender] != 1 && !core.isGovernorOrGuardian(msg.sender))\n revert NotTrusted();\n _;\n }\n\n // ================================ CONSTRUCTOR ================================\n\n constructor() initializer {}\n\n function initialize(ICore _core) external initializer {\n if (address(_core) == address(0)) revert ZeroAddress();\n core = _core;\n }\n\n /// @inheritdoc UUPSUpgradeable\n function _authorizeUpgrade(address) internal view override onlyGuardianUpgrader(core) {}\n\n // =============================== MAIN FUNCTION ===============================\n\n /// @notice Claims rewards for a given set of users\n /// @dev Anyone may call this function for anyone else, funds go to destination regardless, it's just a question of\n /// who provides the proof and pays the gas: `msg.sender` is used only for addresses that require a trusted operator\n /// @param users Recipient of tokens\n /// @param tokens ERC20 claimed\n /// @param amounts Amount of tokens that will be sent to the corresponding users\n /// @param proofs Array of hashes bridging from a leaf `(hash of user | token | amount)` to the Merkle root\n function claim(\n address[] calldata users,\n address[] calldata tokens,\n uint256[] calldata amounts,\n bytes32[][] calldata proofs\n ) external {\n uint256 usersLength = users.length;\n if (\n usersLength == 0 ||\n usersLength != tokens.length ||\n usersLength != amounts.length ||\n usersLength != proofs.length\n ) revert InvalidLengths();\n\n for (uint256 i; i < usersLength; ) {\n address user = users[i];\n address token = tokens[i];\n uint256 amount = amounts[i];\n\n // Checking if only an approved operator can claim for `user`\n if (onlyOperatorCanClaim[user] == 1 && operators[user][msg.sender] == 0) revert NotWhitelisted();\n\n // Verifying proof\n bytes32 leaf = keccak256(abi.encode(user, token, amount));\n if (!_verifyProof(leaf, proofs[i])) revert InvalidProof();\n\n // Closing reentrancy gate here\n uint256 toSend = amount - claimed[user][token].amount;\n claimed[user][token] = Claim(SafeCast.toUint208(amount), uint48(block.timestamp), getMerkleRoot());\n\n IERC20(token).safeTransfer(user, toSend);\n emit Claimed(user, token, toSend);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Returns the MerkleRoot that is currently live for the contract\n function getMerkleRoot() public view returns (bytes32) {\n if (block.timestamp >= endOfDisputePeriod && disputer == address(0)) return tree.merkleRoot;\n else return lastTree.merkleRoot;\n }\n\n // ============================ GOVERNANCE FUNCTIONS ===========================\n\n /// @notice Adds or removes EOAs which are trusted to update the Merkle root\n function toggleTrusted(address eoa) external onlyGovernorOrGuardian {\n uint256 trustedStatus = 1 - canUpdateMerkleRoot[eoa];\n canUpdateMerkleRoot[eoa] = trustedStatus;\n emit TrustedToggled(eoa, trustedStatus == 1);\n }\n\n /// @notice Updates Merkle Tree\n function updateTree(MerkleTree calldata _tree) external {\n if (\n disputer != address(0) ||\n // A trusted address cannot update a tree right after a precedent tree update otherwise it can de facto\n // validate a tree which has not passed the dispute period\n ((canUpdateMerkleRoot[msg.sender] != 1 || block.timestamp < endOfDisputePeriod) &&\n !core.isGovernorOrGuardian(msg.sender))\n ) revert NotTrusted();\n MerkleTree memory _lastTree = tree;\n tree = _tree;\n lastTree = _lastTree;\n\n uint48 _endOfPeriod = _endOfDisputePeriod(uint48(block.timestamp));\n endOfDisputePeriod = _endOfPeriod;\n emit TreeUpdated(_tree.merkleRoot, _tree.ipfsHash, _endOfPeriod);\n }\n\n /// @notice Freezes the Merkle tree update until the dispute is resolved\n /// @dev Requires a deposit of `disputeToken` that'll be slashed if the dispute is not accepted\n /// @dev It is only possible to create a dispute within `disputePeriod` after each tree update\n function disputeTree(string memory reason) external {\n if (disputer != address(0)) revert UnresolvedDispute();\n if (block.timestamp >= endOfDisputePeriod) revert InvalidDispute();\n IERC20(disputeToken).safeTransferFrom(msg.sender, address(this), disputeAmount);\n disputer = msg.sender;\n emit Disputed(reason);\n }\n\n /// @notice Resolve the ongoing dispute, if any\n /// @param valid Whether the dispute was valid\n function resolveDispute(bool valid) external onlyGovernorOrGuardian {\n if (disputer == address(0)) revert NoDispute();\n if (valid) {\n IERC20(disputeToken).safeTransfer(disputer, disputeAmount);\n // If a dispute is valid, the contract falls back to the last tree that was updated\n _revokeTree();\n } else {\n IERC20(disputeToken).safeTransfer(msg.sender, disputeAmount);\n endOfDisputePeriod = _endOfDisputePeriod(uint48(block.timestamp));\n }\n disputer = address(0);\n emit DisputeResolved(valid);\n }\n\n /// @notice Allows the governor or the guardian of this contract to fallback to the last version of the tree\n /// immediately\n function revokeTree() external onlyGovernorOrGuardian {\n if (disputer != address(0)) revert UnresolvedDispute();\n _revokeTree();\n }\n\n /// @notice Toggles permissioned claiming for a given user\n function toggleOnlyOperatorCanClaim(address user) external onlyTrustedOrUser(user) {\n uint256 oldValue = onlyOperatorCanClaim[user];\n onlyOperatorCanClaim[user] = 1 - oldValue;\n emit OperatorClaimingToggled(user, oldValue == 0);\n }\n\n /// @notice Toggles whitelisting for a given user and a given operator\n function toggleOperator(address user, address operator) external onlyTrustedOrUser(user) {\n uint256 oldValue = operators[user][operator];\n operators[user][operator] = 1 - oldValue;\n emit OperatorToggled(user, operator, oldValue == 0);\n }\n\n /// @notice Recovers any ERC20 token\n function recoverERC20(address tokenAddress, address to, uint256 amountToRecover) external onlyGovernorOrGuardian {\n IERC20(tokenAddress).safeTransfer(to, amountToRecover);\n emit Recovered(tokenAddress, to, amountToRecover);\n }\n\n /// @notice Sets the dispute period after which a tree update becomes effective\n function setDisputePeriod(uint48 _disputePeriod) external onlyGovernorOrGuardian {\n disputePeriod = uint48(_disputePeriod);\n emit DisputePeriodUpdated(_disputePeriod);\n }\n\n /// @notice Sets the token used as a caution during disputes\n function setDisputeToken(IERC20 _disputeToken) external onlyGovernorOrGuardian {\n if (disputer != address(0)) revert UnresolvedDispute();\n disputeToken = _disputeToken;\n emit DisputeTokenUpdated(address(_disputeToken));\n }\n\n /// @notice Sets the amount of `disputeToken` used as a caution during disputes\n function setDisputeAmount(uint256 _disputeAmount) external onlyGovernorOrGuardian {\n if (disputer != address(0)) revert UnresolvedDispute();\n disputeAmount = _disputeAmount;\n emit DisputeAmountUpdated(_disputeAmount);\n }\n\n // ============================= INTERNAL FUNCTIONS ============================\n\n /// @notice Fallback to the last version of the tree\n function _revokeTree() internal {\n MerkleTree memory _tree = lastTree;\n endOfDisputePeriod = 0;\n tree = _tree;\n emit Revoked();\n emit TreeUpdated(\n _tree.merkleRoot,\n _tree.ipfsHash,\n (uint48(block.timestamp) / _EPOCH_DURATION) * (_EPOCH_DURATION) // Last hour\n );\n }\n\n /// @notice Returns the end of the dispute period\n /// @dev treeUpdate is rounded up to next hour and then `disputePeriod` hours are added\n function _endOfDisputePeriod(uint48 treeUpdate) internal view returns (uint48) {\n return ((treeUpdate - 1) / _EPOCH_DURATION + 1 + disputePeriod) * (_EPOCH_DURATION);\n }\n\n /// @notice Checks the validity of a proof\n /// @param leaf Hashed leaf data, the starting point of the proof\n /// @param proof Array of hashes forming a hash chain from leaf to root\n /// @return true If proof is correct, else false\n function _verifyProof(bytes32 leaf, bytes32[] memory proof) internal view returns (bool) {\n bytes32 currentHash = leaf;\n uint256 proofLength = proof.length;\n for (uint256 i; i < proofLength; ) {\n if (currentHash < proof[i]) {\n currentHash = keccak256(abi.encode(currentHash, proof[i]));\n } else {\n currentHash = keccak256(abi.encode(proof[i], currentHash));\n }\n unchecked {\n ++i;\n }\n }\n bytes32 root = getMerkleRoot();\n if (root == bytes32(0)) revert InvalidUninitializedRoot();\n return currentHash == root;\n }\n}\n" + }, + "contracts/DistributionCreator.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\n/*\n * █ \n ***** ▓▓▓ \n * ▓▓▓▓▓▓▓ \n * ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓ \n ***** //////// ▓▓▓▓▓▓▓ \n * ///////////// ▓▓▓ \n ▓▓ ////////////////// █ ▓▓ \n ▓▓ ▓▓ /////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓ \n ▓▓ ,////////////////////////////////////// ▓▓ ▓▓ \n ▓▓ ////////////////////////////////////////// ▓▓ \n ▓▓ //////////////////////▓▓▓▓///////////////////// \n ,//////////////////////////////////////////////////// \n .////////////////////////////////////////////////////////// \n .//////////////////////////██.,//////////////////////////█ \n .//////////////////////████..,./////////////////////██ \n ...////////////////███████.....,.////////////////███ \n ,.,////////////████████ ........,///////////████ \n .,.,//////█████████ ,.......///////████ \n ,..//████████ ........./████ \n ..,██████ .....,███ \n .██ ,.,█ \n \n \n \n ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ \n ▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓ \n ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓ \n ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ \n*/\n\npragma solidity ^0.8.17;\n\nimport { ReentrancyGuardUpgradeable } from \"@openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol\";\nimport { IERC20, IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { ECDSA } from \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport { SignatureChecker } from \"@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol\";\n\nimport { IUniswapV3Pool } from \"./interfaces/external/uniswap/IUniswapV3Pool.sol\";\n\nimport \"./utils/UUPSHelper.sol\";\nimport { CampaignParameters } from \"./struct/CampaignParameters.sol\";\nimport { DistributionParameters } from \"./struct/DistributionParameters.sol\";\nimport { RewardTokenAmounts } from \"./struct/RewardTokenAmounts.sol\";\n\n/// @title DistributionCreator\n/// @author Angle Labs, Inc.\n/// @notice Manages the distribution of rewards through the Merkl system\n/// @dev This contract is mostly a helper for APIs built on top of Merkl\n/// @dev This contract is an upgraded version and distinguishes two types of different rewards:\n/// - distributions: type of campaign for concentrated liquidity pools created before Feb 15 2024,\n/// now deprecated\n/// - campaigns: the new more global name to describe any reward program on top of Merkl\n//solhint-disable\ncontract DistributionCreator is UUPSHelper, ReentrancyGuardUpgradeable {\n using SafeERC20 for IERC20;\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n CONSTANTS / VARIABLES \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n uint32 public constant HOUR = 3600;\n\n /// @notice Base for fee computation\n uint256 public constant BASE_9 = 1e9;\n\n uint256 public immutable CHAIN_ID = block.chainid;\n\n /// @notice `Core` contract handling access control\n ICore public core;\n\n /// @notice Contract distributing rewards to users\n address public distributor;\n\n /// @notice Address to which fees are forwarded\n address public feeRecipient;\n\n /// @notice Value (in base 10**9) of the fees taken when creating a campaign\n uint256 public defaultFees;\n\n /// @notice Message that needs to be acknowledged by users creating a campaign\n string public message;\n\n /// @notice Hash of the message that needs to be signed\n bytes32 public messageHash;\n\n /// @notice List of all rewards distributed in the contract on campaigns created before mid Feb 2024\n /// for concentrated liquidity pools\n DistributionParameters[] public distributionList;\n\n /// @notice Maps an address to its fee rebate\n mapping(address => uint256) public feeRebate;\n\n /// @notice Maps a token to whether it is whitelisted or not. No fees are to be paid for incentives given\n /// on pools with whitelisted tokens\n mapping(address => uint256) public isWhitelistedToken;\n\n /// @notice Deprecated, kept for storage compatibility\n mapping(address => uint256) public _nonces;\n\n /// @notice Maps an address to the last valid hash signed\n mapping(address => bytes32) public userSignatures;\n\n /// @notice Maps a user to whether it is whitelisted for not signing\n mapping(address => uint256) public userSignatureWhitelist;\n\n /// @notice Maps a token to the minimum amount that must be sent per epoch for a distribution to be valid\n /// @dev If `rewardTokenMinAmounts[token] == 0`, then `token` cannot be used as a reward\n mapping(address => uint256) public rewardTokenMinAmounts;\n\n /// @notice List of all reward tokens that have at some point been accepted\n address[] public rewardTokens;\n\n /// @notice List of all rewards ever distributed or to be distributed in the contract\n /// @dev An attacker could try to populate this list. It shouldn't be an issue as only view functions\n /// iterate on it\n CampaignParameters[] public campaignList;\n\n /// @notice Maps a campaignId to the ID of the campaign in the campaign list + 1\n mapping(bytes32 => uint256) internal _campaignLookup;\n\n /// @notice Maps a campaign type to the fees for this specific campaign\n mapping(uint32 => uint256) public campaignSpecificFees;\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n EVENTS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n event DistributorUpdated(address indexed _distributor);\n event FeeRebateUpdated(address indexed user, uint256 userFeeRebate);\n event FeeRecipientUpdated(address indexed _feeRecipient);\n event FeesSet(uint256 _fees);\n event CampaignSpecificFeesSet(uint32 campaignType, uint256 _fees);\n event MessageUpdated(bytes32 _messageHash);\n event NewCampaign(CampaignParameters campaign);\n event NewDistribution(DistributionParameters distribution, address indexed sender);\n event RewardTokenMinimumAmountUpdated(address indexed token, uint256 amount);\n event TokenWhitelistToggled(address indexed token, uint256 toggleStatus);\n event UserSigned(bytes32 messageHash, address indexed user);\n event UserSigningWhitelistToggled(address indexed user, uint256 toggleStatus);\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n MODIFIERS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernorOrGuardian() {\n if (!core.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n _;\n }\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernor() {\n if (!core.isGovernor(msg.sender)) revert NotGovernor();\n _;\n }\n\n /// @notice Checks whether an address has signed the message or not\n modifier hasSigned() {\n if (\n userSignatureWhitelist[msg.sender] == 0 &&\n userSignatures[msg.sender] != messageHash &&\n userSignatureWhitelist[tx.origin] == 0 &&\n userSignatures[tx.origin] != messageHash\n ) revert NotSigned();\n _;\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n CONSTRUCTOR \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n function initialize(ICore _core, address _distributor, uint256 _fees) external initializer {\n if (address(_core) == address(0) || _distributor == address(0)) revert ZeroAddress();\n if (_fees >= BASE_9) revert InvalidParam();\n distributor = _distributor;\n core = _core;\n defaultFees = _fees;\n }\n\n constructor() initializer {}\n\n /// @inheritdoc UUPSUpgradeable\n function _authorizeUpgrade(address) internal view override onlyGovernorUpgrader(core) {}\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n USER FACING FUNCTIONS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Creates a `campaign` to incentivize a given pool for a specific period of time\n /// @return The campaignId of the new campaign\n /// @dev If the campaign is badly specified, it will not be handled by the campaign script and rewards may be lost\n /// @dev Reward tokens sent as part of campaigns must have been whitelisted before and amounts\n /// sent should be bigger than a minimum amount specific to each token\n /// @dev This function reverts if the sender has not accepted the terms and conditions\n function createCampaign(CampaignParameters memory newCampaign) external nonReentrant hasSigned returns (bytes32) {\n return _createCampaign(newCampaign);\n }\n\n /// @notice Same as the function above but for multiple campaigns at once\n /// @return List of all the campaign amounts actually deposited for each `campaign` in the `campaigns` list\n function createCampaigns(\n CampaignParameters[] memory campaigns\n ) external nonReentrant hasSigned returns (bytes32[] memory) {\n uint256 campaignsLength = campaigns.length;\n bytes32[] memory campaignIds = new bytes32[](campaignsLength);\n for (uint256 i; i < campaignsLength; ) {\n campaignIds[i] = _createCampaign(campaigns[i]);\n unchecked {\n ++i;\n }\n }\n return campaignIds;\n }\n\n /// @notice Allows a user to accept the conditions without signing the message\n /// @dev Users may either call `acceptConditions` here or `sign` the message\n function acceptConditions() external {\n userSignatureWhitelist[msg.sender] = 1;\n }\n\n /// @notice Checks whether the `msg.sender`'s `signature` is compatible with the message\n /// to sign and stores the signature\n /// @dev If you signed the message once, and the message has not been modified, then you do not\n /// need to sign again\n function sign(bytes calldata signature) external {\n _sign(signature);\n }\n\n /// @notice Combines signing the message and creating a campaign\n function signAndCreateCampaign(\n CampaignParameters memory newCampaign,\n bytes calldata signature\n ) external returns (bytes32) {\n _sign(signature);\n return _createCampaign(newCampaign);\n }\n\n /// @notice Creates a `distribution` to incentivize a given pool for a specific period of time\n function createDistribution(\n DistributionParameters memory newDistribution\n ) external nonReentrant hasSigned returns (uint256 distributionAmount) {\n return _createDistribution(newDistribution);\n }\n\n /// @notice Same as the function above but for multiple distributions at once\n function createDistributions(\n DistributionParameters[] memory distributions\n ) external nonReentrant hasSigned returns (uint256[] memory) {\n uint256 distributionsLength = distributions.length;\n uint256[] memory distributionAmounts = new uint256[](distributionsLength);\n for (uint256 i; i < distributionsLength; ) {\n distributionAmounts[i] = _createDistribution(distributions[i]);\n unchecked {\n ++i;\n }\n }\n return distributionAmounts;\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n GETTERS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Returns the distribution at a given index converted into a campaign\n function distribution(uint256 index) external view returns (CampaignParameters memory) {\n return _convertDistribution(distributionList[index]);\n }\n\n /// @notice Returns the index of a campaign in the campaign list\n function campaignLookup(bytes32 _campaignId) public view returns (uint256) {\n uint256 index = _campaignLookup[_campaignId];\n if (index == 0) revert CampaignDoesNotExist();\n return index - 1;\n }\n\n /// @notice Returns the campaign parameters of a given campaignId\n function campaign(bytes32 _campaignId) external view returns (CampaignParameters memory) {\n return campaignList[campaignLookup(_campaignId)];\n }\n\n /// @notice Returns the campaign ID for a given campaign\n /// @dev The campaign ID is computed as the hash of the following parameters:\n /// - `campaign.creator`\n /// - `campaign.rewardToken`\n /// - `campaign.campaignType`\n /// - `campaign.startTimestamp`\n /// - `campaign.duration`\n /// - `campaign.campaignData`\n /// This prevents the creation by the same account of two campaigns with the same parameters\n /// which is not a huge issue\n function campaignId(CampaignParameters memory campaignData) public view returns (bytes32) {\n return\n bytes32(\n keccak256(\n abi.encodePacked(\n CHAIN_ID,\n campaignData.creator,\n campaignData.rewardToken,\n campaignData.campaignType,\n campaignData.startTimestamp,\n campaignData.duration,\n campaignData.campaignData\n )\n )\n );\n }\n\n /// @notice Returns the list of all the reward tokens supported as well as their minimum amounts\n /// @dev Not to be queried on-chain and hence not optimized for gas consumption\n function getValidRewardTokens() external view returns (RewardTokenAmounts[] memory) {\n (RewardTokenAmounts[] memory validRewardTokens, ) = _getValidRewardTokens(0, type(uint32).max);\n return validRewardTokens;\n }\n\n /// @dev Not to be queried on-chain and hence not optimized for gas consumption\n function getValidRewardTokens(\n uint32 skip,\n uint32 first\n ) external view returns (RewardTokenAmounts[] memory, uint256) {\n return _getValidRewardTokens(skip, first);\n }\n\n /// @notice Gets all the campaigns which were live at some point between `start` and `end` timestamp\n /// @param skip Disregard distibutions with a global index lower than `skip`\n /// @param first Limit the length of the returned array to `first`\n /// @return searchCampaigns Eligible campaigns\n /// @return lastIndexCampaign Index of the last campaign assessed in the list of all campaigns\n /// @dev For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexCampaign`\n /// @dev Not to be queried on-chain and hence not optimized for gas consumption\n function getCampaignsBetween(\n uint32 start,\n uint32 end,\n uint32 skip,\n uint32 first\n ) external view returns (CampaignParameters[] memory, uint256 lastIndexCampaign) {\n return _getCampaignsBetween(start, end, skip, first);\n }\n\n /// @notice Gets all the distributions which were live at some point between `start` and `end` timestamp\n /// @param skip Disregard distibutions with a global index lower than `skip`\n /// @param first Limit the length of the returned array to `first`\n /// @return searchDistributions Eligible distributions\n /// @return lastIndexDistribution Index of the last distribution assessed in the list of all distributions\n /// @dev For pagniation purpose, in case of out of gas, you can call back the same function but with `skip` set to `lastIndexDistribution`\n /// @dev Not to be queried on-chain and hence not optimized for gas consumption\n function getDistributionsBetweenEpochs(\n uint32 epochStart,\n uint32 epochEnd,\n uint32 skip,\n uint32 first\n ) external view returns (DistributionParameters[] memory, uint256 lastIndexDistribution) {\n return _getDistributionsBetweenEpochs(_getRoundedEpoch(epochStart), _getRoundedEpoch(epochEnd), skip, first);\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n GOVERNANCE FUNCTIONS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Sets a new `distributor` to which rewards should be distributed\n function setNewDistributor(address _distributor) external onlyGovernor {\n if (_distributor == address(0)) revert InvalidParam();\n distributor = _distributor;\n emit DistributorUpdated(_distributor);\n }\n\n /// @notice Sets the defaultFees on deposit\n function setFees(uint256 _defaultFees) external onlyGovernor {\n if (_defaultFees >= BASE_9) revert InvalidParam();\n defaultFees = _defaultFees;\n emit FeesSet(_defaultFees);\n }\n\n /// @notice Sets the fees specific for a campaign\n /// @dev To waive the fees for a campaign, set its fees to 1\n function setCampaignFees(uint32 campaignType, uint256 _fees) external onlyGovernorOrGuardian {\n if (_fees >= BASE_9) revert InvalidParam();\n campaignSpecificFees[campaignType] = _fees;\n emit CampaignSpecificFeesSet(campaignType, _fees);\n }\n\n /// @notice Toggles the fee whitelist for `token`\n function toggleTokenWhitelist(address token) external onlyGovernorOrGuardian {\n uint256 toggleStatus = 1 - isWhitelistedToken[token];\n isWhitelistedToken[token] = toggleStatus;\n emit TokenWhitelistToggled(token, toggleStatus);\n }\n\n /// @notice Recovers fees accrued on the contract for a list of `tokens`\n function recoverFees(IERC20[] calldata tokens, address to) external onlyGovernor {\n uint256 tokensLength = tokens.length;\n for (uint256 i; i < tokensLength; ) {\n tokens[i].safeTransfer(to, tokens[i].balanceOf(address(this)));\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Sets fee rebates for a given user\n function setUserFeeRebate(address user, uint256 userFeeRebate) external onlyGovernorOrGuardian {\n feeRebate[user] = userFeeRebate;\n emit FeeRebateUpdated(user, userFeeRebate);\n }\n\n /// @notice Sets the minimum amounts per distribution epoch for different reward tokens\n function setRewardTokenMinAmounts(\n address[] calldata tokens,\n uint256[] calldata amounts\n ) external onlyGovernorOrGuardian {\n uint256 tokensLength = tokens.length;\n if (tokensLength != amounts.length) revert InvalidLengths();\n for (uint256 i; i < tokensLength; ++i) {\n uint256 amount = amounts[i];\n // Basic logic check to make sure there are no duplicates in the `rewardTokens` table. If a token is\n // removed then re-added, it will appear as a duplicate in the list\n if (amount > 0 && rewardTokenMinAmounts[tokens[i]] == 0) rewardTokens.push(tokens[i]);\n rewardTokenMinAmounts[tokens[i]] = amount;\n emit RewardTokenMinimumAmountUpdated(tokens[i], amount);\n }\n }\n\n /// @notice Sets a new address to receive fees\n function setFeeRecipient(address _feeRecipient) external onlyGovernor {\n feeRecipient = _feeRecipient;\n emit FeeRecipientUpdated(_feeRecipient);\n }\n\n /// @notice Sets the message that needs to be signed by users before posting rewards\n function setMessage(string memory _message) external onlyGovernor {\n message = _message;\n bytes32 _messageHash = ECDSA.toEthSignedMessageHash(bytes(_message));\n messageHash = _messageHash;\n emit MessageUpdated(_messageHash);\n }\n\n /// @notice Toggles the whitelist status for `user` when it comes to signing messages before depositing rewards.\n function toggleSigningWhitelist(address user) external onlyGovernorOrGuardian {\n uint256 whitelistStatus = 1 - userSignatureWhitelist[user];\n userSignatureWhitelist[user] = whitelistStatus;\n emit UserSigningWhitelistToggled(user, whitelistStatus);\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n INTERNAL \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Internal version of `createCampaign`\n function _createCampaign(CampaignParameters memory newCampaign) internal returns (bytes32) {\n uint256 rewardTokenMinAmount = rewardTokenMinAmounts[newCampaign.rewardToken];\n // if epoch parameters lead to a past campaign\n if (newCampaign.startTimestamp < block.timestamp) revert CampaignSouldStartInFuture();\n // if the campaign doesn't last at least one hour\n if (newCampaign.duration < HOUR) revert CampaignDurationBelowHour();\n // if the reward token is not whitelisted as an incentive token\n if (rewardTokenMinAmount == 0) revert CampaignRewardTokenNotWhitelisted();\n // if the amount distributed is too small with respect to what is allowed\n if ((newCampaign.amount * HOUR) / newCampaign.duration < rewardTokenMinAmount) revert CampaignRewardTooLow();\n\n if (newCampaign.creator == address(0)) newCampaign.creator = msg.sender;\n\n // Computing fees: these are waived for whitelisted addresses and if there is a whitelisted token in a pool\n uint256 _fees = campaignSpecificFees[newCampaign.campaignType];\n if (_fees == 1) _fees = 0;\n else if (_fees == 0) _fees = defaultFees;\n uint256 campaignAmountMinusFees = _computeFees(_fees, newCampaign.amount, newCampaign.rewardToken);\n newCampaign.amount = campaignAmountMinusFees;\n\n newCampaign.campaignId = campaignId(newCampaign);\n\n if (_campaignLookup[newCampaign.campaignId] != 0) revert CampaignAlreadyExists();\n _campaignLookup[newCampaign.campaignId] = campaignList.length + 1;\n campaignList.push(newCampaign);\n emit NewCampaign(newCampaign);\n\n return newCampaign.campaignId;\n }\n\n /// @notice Creates a distribution from a deprecated distribution type\n function _createDistribution(DistributionParameters memory newDistribution) internal returns (uint256) {\n _createCampaign(_convertDistribution(newDistribution));\n // Not gas efficient but deprecated\n return campaignList[campaignList.length - 1].amount;\n }\n\n /// @notice Converts the deprecated distribution type into a campaign\n function _convertDistribution(\n DistributionParameters memory distributionToConvert\n ) internal view returns (CampaignParameters memory) {\n uint256 wrapperLength = distributionToConvert.wrapperTypes.length;\n address[] memory whitelist = new address[](wrapperLength);\n address[] memory blacklist = new address[](wrapperLength);\n uint256 whitelistLength;\n uint256 blacklistLength;\n for (uint256 k = 0; k < wrapperLength; k++) {\n if (distributionToConvert.wrapperTypes[k] == 0) {\n whitelist[whitelistLength] = (distributionToConvert.positionWrappers[k]);\n whitelistLength += 1;\n }\n if (distributionToConvert.wrapperTypes[k] == 3) {\n blacklist[blacklistLength] = (distributionToConvert.positionWrappers[k]);\n blacklistLength += 1;\n }\n }\n\n assembly {\n mstore(whitelist, whitelistLength)\n mstore(blacklist, blacklistLength)\n }\n\n return\n CampaignParameters({\n campaignId: distributionToConvert.rewardId,\n creator: msg.sender,\n rewardToken: distributionToConvert.rewardToken,\n amount: distributionToConvert.amount,\n campaignType: 2,\n startTimestamp: distributionToConvert.epochStart,\n duration: distributionToConvert.numEpoch * HOUR,\n campaignData: abi.encode(\n distributionToConvert.uniV3Pool,\n distributionToConvert.propFees, // eg. 6000\n distributionToConvert.propToken0, // eg. 3000\n distributionToConvert.propToken1, // eg. 1000\n distributionToConvert.isOutOfRangeIncentivized, // eg. 0\n distributionToConvert.boostingAddress, // eg. NULL_ADDRESS\n distributionToConvert.boostedReward, // eg. 0\n whitelist, // eg. []\n blacklist, // eg. []\n \"0x\"\n )\n });\n }\n\n /// @notice Computes the fees to be taken on a campaign and transfers them to the fee recipient\n function _computeFees(\n uint256 baseFeesValue,\n uint256 distributionAmount,\n address rewardToken\n ) internal returns (uint256 distributionAmountMinusFees) {\n uint256 _fees = (baseFeesValue * (BASE_9 - feeRebate[msg.sender])) / BASE_9;\n distributionAmountMinusFees = distributionAmount;\n if (_fees != 0) {\n distributionAmountMinusFees = (distributionAmount * (BASE_9 - _fees)) / BASE_9;\n address _feeRecipient = feeRecipient;\n _feeRecipient = _feeRecipient == address(0) ? address(this) : _feeRecipient;\n IERC20(rewardToken).safeTransferFrom(\n msg.sender,\n _feeRecipient,\n distributionAmount - distributionAmountMinusFees\n );\n }\n IERC20(rewardToken).safeTransferFrom(msg.sender, distributor, distributionAmountMinusFees);\n }\n\n /// @notice Internal version of the `sign` function\n function _sign(bytes calldata signature) internal {\n bytes32 _messageHash = messageHash;\n if (!SignatureChecker.isValidSignatureNow(msg.sender, _messageHash, signature)) revert InvalidSignature();\n userSignatures[msg.sender] = _messageHash;\n emit UserSigned(_messageHash, msg.sender);\n }\n\n /// @notice Rounds an `epoch` timestamp to the start of the corresponding period\n function _getRoundedEpoch(uint32 epoch) internal pure returns (uint32) {\n return (epoch / HOUR) * HOUR;\n }\n\n /// @notice Internal version of `getCampaignsBetween`\n function _getCampaignsBetween(\n uint32 start,\n uint32 end,\n uint32 skip,\n uint32 first\n ) internal view returns (CampaignParameters[] memory, uint256) {\n uint256 length;\n uint256 campaignListLength = campaignList.length;\n uint256 returnSize = first > campaignListLength ? campaignListLength : first;\n CampaignParameters[] memory activeRewards = new CampaignParameters[](returnSize);\n uint32 i = skip;\n while (i < campaignListLength) {\n CampaignParameters memory campaignToProcess = campaignList[i];\n if (\n campaignToProcess.startTimestamp + campaignToProcess.duration > start &&\n campaignToProcess.startTimestamp < end\n ) {\n activeRewards[length] = campaignToProcess;\n length += 1;\n }\n unchecked {\n ++i;\n }\n if (length == returnSize) break;\n }\n assembly {\n mstore(activeRewards, length)\n }\n return (activeRewards, i);\n }\n\n /// @notice Internal version of `getDistributionsBetweenEpochs`\n function _getDistributionsBetweenEpochs(\n uint32 epochStart,\n uint32 epochEnd,\n uint32 skip,\n uint32 first\n ) internal view returns (DistributionParameters[] memory, uint256) {\n uint256 length;\n uint256 distributionListLength = distributionList.length;\n uint256 returnSize = first > distributionListLength ? distributionListLength : first;\n DistributionParameters[] memory activeRewards = new DistributionParameters[](returnSize);\n uint32 i = skip;\n while (i < distributionListLength) {\n DistributionParameters memory d = distributionList[i];\n if (d.epochStart + d.numEpoch * HOUR > epochStart && d.epochStart < epochEnd) {\n activeRewards[length] = d;\n length += 1;\n }\n unchecked {\n ++i;\n }\n if (length == returnSize) break;\n }\n assembly {\n mstore(activeRewards, length)\n }\n return (activeRewards, i);\n }\n\n /// @notice Builds the list of valid reward tokens\n function _getValidRewardTokens(\n uint32 skip,\n uint32 first\n ) internal view returns (RewardTokenAmounts[] memory, uint256) {\n uint256 length;\n uint256 rewardTokenListLength = rewardTokens.length;\n uint256 returnSize = first > rewardTokenListLength ? rewardTokenListLength : first;\n RewardTokenAmounts[] memory validRewardTokens = new RewardTokenAmounts[](returnSize);\n uint32 i = skip;\n while (i < rewardTokenListLength) {\n address token = rewardTokens[i];\n uint256 minAmount = rewardTokenMinAmounts[token];\n if (minAmount > 0) {\n validRewardTokens[length] = RewardTokenAmounts(token, minAmount);\n length += 1;\n }\n unchecked {\n ++i;\n }\n if (length == returnSize) break;\n }\n assembly {\n mstore(validRewardTokens, length)\n }\n return (validRewardTokens, i);\n }\n\n /**\n * @dev This empty reserved space is put in place to allow future versions to add new\n * variables without shifting down storage in the inheritance chain.\n * See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps\n */\n uint256[33] private __gap;\n}\n" + }, + "contracts/Distributor.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\n/*\n * █ \n ***** ▓▓▓ \n * ▓▓▓▓▓▓▓ \n * ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓ \n ***** //////// ▓▓▓▓▓▓▓ \n * ///////////// ▓▓▓ \n ▓▓ ////////////////// █ ▓▓ \n ▓▓ ▓▓ /////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓ \n ▓▓ ,////////////////////////////////////// ▓▓ ▓▓ \n ▓▓ ////////////////////////////////////////// ▓▓ \n ▓▓ //////////////////////▓▓▓▓///////////////////// \n ,//////////////////////////////////////////////////// \n .////////////////////////////////////////////////////////// \n .//////////////////////////██.,//////////////////////////█ \n .//////////////////////████..,./////////////////////██ \n ...////////////////███████.....,.////////////////███ \n ,.,////////////████████ ........,///////////████ \n .,.,//////█████████ ,.......///////████ \n ,..//████████ ........./████ \n ..,██████ .....,███ \n .██ ,.,█ \n \n \n \n ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ \n ▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓ \n ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓ \n ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ \n*/\n\npragma solidity ^0.8.17;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { SafeCast } from \"@openzeppelin/contracts/utils/math/SafeCast.sol\";\n\nimport \"./utils/UUPSHelper.sol\";\n\nstruct MerkleTree {\n // Root of a Merkle tree which leaves are `(address user, address token, uint amount)`\n // representing an amount of tokens accumulated by `user`.\n // The Merkle tree is assumed to have only increasing amounts: that is to say if a user can claim 1,\n // then after the amount associated in the Merkle tree for this token should be x > 1\n bytes32 merkleRoot;\n // Ipfs hash of the tree data\n bytes32 ipfsHash;\n}\n\nstruct Claim {\n uint208 amount;\n uint48 timestamp;\n bytes32 merkleRoot;\n}\n\n/// @title Distributor\n/// @notice Allows to claim rewards distributed to them through Merkl\n/// @author Angle Labs. Inc\ncontract Distributor is UUPSHelper {\n using SafeERC20 for IERC20;\n\n /// @notice Epoch duration\n uint32 internal constant _EPOCH_DURATION = 3600;\n\n // ================================= VARIABLES =================================\n\n /// @notice Tree of claimable tokens through this contract\n MerkleTree public tree;\n\n /// @notice Tree that was in place in the contract before the last `tree` update\n MerkleTree public lastTree;\n\n /// @notice Token to deposit to freeze the roots update\n IERC20 public disputeToken;\n\n /// @notice `Core` contract handling access control\n ICore public core;\n\n /// @notice Address which created the dispute\n /// @dev Used to store if there is an ongoing dispute\n address public disputer;\n\n /// @notice When the current tree will become valid\n uint48 public endOfDisputePeriod;\n\n /// @notice Time after which a change in a tree becomes effective, in EPOCH_DURATION\n uint48 public disputePeriod;\n\n /// @notice Amount to deposit to freeze the roots update\n uint256 public disputeAmount;\n\n /// @notice Mapping user -> token -> amount to track claimed amounts\n mapping(address => mapping(address => Claim)) public claimed;\n\n /// @notice Trusted EOAs to update the Merkle root\n mapping(address => uint256) public canUpdateMerkleRoot;\n\n /// @notice Whether or not to disable permissionless claiming\n mapping(address => uint256) public onlyOperatorCanClaim;\n\n /// @notice user -> operator -> authorisation to claim\n mapping(address => mapping(address => uint256)) public operators;\n\n uint256[38] private __gap;\n\n // =================================== EVENTS ==================================\n\n event Claimed(address indexed user, address indexed token, uint256 amount);\n event DisputeAmountUpdated(uint256 _disputeAmount);\n event Disputed(string reason);\n event DisputePeriodUpdated(uint48 _disputePeriod);\n event DisputeResolved(bool valid);\n event DisputeTokenUpdated(address indexed _disputeToken);\n event OperatorClaimingToggled(address indexed user, bool isEnabled);\n event OperatorToggled(address indexed user, address indexed operator, bool isWhitelisted);\n event Recovered(address indexed token, address indexed to, uint256 amount);\n event Revoked(); // With this event an indexer could maintain a table (timestamp, merkleRootUpdate)\n event TreeUpdated(bytes32 merkleRoot, bytes32 ipfsHash, uint48 endOfDisputePeriod);\n event TrustedToggled(address indexed eoa, bool trust);\n\n // ================================= MODIFIERS =================================\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernorOrGuardian() {\n if (!core.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n _;\n }\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernor() {\n if (!core.isGovernor(msg.sender)) revert NotGovernor();\n _;\n }\n\n /// @notice Checks whether the `msg.sender` is the `user` address or is a trusted address\n modifier onlyTrustedOrUser(address user) {\n if (user != msg.sender && canUpdateMerkleRoot[msg.sender] != 1 && !core.isGovernorOrGuardian(msg.sender))\n revert NotTrusted();\n _;\n }\n\n // ================================ CONSTRUCTOR ================================\n\n constructor() initializer {}\n\n function initialize(ICore _core) external initializer {\n if (address(_core) == address(0)) revert ZeroAddress();\n core = _core;\n }\n\n /// @inheritdoc UUPSUpgradeable\n function _authorizeUpgrade(address) internal view override onlyGovernorUpgrader(core) {}\n\n // =============================== MAIN FUNCTION ===============================\n\n /// @notice Claims rewards for a given set of users\n /// @dev Anyone may call this function for anyone else, funds go to destination regardless, it's just a question of\n /// who provides the proof and pays the gas: `msg.sender` is used only for addresses that require a trusted operator\n /// @param users Recipient of tokens\n /// @param tokens ERC20 claimed\n /// @param amounts Amount of tokens that will be sent to the corresponding users\n /// @param proofs Array of hashes bridging from a leaf `(hash of user | token | amount)` to the Merkle root\n function claim(\n address[] calldata users,\n address[] calldata tokens,\n uint256[] calldata amounts,\n bytes32[][] calldata proofs\n ) external {\n uint256 usersLength = users.length;\n if (\n usersLength == 0 ||\n usersLength != tokens.length ||\n usersLength != amounts.length ||\n usersLength != proofs.length\n ) revert InvalidLengths();\n\n for (uint256 i; i < usersLength; ) {\n address user = users[i];\n address token = tokens[i];\n uint256 amount = amounts[i];\n\n // Checking if only an approved operator can claim for `user`\n if (onlyOperatorCanClaim[user] == 1 && operators[user][msg.sender] == 0) revert NotWhitelisted();\n\n // Verifying proof\n bytes32 leaf = keccak256(abi.encode(user, token, amount));\n if (!_verifyProof(leaf, proofs[i])) revert InvalidProof();\n\n // Closing reentrancy gate here\n uint256 toSend = amount - claimed[user][token].amount;\n claimed[user][token] = Claim(SafeCast.toUint208(amount), uint48(block.timestamp), getMerkleRoot());\n\n IERC20(token).safeTransfer(user, toSend);\n emit Claimed(user, token, toSend);\n unchecked {\n ++i;\n }\n }\n }\n\n /// @notice Returns the MerkleRoot that is currently live for the contract\n function getMerkleRoot() public view returns (bytes32) {\n if (block.timestamp >= endOfDisputePeriod && disputer == address(0)) return tree.merkleRoot;\n else return lastTree.merkleRoot;\n }\n\n // ============================ GOVERNANCE FUNCTIONS ===========================\n\n /// @notice Adds or removes EOAs which are trusted to update the Merkle root\n function toggleTrusted(address eoa) external onlyGovernor {\n uint256 trustedStatus = 1 - canUpdateMerkleRoot[eoa];\n canUpdateMerkleRoot[eoa] = trustedStatus;\n emit TrustedToggled(eoa, trustedStatus == 1);\n }\n\n /// @notice Updates Merkle Tree\n function updateTree(MerkleTree calldata _tree) external {\n if (\n disputer != address(0) ||\n // A trusted address cannot update a tree right after a precedent tree update otherwise it can de facto\n // validate a tree which has not passed the dispute period\n ((canUpdateMerkleRoot[msg.sender] != 1 || block.timestamp < endOfDisputePeriod) &&\n !core.isGovernor(msg.sender))\n ) revert NotTrusted();\n MerkleTree memory _lastTree = tree;\n tree = _tree;\n lastTree = _lastTree;\n\n uint48 _endOfPeriod = _endOfDisputePeriod(uint48(block.timestamp));\n endOfDisputePeriod = _endOfPeriod;\n emit TreeUpdated(_tree.merkleRoot, _tree.ipfsHash, _endOfPeriod);\n }\n\n /// @notice Freezes the Merkle tree update until the dispute is resolved\n /// @dev Requires a deposit of `disputeToken` that'll be slashed if the dispute is not accepted\n /// @dev It is only possible to create a dispute within `disputePeriod` after each tree update\n function disputeTree(string memory reason) external {\n if (disputer != address(0)) revert UnresolvedDispute();\n if (block.timestamp >= endOfDisputePeriod) revert InvalidDispute();\n IERC20(disputeToken).safeTransferFrom(msg.sender, address(this), disputeAmount);\n disputer = msg.sender;\n emit Disputed(reason);\n }\n\n /// @notice Resolve the ongoing dispute, if any\n /// @param valid Whether the dispute was valid\n function resolveDispute(bool valid) external onlyGovernorOrGuardian {\n if (disputer == address(0)) revert NoDispute();\n if (valid) {\n IERC20(disputeToken).safeTransfer(disputer, disputeAmount);\n // If a dispute is valid, the contract falls back to the last tree that was updated\n _revokeTree();\n } else {\n IERC20(disputeToken).safeTransfer(msg.sender, disputeAmount);\n endOfDisputePeriod = _endOfDisputePeriod(uint48(block.timestamp));\n }\n disputer = address(0);\n emit DisputeResolved(valid);\n }\n\n /// @notice Allows the governor or the guardian of this contract to fallback to the last version of the tree\n /// immediately\n function revokeTree() external onlyGovernorOrGuardian {\n if (disputer != address(0)) revert UnresolvedDispute();\n _revokeTree();\n }\n\n /// @notice Toggles permissioned claiming for a given user\n function toggleOnlyOperatorCanClaim(address user) external onlyTrustedOrUser(user) {\n uint256 oldValue = onlyOperatorCanClaim[user];\n onlyOperatorCanClaim[user] = 1 - oldValue;\n emit OperatorClaimingToggled(user, oldValue == 0);\n }\n\n /// @notice Toggles whitelisting for a given user and a given operator\n function toggleOperator(address user, address operator) external onlyTrustedOrUser(user) {\n uint256 oldValue = operators[user][operator];\n operators[user][operator] = 1 - oldValue;\n emit OperatorToggled(user, operator, oldValue == 0);\n }\n\n /// @notice Recovers any ERC20 token\n function recoverERC20(address tokenAddress, address to, uint256 amountToRecover) external onlyGovernor {\n IERC20(tokenAddress).safeTransfer(to, amountToRecover);\n emit Recovered(tokenAddress, to, amountToRecover);\n }\n\n /// @notice Sets the dispute period after which a tree update becomes effective\n function setDisputePeriod(uint48 _disputePeriod) external onlyGovernor {\n disputePeriod = uint48(_disputePeriod);\n emit DisputePeriodUpdated(_disputePeriod);\n }\n\n /// @notice Sets the token used as a caution during disputes\n function setDisputeToken(IERC20 _disputeToken) external onlyGovernor {\n if (disputer != address(0)) revert UnresolvedDispute();\n disputeToken = _disputeToken;\n emit DisputeTokenUpdated(address(_disputeToken));\n }\n\n /// @notice Sets the amount of `disputeToken` used as a caution during disputes\n function setDisputeAmount(uint256 _disputeAmount) external onlyGovernor {\n if (disputer != address(0)) revert UnresolvedDispute();\n disputeAmount = _disputeAmount;\n emit DisputeAmountUpdated(_disputeAmount);\n }\n\n // ============================= INTERNAL FUNCTIONS ============================\n\n /// @notice Fallback to the last version of the tree\n function _revokeTree() internal {\n MerkleTree memory _tree = lastTree;\n endOfDisputePeriod = 0;\n tree = _tree;\n emit Revoked();\n emit TreeUpdated(\n _tree.merkleRoot,\n _tree.ipfsHash,\n (uint48(block.timestamp) / _EPOCH_DURATION) * (_EPOCH_DURATION) // Last hour\n );\n }\n\n /// @notice Returns the end of the dispute period\n /// @dev treeUpdate is rounded up to next hour and then `disputePeriod` hours are added\n function _endOfDisputePeriod(uint48 treeUpdate) internal view returns (uint48) {\n return ((treeUpdate - 1) / _EPOCH_DURATION + 1 + disputePeriod) * (_EPOCH_DURATION);\n }\n\n /// @notice Checks the validity of a proof\n /// @param leaf Hashed leaf data, the starting point of the proof\n /// @param proof Array of hashes forming a hash chain from leaf to root\n /// @return true If proof is correct, else false\n function _verifyProof(bytes32 leaf, bytes32[] memory proof) internal view returns (bool) {\n bytes32 currentHash = leaf;\n uint256 proofLength = proof.length;\n for (uint256 i; i < proofLength; ) {\n if (currentHash < proof[i]) {\n currentHash = keccak256(abi.encode(currentHash, proof[i]));\n } else {\n currentHash = keccak256(abi.encode(proof[i], currentHash));\n }\n unchecked {\n ++i;\n }\n }\n bytes32 root = getMerkleRoot();\n if (root == bytes32(0)) revert InvalidUninitializedRoot();\n return currentHash == root;\n }\n}\n" + }, + "contracts/interfaces/external/uniswap/IUniswapV3Pool.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity >=0.5.0;\n\n/// @title Pool state that never changes\n/// @notice These parameters are fixed for a pool forever, i.e., the methods will always return the same values\ninterface IUniswapV3Pool {\n /// @notice The first of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token0() external view returns (address);\n\n /// @notice The second of the two tokens of the pool, sorted by address\n /// @return The token contract address\n function token1() external view returns (address);\n\n /// @notice The pool's fee in hundredths of a bip, i.e. 1e-6\n /// @return The fee\n function fee() external view returns (uint24);\n}\n" + }, + "contracts/interfaces/ICore.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.17;\n\n/// @title ICore\n/// @author Angle Labs, Inc.\n/// @notice Interface for the `Core` contracts of smart contract modules used in Angle Labs contracts\ninterface ICore {\n /// @notice Checks whether an address is governor\n /// @param admin Address to check\n /// @return Whether the address has the `GOVERNOR_ROLE` or not\n function isGovernor(address admin) external view returns (bool);\n\n /// @notice Checks whether an address is a governor or a guardian of a module\n /// @param admin Address to check\n /// @return Whether the address has the `GUARDIAN_ROLE` or not\n /// @dev Governance should make sure when adding a governor to also give this governor the guardian\n /// role by calling the `addGovernor` function\n function isGovernorOrGuardian(address admin) external view returns (bool);\n}\n" + }, + "contracts/middleman/MerklFraxIncentivizationHandler.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.17;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"../DistributionCreator.sol\";\n\n/// @title MerklFraxIncentivizationHandler\n/// @author Angle Labs, Inc.\n/// @notice Manages the transfer of rewards sent by FRAX `IncentivizingLiquidityAmo` contract to the\n/// `DistributionCreator` contract\n/// @dev This contract is built under the assumption that the `DistributionCreator` contract has already whitelisted\n/// this contract for it to distribute rewards without having to sign a message\ncontract MerklFraxIncentivizationHandler is Ownable {\n using SafeERC20 for IERC20;\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n PARAMETERS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n address public operatorAddress;\n\n /// @notice Maps a gauge, incentive token pair to its reward parameters\n mapping(address => mapping(address => DistributionParameters)) public gaugeParams;\n\n /// @notice Maps an incentive token to a set of (pool, leftovers)\n /// @dev Merkl imposes that each token distribution comes with a minimum amount per hour\n /// We use this mapping to keep track of leftovers to be distributed during future distributions\n mapping(address => mapping(address => uint256)) public leftovers;\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n MODIFIER / EVENT \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n modifier onlyByOwnerOperator() {\n require(msg.sender == operatorAddress || msg.sender == owner(), \"Not owner or operator\");\n _;\n }\n\n event GaugeSet(address indexed gauge, address indexed incentiveTokenAddress);\n\n constructor(address _operatorAddress) Ownable() {\n operatorAddress = _operatorAddress;\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n REFERENCES \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Address of the Merkl contract managing rewards to be distributed\n /// @dev Address is the same across the different chains on which it is deployed\n function merklDistributionCreator() public view virtual returns (DistributionCreator) {\n return DistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);\n }\n\n /*//////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n EXTERNAL FUNCTIONS \n //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/\n\n /// @notice Specifies the reward distribution parameters for `poolAddress`\n function setGauge(\n address poolAddress,\n address incentiveTokenAddress,\n DistributionParameters memory params\n ) external onlyByOwnerOperator {\n if (poolAddress == address(0) || incentiveTokenAddress == address(0)) revert InvalidParams();\n gaugeParams[poolAddress][incentiveTokenAddress] = params;\n emit GaugeSet(poolAddress, incentiveTokenAddress);\n }\n\n /// @notice Sets the operator of the contract\n function setOperator(address _operatorAddress) external onlyByOwnerOperator {\n operatorAddress = _operatorAddress;\n }\n\n /// @notice Function called by FRAX contract to stream rewards to `poolAddress`\n /// @dev Params for the incentivization of the pool must have been set prior to any call for\n /// a `(poolAddress,incentiveTokenAddress)` pair\n function incentivizePool(\n address poolAddress,\n address,\n address,\n address incentiveTokenAddress,\n uint256,\n uint256 amount\n ) external {\n IERC20(incentiveTokenAddress).safeTransferFrom(msg.sender, address(this), amount);\n DistributionParameters memory params = gaugeParams[poolAddress][incentiveTokenAddress];\n if (params.uniV3Pool == address(0)) revert InvalidParams();\n DistributionCreator creator = merklDistributionCreator();\n // Minimum amount of incentive tokens to be distributed per hour\n uint256 minAmount = creator.rewardTokenMinAmounts(incentiveTokenAddress) * params.numEpoch;\n params.epochStart = uint32(block.timestamp);\n // Adding the leftover amounts to the total amount to be distributed\n uint256 leftover = leftovers[incentiveTokenAddress][poolAddress];\n amount += leftover;\n params.amount = amount;\n if (amount > 0) {\n if (amount > minAmount) {\n if (leftover > 0) leftovers[incentiveTokenAddress][poolAddress] = 0;\n _handleIncentiveTokenAllowance(IERC20(incentiveTokenAddress), address(creator), amount);\n merklDistributionCreator().createDistribution(params);\n } else {\n leftovers[incentiveTokenAddress][poolAddress] = amount;\n }\n }\n }\n\n /// @notice Restores the allowance for the ANGLE token to the `DistributionCreator` contract\n function _handleIncentiveTokenAllowance(IERC20 incentiveTokenAddress, address spender, uint256 amount) internal {\n uint256 currentAllowance = incentiveTokenAddress.allowance(address(this), spender);\n if (currentAllowance < amount) incentiveTokenAddress.safeIncreaseAllowance(spender, amount - currentAllowance);\n }\n}\n" + }, + "contracts/middleman/MerklGaugeMiddleman.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\n/*\n * █ \n ***** ▓▓▓ \n * ▓▓▓▓▓▓▓ \n * ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓ \n ***** //////// ▓▓▓▓▓▓▓ \n * ///////////// ▓▓▓ \n ▓▓ ////////////////// █ ▓▓ \n ▓▓ ▓▓ /////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓ \n ▓▓ ,////////////////////////////////////// ▓▓ ▓▓ \n ▓▓ ////////////////////////////////////////// ▓▓ \n ▓▓ //////////////////////▓▓▓▓///////////////////// \n ,//////////////////////////////////////////////////// \n .////////////////////////////////////////////////////////// \n .//////////////////////////██.,//////////////////////////█ \n .//////////////////////████..,./////////////////////██ \n ...////////////////███████.....,.////////////////███ \n ,.,////////////████████ ........,///////////████ \n .,.,//////█████████ ,.......///////████ \n ,..//████████ ........./████ \n ..,██████ .....,███ \n .██ ,.,█ \n \n \n \n ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ \n ▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓ \n ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓ \n ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ \n*/\n\npragma solidity ^0.8.17;\n\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\n\nimport \"../DistributionCreator.sol\";\n\n/// @title MerklGaugeMiddleman\n/// @author Angle Labs, Inc.\n/// @notice Manages the transfer of ANGLE rewards to the `DistributionCreator` contract\n/// @dev This contract is built under the assumption that the `DistributionCreator` contract has already whitelisted\n/// this contract for it to distribute rewards without having to sign a message\n/// @dev Transient funds left in this contract after a call may be exploited\ncontract MerklGaugeMiddleman {\n using SafeERC20 for IERC20;\n\n // ================================= PARAMETERS ================================\n\n /// @notice Contract handling access control\n ICore public accessControlManager;\n\n /// @notice Maps a gauge to its reward parameters\n mapping(address => DistributionParameters) public gaugeParams;\n\n // =================================== EVENT ===================================\n\n event GaugeSet(address indexed gauge);\n\n constructor(ICore _accessControlManager) {\n if (address(_accessControlManager) == address(0)) revert ZeroAddress();\n accessControlManager = _accessControlManager;\n IERC20 _angle = angle();\n // Condition left here for testing purposes\n if (address(_angle) != address(0))\n _angle.safeIncreaseAllowance(address(merklDistributionCreator()), type(uint256).max);\n }\n\n // ================================= REFERENCES ================================\n\n /// @notice Address of the ANGLE token\n function angle() public view virtual returns (IERC20) {\n return IERC20(0x31429d1856aD1377A8A0079410B297e1a9e214c2);\n }\n\n /// @notice Address of the Merkl contract managing rewards to be distributed\n /// @dev Address is the same across the different chains on which it is deployed\n function merklDistributionCreator() public view virtual returns (DistributionCreator) {\n return DistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);\n }\n\n // ============================= EXTERNAL FUNCTIONS ============================\n\n /// @notice Restores the allowance for the ANGLE token to the `DistributionCreator` contract\n function setAngleAllowance() external {\n IERC20 _angle = angle();\n address manager = address(merklDistributionCreator());\n uint256 currentAllowance = _angle.allowance(address(this), manager);\n if (currentAllowance < type(uint256).max)\n _angle.safeIncreaseAllowance(manager, type(uint256).max - currentAllowance);\n }\n\n /// @notice Specifies the reward distribution parameters for `gauge`\n function setGauge(address gauge, DistributionParameters memory params) external {\n if (!accessControlManager.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n DistributionCreator manager = merklDistributionCreator();\n if (\n gauge == address(0) ||\n params.rewardToken != address(angle()) ||\n (manager.isWhitelistedToken(IUniswapV3Pool(params.uniV3Pool).token0()) == 0 &&\n manager.isWhitelistedToken(IUniswapV3Pool(params.uniV3Pool).token1()) == 0)\n ) revert InvalidParams();\n gaugeParams[gauge] = params;\n emit GaugeSet(gauge);\n }\n\n /// @notice Transmits rewards from the `AngleDistributor` to the `DistributionCreator` with the correct\n /// parameters\n /// @dev Callable by any contract\n /// @dev This method can be used to recover leftover ANGLE tokens in the contract\n function notifyReward(address gauge, uint256 amount) public {\n DistributionParameters memory params = gaugeParams[gauge];\n if (params.uniV3Pool == address(0)) revert InvalidParams();\n if (amount == 0) amount = angle().balanceOf(address(this));\n params.epochStart = uint32(block.timestamp);\n params.amount = amount;\n DistributionCreator creator = merklDistributionCreator();\n if (amount > 0) {\n // Need to deal with minimum distribution amounts\n if (amount > creator.rewardTokenMinAmounts(address(angle())) * params.numEpoch) {\n merklDistributionCreator().createDistribution(params);\n } else {\n // Sending leftover ANGLE tokens to the `msg.sender`\n angle().safeTransfer(msg.sender, amount);\n }\n }\n }\n\n /// @notice Fetches tokens and transmits rewards in the same transaction\n function notifyRewardWithTransfer(address gauge, uint256 amount) external {\n angle().safeTransferFrom(msg.sender, address(this), amount);\n notifyReward(gauge, amount);\n }\n}\n" + }, + "contracts/middleman/MerklGaugeMiddlemanPolygon.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.17;\n\nimport \"./MerklGaugeMiddleman.sol\";\n\n/// @title MerklGaugeMiddlemanPolygon\n/// @author Angle Labs, Inc.\ncontract MerklGaugeMiddlemanPolygon is MerklGaugeMiddleman {\n constructor(ICore _accessControlManager) MerklGaugeMiddleman(_accessControlManager) {}\n\n function angle() public pure override returns (IERC20) {\n return IERC20(0x900F717EA076E1E7a484ad9DD2dB81CEEc60eBF1);\n }\n}\n" + }, + "contracts/mock/MockMerklFraxIncentivizationHandler.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.17;\n\nimport \"../middleman/MerklFraxIncentivizationHandler.sol\";\n\ncontract MockMerklFraxIncentivizationHandler is MerklFraxIncentivizationHandler {\n DistributionCreator public manager;\n\n constructor(address _operator) MerklFraxIncentivizationHandler(_operator) {}\n\n function merklDistributionCreator() public view override returns (DistributionCreator) {\n return manager;\n }\n\n function setAddresses(DistributionCreator _manager) external {\n manager = _manager;\n }\n}\n" + }, + "contracts/mock/MockMerklGaugeMiddleman.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.17;\n\nimport \"../middleman/MerklGaugeMiddleman.sol\";\n\ncontract MockMerklGaugeMiddleman is MerklGaugeMiddleman {\n address public angleDistributorAddress;\n IERC20 public angleAddress;\n DistributionCreator public manager;\n\n constructor(ICore _coreBorrow) MerklGaugeMiddleman(_coreBorrow) {}\n\n function angle() public view override returns (IERC20) {\n return angleAddress;\n }\n\n function merklDistributionCreator() public view override returns (DistributionCreator) {\n return manager;\n }\n\n function setAddresses(\n address _angleDistributorAddress,\n IERC20 _angleAddress,\n DistributionCreator _manager\n ) external {\n angleDistributorAddress = _angleDistributorAddress;\n angleAddress = _angleAddress;\n manager = _manager;\n }\n}\n" + }, + "contracts/struct/CampaignParameters.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nstruct CampaignParameters {\n // POPULATED ONCE CREATED\n\n // ID of the campaign. This can be left as a null bytes32 when creating campaigns\n // on Merkl.\n bytes32 campaignId;\n // CHOSEN BY CAMPAIGN CREATOR\n\n // Address of the campaign creator, if marked as address(0), it will be overriden with the\n // address of the `msg.sender` creating the campaign\n address creator;\n // Address of the token used as a reward\n address rewardToken;\n // Amount of `rewardToken` to distribute across all the epochs\n // Amount distributed per epoch is `amount/numEpoch`\n uint256 amount;\n // Type of campaign\n uint32 campaignType;\n // Timestamp at which the campaign should start\n uint32 startTimestamp;\n // Duration of the campaign in seconds. Has to be a multiple of EPOCH = 3600\n uint32 duration;\n // Extra data to pass to specify the campaign\n bytes campaignData;\n}\n" + }, + "contracts/struct/DistributionParameters.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nstruct DistributionParameters {\n // ID of the reward (populated once created). This can be left as a null bytes32 when creating distributions\n // on Merkl.\n bytes32 rewardId;\n // Address of the UniswapV3 pool that needs to be incentivized\n address uniV3Pool;\n // Address of the reward token for the incentives\n address rewardToken;\n // Amount of `rewardToken` to distribute across all the epochs\n // Amount distributed per epoch is `amount/numEpoch`\n uint256 amount;\n // List of all position wrappers to consider or not for this contract. Some wrappers like Gamma or Arrakis\n // are automatically detected and so there is no need to specify them here. Check out the docs to find out\n // which need to be specified and which are not automatically detected.\n address[] positionWrappers;\n // Type (blacklist==3, whitelist==0, ...) encoded as a `uint32` for each wrapper in the list above. Mapping between\n // wrapper types and their corresponding `uint32` value can be found in Angle Docs\n uint32[] wrapperTypes;\n // In the incentivization formula, how much of the fees should go to holders of token0\n // in base 10**4\n uint32 propToken0;\n // Proportion for holding token1 (in base 10**4)\n uint32 propToken1;\n // Proportion for providing a useful liquidity (in base 10**4) that generates fees\n uint32 propFees;\n // Timestamp at which the incentivization should start. This is in the same units as `block.timestamp`.\n uint32 epochStart;\n // Amount of epochs for which incentivization should last. Epochs are expressed in hours here, so for a\n // campaign of 1 week `numEpoch` should for instance be 168.\n uint32 numEpoch;\n // Whether out of range liquidity should still be incentivized or not\n // This should be equal to 1 if out of range liquidity should still be incentivized\n // and 0 otherwise.\n uint32 isOutOfRangeIncentivized;\n // How much more addresses with a maximum boost can get with respect to addresses\n // which do not have a boost (in base 4). In the case of Curve where addresses get 2.5x more\n // this would be 25000.\n uint32 boostedReward;\n // Address of the token which dictates who gets boosted rewards or not. This is optional\n // and if the zero address is given no boost will be taken into account. In the case of Curve, this address\n // would for instance be the veBoostProxy address, or in other cases the veToken address.\n address boostingAddress;\n // Additional data passed when distributing rewards. This parameter may be used in case\n // the reward distribution script needs to look into other parameters beyond the ones above.\n // In most cases, when creating a campaign on Merkl, you can leave this as an empty bytes.\n bytes additionalData;\n}\n" + }, + "contracts/struct/RewardTokenAmounts.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nstruct RewardTokenAmounts {\n address token;\n uint256 minimumAmountPerEpoch;\n}\n" + }, + "contracts/tokenWrappers/AaveTokenWrapper.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport { ERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20 } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport \"../DistributionCreator.sol\";\n\nimport \"../utils/UUPSHelper.sol\";\n\ncontract AaveTokenWrapper is UUPSHelper, ERC20Upgradeable {\n using SafeERC20 for IERC20;\n\n // ================================= VARIABLES =================================\n\n /// @notice `Core` contract handling access control\n ICore public core;\n\n // could be put as immutable in non upgradeable contract\n address public token;\n address public distributor;\n address public distributionCreator;\n\n mapping(address => uint256) public isMasterClaimer;\n mapping(address => address) public delegateReceiver;\n mapping(address => uint256) public permissionlessClaim;\n\n error InvalidClaim();\n\n // =================================== EVENTS ==================================\n\n event Recovered(address indexed token, address indexed to, uint256 amount);\n\n // ================================= MODIFIERS =================================\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernor() {\n if (!core.isGovernor(msg.sender)) revert NotGovernor();\n _;\n }\n\n // ================================= FUNCTIONS =================================\n\n function initialize(\n address underlyingToken,\n address _distributor,\n address _core,\n address _distributionCreator\n ) public initializer {\n // TODO could fetch name and symbol based on real token\n __ERC20_init(\"AaveTokenWrapper\", \"ATW\");\n __UUPSUpgradeable_init();\n if (underlyingToken == address(0) || _distributor == address(0) || _distributionCreator == address(0))\n revert ZeroAddress();\n ICore(_core).isGovernor(msg.sender);\n token = underlyingToken;\n distributor = _distributor;\n distributionCreator = _distributionCreator;\n core = ICore(_core);\n }\n\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {\n // Needs an approval before hand, this is how mints are done\n if (to == distributor) {\n IERC20(token).safeTransferFrom(from, address(this), amount);\n _mint(from, amount); // These are then transfered to the distributor\n } else {\n if (to == _getFeeRecipient()) {\n IERC20(token).safeTransferFrom(from, to, amount);\n _mint(from, amount);\n }\n }\n }\n\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\n if (from == address(distributor)) {\n if (tx.origin == to || permissionlessClaim[to] == 1 || isMasterClaimer[tx.origin] == 1) {\n _handleClaim(to, amount);\n } else if (allowance(to, tx.origin) > amount) {\n _spendAllowance(to, tx.origin, amount);\n _handleClaim(to, amount);\n } else {\n revert InvalidClaim();\n }\n } else if (to == _getFeeRecipient()) {\n // To avoid having any token aside from the distributor\n _burn(to, amount);\n }\n }\n\n function _handleClaim(address to, uint256 amount) internal {\n address delegate = delegateReceiver[to];\n _burn(to, amount);\n if (delegate == address(0) || delegate == to) {\n IERC20(token).safeTransfer(to, amount);\n } else {\n IERC20(token).safeTransfer(delegate, amount);\n }\n }\n\n function _getFeeRecipient() internal view returns (address feeRecipient) {\n address _distributionCreator = distributionCreator;\n feeRecipient = DistributionCreator(_distributionCreator).feeRecipient();\n feeRecipient = feeRecipient == address(0) ? _distributionCreator : feeRecipient;\n }\n\n /// @notice Recovers any ERC20 token\n function recoverERC20(address tokenAddress, address to, uint256 amountToRecover) external onlyGovernor {\n IERC20(tokenAddress).safeTransfer(to, amountToRecover);\n emit Recovered(tokenAddress, to, amountToRecover);\n }\n\n function toggleMasterClaimer(address claimer) external onlyGovernor {\n uint256 claimStatus = 1 - isMasterClaimer[claimer];\n isMasterClaimer[claimer] = claimStatus;\n }\n\n function togglePermissionlessClaim() external {\n uint256 permission = 1 - permissionlessClaim[msg.sender];\n permissionlessClaim[msg.sender] = permission;\n }\n\n function updateDelegateReceiver(address receiver) external {\n delegateReceiver[msg.sender] = receiver;\n }\n\n /// @inheritdoc UUPSUpgradeable\n function _authorizeUpgrade(address) internal view override onlyGovernorUpgrader(core) {}\n}\n" + }, + "contracts/tokenWrappers/BaseTokenWrapper.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport { ERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20, IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\nimport \"../utils/UUPSHelper.sol\";\n\ninterface IDistributionCreator {\n function distributor() external view returns (address);\n function feeRecipient() external view returns (address);\n}\n\nabstract contract BaseMerklTokenWrapper is UUPSHelper, ERC20Upgradeable {\n using SafeERC20 for IERC20;\n\n // ================================= CONSTANTS =================================\n\n IDistributionCreator public constant DISTRIBUTOR_CREATOR =\n IDistributionCreator(0x8BB4C975Ff3c250e0ceEA271728547f3802B36Fd);\n\n address public immutable DISTRIBUTOR = DISTRIBUTOR_CREATOR.distributor();\n address public immutable FEE_RECIPIENT = DISTRIBUTOR_CREATOR.feeRecipient();\n\n // ================================= VARIABLES =================================\n\n /// @notice `Core` contract handling access control\n ICore public core;\n\n // =================================== EVENTS ==================================\n\n event Recovered(address indexed token, address indexed to, uint256 amount);\n\n // ================================= MODIFIERS =================================\n\n /// @notice Checks whether the `msg.sender` has the governor role or the guardian role\n modifier onlyGovernor() {\n if (!core.isGovernor(msg.sender)) revert NotGovernor();\n _;\n }\n\n // ================================= FUNCTIONS =================================\n\n function token() public view virtual returns (address);\n\n function isTokenWrapper() external pure returns (bool) {\n return true;\n }\n\n function initialize(ICore _core) public initializer onlyProxy {\n __ERC20_init(\n string.concat(\"Merkl Token Wrapper - \", IERC20Metadata(token()).name()),\n string.concat(\"mtw\", IERC20Metadata(token()).symbol())\n );\n __UUPSUpgradeable_init();\n if (address(_core) == address(0)) revert ZeroAddress();\n core = _core;\n }\n\n /// @notice Recovers any ERC20 token\n /// @dev Governance only, to trigger only if something went wrong\n function recoverERC20(address tokenAddress, address to, uint256 amountToRecover) external onlyGovernor {\n IERC20(tokenAddress).safeTransfer(to, amountToRecover);\n emit Recovered(tokenAddress, to, amountToRecover);\n }\n\n /// @inheritdoc UUPSUpgradeable\n function _authorizeUpgrade(address) internal view override onlyGovernorUpgrader(core) {}\n}\n" + }, + "contracts/tokenWrappers/PointToken.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.7;\n\nimport \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport { ICore } from \"../interfaces/ICore.sol\";\nimport \"../utils/Errors.sol\";\n\n/// @title PointToken\n/// @author Angle Labs, Inc.\n/// @notice Reference contract for points systems within Merkl\ncontract PointToken is ERC20 {\n mapping(address => bool) public minters;\n mapping(address => bool) public whitelistedRecipients;\n ICore public accessControlManager;\n uint8 public allowedTransfers;\n\n constructor(\n string memory name_,\n string memory symbol_,\n address _minter,\n address _accessControlManager\n ) ERC20(name_, symbol_) {\n if (_accessControlManager == address(0) || _minter == address(0)) revert ZeroAddress();\n accessControlManager = ICore(_accessControlManager);\n minters[_minter] = true;\n }\n\n modifier onlyGovernorOrGuardian() {\n if (!accessControlManager.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n _;\n }\n\n modifier onlyMinter() {\n if (!minters[msg.sender]) revert NotTrusted();\n _;\n }\n\n function mint(address account, uint256 amount) external onlyMinter {\n _mint(account, amount);\n }\n\n function burn(address account, uint256 amount) external onlyMinter {\n _burn(account, amount);\n }\n\n function mintBatch(address[] memory accounts, uint256[] memory amounts) external onlyMinter {\n uint256 length = accounts.length;\n for (uint256 i = 0; i < length; ++i) {\n _mint(accounts[i], amounts[i]);\n }\n }\n\n function toggleMinter(address minter) external onlyGovernorOrGuardian {\n minters[minter] = !minters[minter];\n }\n\n function toggleAllowedTransfers() external onlyGovernorOrGuardian {\n allowedTransfers = 1 - allowedTransfers;\n }\n\n function toggleWhitelistedRecipient(address recipient) external onlyGovernorOrGuardian {\n whitelistedRecipients[recipient] = !whitelistedRecipients[recipient];\n }\n\n function _beforeTokenTransfer(address from, address to, uint256) internal view override {\n if (\n allowedTransfers == 0 &&\n from != address(0) &&\n to != address(0) &&\n !whitelistedRecipients[from] &&\n !whitelistedRecipients[to]\n ) revert NotAllowed();\n }\n}\n" + }, + "contracts/tokenWrappers/RadiantTokenWrapper.sol": { + "content": "// SPDX-License-Identifier: BUSL-1.1\n\npragma solidity ^0.8.17;\n\nimport { ERC20Upgradeable } from \"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol\";\nimport { SafeERC20 } from \"@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol\";\nimport { IERC20, IERC20Metadata } from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\nimport { BaseMerklTokenWrapper } from \"./BaseTokenWrapper.sol\";\n\ninterface IVesting {\n function rdntToken() external view returns (address);\n function vestTokens(address, uint256, bool) external returns (address);\n}\n\n/// @title Radiant MTW\n/// @dev This token can only be held by merkl distributor\n/// @dev Transferring to the distributor will require transferring the underlying token to this contract\n/// @dev Transferring from the distributor will trigger vesting action\n/// @dev Transferring token to the distributor is permissionless so anyone could mint this wrapper - the only\n/// impact would be to forfeit these tokens\ncontract RadiantMerklTokenWrapper is BaseMerklTokenWrapper {\n using SafeERC20 for IERC20;\n\n // ================================= CONSTANTS =================================\n\n IVesting public constant VESTING = IVesting(0x76ba3eC5f5adBf1C58c91e86502232317EeA72dE);\n address internal immutable _UNDERLYING = VESTING.rdntToken();\n\n // ================================= FUNCTIONS =================================\n\n function token() public view override returns (address) {\n return _UNDERLYING;\n }\n\n function _beforeTokenTransfer(address from, address to, uint256 amount) internal override {\n // Needs an RDNT approval beforehand, this is how mints of coupons are done\n if (to == DISTRIBUTOR) {\n IERC20(_UNDERLYING).safeTransferFrom(from, address(this), amount);\n _mint(from, amount); // These are then transferred to the distributor\n }\n\n // Will be burn right after, to avoid having any token aside from on the distributor\n if (to == FEE_RECIPIENT) {\n IERC20(_UNDERLYING).safeTransferFrom(from, FEE_RECIPIENT, amount);\n _mint(from, amount); // These are then transferred to the fee manager\n }\n }\n\n function _afterTokenTransfer(address from, address to, uint256 amount) internal override {\n if (to == FEE_RECIPIENT) {\n _burn(to, amount); // To avoid having any token aside from on the distributor\n }\n\n if (from == DISTRIBUTOR) {\n _burn(to, amount);\n\n // Vesting logic\n IERC20(_UNDERLYING).transfer(address(VESTING), amount);\n VESTING.vestTokens(to, amount, true);\n }\n }\n}\n" + }, + "contracts/utils/Errors.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\npragma solidity ^0.8.17;\n\nerror CampaignDoesNotExist();\nerror CampaignAlreadyExists();\nerror CampaignDurationBelowHour();\nerror CampaignRewardTokenNotWhitelisted();\nerror CampaignRewardTooLow();\nerror CampaignSouldStartInFuture();\nerror InvalidDispute();\nerror InvalidLengths();\nerror InvalidParam();\nerror InvalidParams();\nerror InvalidProof();\nerror InvalidUninitializedRoot();\nerror InvalidReward();\nerror InvalidSignature();\nerror NoDispute();\nerror NotAllowed();\nerror NotGovernor();\nerror NotGovernorOrGuardian();\nerror NotSigned();\nerror NotTrusted();\nerror NotWhitelisted();\nerror UnresolvedDispute();\nerror ZeroAddress();\n" + }, + "contracts/utils/UUPSHelper.sol": { + "content": "// SPDX-License-Identifier: GPL-3.0\n\n/*\n * █ \n ***** ▓▓▓ \n * ▓▓▓▓▓▓▓ \n * ///. ▓▓▓▓▓▓▓▓▓▓▓▓▓ \n ***** //////// ▓▓▓▓▓▓▓ \n * ///////////// ▓▓▓ \n ▓▓ ////////////////// █ ▓▓ \n ▓▓ ▓▓ /////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ //////////////////////////// ▓▓ ▓▓ \n ▓▓ ▓▓ /////////▓▓▓///////▓▓▓///////// ▓▓ ▓▓ \n ▓▓ ,////////////////////////////////////// ▓▓ ▓▓ \n ▓▓ ////////////////////////////////////////// ▓▓ \n ▓▓ //////////////////////▓▓▓▓///////////////////// \n ,//////////////////////////////////////////////////// \n .////////////////////////////////////////////////////////// \n .//////////////////////////██.,//////////////////////////█ \n .//////////////////////████..,./////////////////////██ \n ...////////////////███████.....,.////////////////███ \n ,.,////////////████████ ........,///////////████ \n .,.,//////█████████ ,.......///////████ \n ,..//████████ ........./████ \n ..,██████ .....,███ \n .██ ,.,█ \n \n \n \n ▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓ ▓▓▓▓▓▓▓▓▓▓ \n ▓▓▓▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓ ▓▓▓▓ \n ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓▓ ▓▓ ▓▓▓▓▓ \n ▓▓▓ ▓▓ ▓▓▓ ▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ ▓▓▓▓▓▓▓▓▓▓ \n*/\n\npragma solidity ^0.8.17;\n\nimport { UUPSUpgradeable } from \"@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol\";\n\nimport { ICore } from \"../interfaces/ICore.sol\";\nimport \"../utils/Errors.sol\";\n\n/// @title UUPSHelper\n/// @notice Helper contract for UUPSUpgradeable contracts where the upgradeability is controlled by a specific address\n/// @author Angle Labs., Inc\n/// @dev The 0 address check in the modifier allows the use of these modifiers during initialization\nabstract contract UUPSHelper is UUPSUpgradeable {\n modifier onlyGuardianUpgrader(ICore _core) {\n if (address(_core) != address(0) && !_core.isGovernorOrGuardian(msg.sender)) revert NotGovernorOrGuardian();\n _;\n }\n\n modifier onlyGovernorUpgrader(ICore _core) {\n if (address(_core) != address(0) && !_core.isGovernor(msg.sender)) revert NotGovernor();\n _;\n }\n\n constructor() initializer {}\n}\n" + } + }, + "settings": { + "optimizer": { + "enabled": true, + "runs": 100000 + }, + "viaIR": false, + "outputSelection": { + "*": { + "*": [ + "abi", + "evm.bytecode", + "evm.deployedBytecode", + "evm.methodIdentifiers", + "metadata", + "devdoc", + "userdoc", + "storageLayout", + "evm.gasEstimates" + ], + "": [ + "ast" + ] + } + }, + "metadata": { + "useLiteralContent": true + } + } +} \ No newline at end of file