{"file_path":"contracts/Floki.sol","creation_status":"success","source_code":"// SPDX-License-Identifier: MIT\npragma solidity 0.8.11;\n\nimport \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport \"@openzeppelin/contracts/access/Ownable.sol\";\n\nimport \"./governance/IGovernanceToken.sol\";\nimport \"./tax/ITaxHandler.sol\";\nimport \"./treasury/ITreasuryHandler.sol\";\n\n/**\n * @title Floki token contract\n * @dev The Floki token has modular systems for tax and treasury handler as well as governance capabilities.\n */\ncontract FLOKI is IERC20, IGovernanceToken, Ownable {\n    /// @dev Registry of user token balances.\n    mapping(address => uint256) private _balances;\n\n    /// @dev Registry of addresses users have given allowances to.\n    mapping(address => mapping(address => uint256)) private _allowances;\n\n    /// @notice Registry of user delegates for governance.\n    mapping(address => address) public delegates;\n\n    /// @notice Registry of nonces for vote delegation.\n    mapping(address => uint256) public nonces;\n\n    /// @notice Registry of the number of balance checkpoints an account has.\n    mapping(address => uint32) public numCheckpoints;\n\n    /// @notice Registry of balance checkpoints per account.\n    mapping(address => mapping(uint32 => Checkpoint)) public checkpoints;\n\n    /// @notice The EIP-712 typehash for the contract's domain.\n    bytes32 public constant DOMAIN_TYPEHASH =\n        keccak256(\"EIP712Domain(string name,uint256 chainId,address verifyingContract)\");\n\n    /// @notice The EIP-712 typehash for the delegation struct used by the contract.\n    bytes32 public constant DELEGATION_TYPEHASH =\n        keccak256(\"Delegation(address delegatee,uint256 nonce,uint256 expiry)\");\n\n    /// @notice The contract implementing tax calculations.\n    ITaxHandler public taxHandler;\n\n    /// @notice The contract that performs treasury-related operations.\n    ITreasuryHandler public treasuryHandler;\n\n    /// @notice Emitted when the tax handler contract is changed.\n    event TaxHandlerChanged(address oldAddress, address newAddress);\n\n    /// @notice Emitted when the treasury handler contract is changed.\n    event TreasuryHandlerChanged(address oldAddress, address newAddress);\n\n    /// @dev Name of the token.\n    string private _name;\n\n    /// @dev Symbol of the token.\n    string private _symbol;\n\n    /**\n     * @param name_ Name of the token.\n     * @param symbol_ Symbol of the token.\n     * @param taxHandlerAddress Initial tax handler contract.\n     * @param treasuryHandlerAddress Initial treasury handler contract.\n     */\n    constructor(\n        string memory name_,\n        string memory symbol_,\n        address taxHandlerAddress,\n        address treasuryHandlerAddress\n    ) {\n        _name = name_;\n        _symbol = symbol_;\n\n        taxHandler = ITaxHandler(taxHandlerAddress);\n        treasuryHandler = ITreasuryHandler(treasuryHandlerAddress);\n\n        _balances[_msgSender()] = totalSupply();\n\n        emit Transfer(address(0), _msgSender(), totalSupply());\n    }\n\n    /**\n     * @notice Get token name.\n     * @return Name of the token.\n     */\n    function name() public view returns (string memory) {\n        return _name;\n    }\n\n    /**\n     * @notice Get token symbol.\n     * @return Symbol of the token.\n     */\n    function symbol() external view returns (string memory) {\n        return _symbol;\n    }\n\n    /**\n     * @notice Get number of decimals used by the token.\n     * @return Number of decimals used by the token.\n     */\n    function decimals() external pure returns (uint8) {\n        return 9;\n    }\n\n    /**\n     * @notice Get the maximum number of tokens.\n     * @return The maximum number of tokens that will ever be in existence.\n     */\n    function totalSupply() public pure override returns (uint256) {\n        // Ten trillion, i.e., 10,000,000,000,000 tokens.\n        return 1e13 * 1e9;\n    }\n\n    /**\n     * @notice Get token balance of given given account.\n     * @param account Address to retrieve balance for.\n     * @return The number of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view override returns (uint256) {\n        return _balances[account];\n    }\n\n    /**\n     * @notice Transfer tokens from caller's address to another.\n     * @param recipient Address to send the caller's tokens to.\n     * @param amount The number of tokens to transfer to recipient.\n     * @return True if transfer succeeds, else an error is raised.\n     */\n    function transfer(address recipient, uint256 amount) external override returns (bool) {\n        _transfer(_msgSender(), recipient, amount);\n        return true;\n    }\n\n    /**\n     * @notice Get the allowance `owner` has given `spender`.\n     * @param owner The address on behalf of whom tokens can be spent by `spender`.\n     * @param spender The address authorized to spend tokens on behalf of `owner`.\n     * @return The allowance `owner` has given `spender`.\n     */\n    function allowance(address owner, address spender) external view override returns (uint256) {\n        return _allowances[owner][spender];\n    }\n\n    /**\n     * @notice Approve address to spend caller's tokens.\n     * @dev This method can be exploited by malicious spenders if their allowance is already non-zero. See the following\n     * document for details: https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/edit.\n     * Ensure the spender can be trusted before calling this method if they've already been approved before. Otherwise\n     * use either the `increaseAllowance`/`decreaseAllowance` functions, or first set their allowance to zero, before\n     * setting a new allowance.\n     * @param spender Address to authorize for token expenditure.\n     * @param amount The number of tokens `spender` is allowed to spend.\n     * @return True if the approval succeeds, else an error is raised.\n     */\n    function approve(address spender, uint256 amount) external override returns (bool) {\n        _approve(_msgSender(), spender, amount);\n        return true;\n    }\n\n    /**\n     * @notice Transfer tokens from one address to another.\n     * @param sender Address to move tokens from.\n     * @param recipient Address to send the caller's tokens to.\n     * @param amount The number of tokens to transfer to recipient.\n     * @return True if the transfer succeeds, else an error is raised.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external override returns (bool) {\n        _transfer(sender, recipient, amount);\n\n        uint256 currentAllowance = _allowances[sender][_msgSender()];\n        require(\n            currentAllowance >= amount,\n            \"FLOKI:transferFrom:ALLOWANCE_EXCEEDED: Transfer amount exceeds allowance.\"\n        );\n        unchecked {\n            _approve(sender, _msgSender(), currentAllowance - amount);\n        }\n\n        return true;\n    }\n\n    /**\n     * @notice Increase spender's allowance.\n     * @param spender Address of user authorized to spend caller's tokens.\n     * @param addedValue The number of tokens to add to `spender`'s allowance.\n     * @return True if the allowance is successfully increased, else an error is raised.\n     */\n    function increaseAllowance(address spender, uint256 addedValue) external returns (bool) {\n        _approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);\n\n        return true;\n    }\n\n    /**\n     * @notice Decrease spender's allowance.\n     * @param spender Address of user authorized to spend caller's tokens.\n     * @param subtractedValue The number of tokens to remove from `spender`'s allowance.\n     * @return True if the allowance is successfully decreased, else an error is raised.\n     */\n    function decreaseAllowance(address spender, uint256 subtractedValue) external returns (bool) {\n        uint256 currentAllowance = _allowances[_msgSender()][spender];\n        require(\n            currentAllowance >= subtractedValue,\n            \"FLOKI:decreaseAllowance:ALLOWANCE_UNDERFLOW: Subtraction results in sub-zero allowance.\"\n        );\n        unchecked {\n            _approve(_msgSender(), spender, currentAllowance - subtractedValue);\n        }\n\n        return true;\n    }\n\n    /**\n     * @notice Delegate votes to given address.\n     * @dev It should be noted that users that want to vote themselves, also need to call this method, albeit with their\n     * own address.\n     * @param delegatee Address to delegate votes to.\n     */\n    function delegate(address delegatee) external {\n        return _delegate(msg.sender, delegatee);\n    }\n\n    /**\n     * @notice Delegate votes from signatory to `delegatee`.\n     * @param delegatee The address to delegate votes to.\n     * @param nonce The contract state required to match the signature.\n     * @param expiry The time at which to expire the signature.\n     * @param v The recovery byte of the signature.\n     * @param r Half of the ECDSA signature pair.\n     * @param s Half of the ECDSA signature pair.\n     */\n    function delegateBySig(\n        address delegatee,\n        uint256 nonce,\n        uint256 expiry,\n        uint8 v,\n        bytes32 r,\n        bytes32 s\n    ) external {\n        bytes32 domainSeparator = keccak256(\n            abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name())), block.chainid, address(this))\n        );\n        bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));\n        bytes32 digest = keccak256(abi.encodePacked(\"\\x19\\x01\", domainSeparator, structHash));\n        address signatory = ecrecover(digest, v, r, s);\n\n        require(signatory != address(0), \"FLOKI:delegateBySig:INVALID_SIGNATURE: Received signature was invalid.\");\n        require(block.timestamp <= expiry, \"FLOKI:delegateBySig:EXPIRED_SIGNATURE: Received signature has expired.\");\n        require(nonce == nonces[signatory]++, \"FLOKI:delegateBySig:INVALID_NONCE: Received nonce was invalid.\");\n\n        return _delegate(signatory, delegatee);\n    }\n\n    /**\n     * @notice Determine the number of votes for an account as of a block number.\n     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\n     * @param account The address of the account to check.\n     * @param blockNumber The block number to get the vote balance at.\n     * @return The number of votes the account had as of the given block.\n     */\n    function getVotesAtBlock(address account, uint32 blockNumber) public view returns (uint224) {\n        require(\n            blockNumber < block.number,\n            \"FLOKI:getVotesAtBlock:FUTURE_BLOCK: Cannot get votes at a block in the future.\"\n        );\n\n        uint32 nCheckpoints = numCheckpoints[account];\n        if (nCheckpoints == 0) {\n            return 0;\n        }\n\n        // First check most recent balance.\n        if (checkpoints[account][nCheckpoints - 1].blockNumber <= blockNumber) {\n            return checkpoints[account][nCheckpoints - 1].votes;\n        }\n\n        // Next check implicit zero balance.\n        if (checkpoints[account][0].blockNumber > blockNumber) {\n            return 0;\n        }\n\n        // Perform binary search.\n        uint32 lowerBound = 0;\n        uint32 upperBound = nCheckpoints - 1;\n        while (upperBound > lowerBound) {\n            uint32 center = upperBound - (upperBound - lowerBound) / 2;\n            Checkpoint memory checkpoint = checkpoints[account][center];\n\n            if (checkpoint.blockNumber == blockNumber) {\n                return checkpoint.votes;\n            } else if (checkpoint.blockNumber < blockNumber) {\n                lowerBound = center;\n            } else {\n                upperBound = center - 1;\n            }\n        }\n\n        // No exact block found. Use last known balance before that block number.\n        return checkpoints[account][lowerBound].votes;\n    }\n\n    /**\n     * @notice Set new tax handler contract.\n     * @param taxHandlerAddress Address of new tax handler contract.\n     */\n    function setTaxHandler(address taxHandlerAddress) external onlyOwner {\n        address oldTaxHandlerAddress = address(taxHandler);\n        taxHandler = ITaxHandler(taxHandlerAddress);\n\n        emit TaxHandlerChanged(oldTaxHandlerAddress, taxHandlerAddress);\n    }\n\n    /**\n     * @notice Set new treasury handler contract.\n     * @param treasuryHandlerAddress Address of new treasury handler contract.\n     */\n    function setTreasuryHandler(address treasuryHandlerAddress) external onlyOwner {\n        address oldTreasuryHandlerAddress = address(treasuryHandler);\n        treasuryHandler = ITreasuryHandler(treasuryHandlerAddress);\n\n        emit TreasuryHandlerChanged(oldTreasuryHandlerAddress, treasuryHandlerAddress);\n    }\n\n    /**\n     * @notice Delegate votes from one address to another.\n     * @param delegator Address from which to delegate votes for.\n     * @param delegatee Address to delegate votes to.\n     */\n    function _delegate(address delegator, address delegatee) private {\n        address currentDelegate = delegates[delegator];\n        uint256 delegatorBalance = _balances[delegator];\n        delegates[delegator] = delegatee;\n\n        emit DelegateChanged(delegator, currentDelegate, delegatee);\n\n        _moveDelegates(currentDelegate, delegatee, uint224(delegatorBalance));\n    }\n\n    /**\n     * @notice Move delegates from one address to another.\n     * @param from Representative to move delegates from.\n     * @param to Representative to move delegates to.\n     * @param amount Number of delegates to move.\n     */\n    function _moveDelegates(\n        address from,\n        address to,\n        uint224 amount\n    ) private {\n        // No need to update checkpoints if the votes don't actually move between different delegates. This can be the\n        // case where tokens are transferred between two parties that have delegated their votes to the same address.\n        if (from == to) {\n            return;\n        }\n\n        // Some users preemptively delegate their votes (i.e. before they have any tokens). No need to perform an update\n        // to the checkpoints in that case.\n        if (amount == 0) {\n            return;\n        }\n\n        if (from != address(0)) {\n            uint32 fromRepNum = numCheckpoints[from];\n            uint224 fromRepOld = fromRepNum > 0 ? checkpoints[from][fromRepNum - 1].votes : 0;\n            uint224 fromRepNew = fromRepOld - amount;\n\n            _writeCheckpoint(from, fromRepNum, fromRepOld, fromRepNew);\n        }\n\n        if (to != address(0)) {\n            uint32 toRepNum = numCheckpoints[to];\n            uint224 toRepOld = toRepNum > 0 ? checkpoints[to][toRepNum - 1].votes : 0;\n            uint224 toRepNew = toRepOld + amount;\n\n            _writeCheckpoint(to, toRepNum, toRepOld, toRepNew);\n        }\n    }\n\n    /**\n     * @notice Write balance checkpoint to chain.\n     * @param delegatee The address to write the checkpoint for.\n     * @param nCheckpoints The number of checkpoints `delegatee` already has.\n     * @param oldVotes Number of votes prior to this checkpoint.\n     * @param newVotes Number of votes `delegatee` now has.\n     */\n    function _writeCheckpoint(\n        address delegatee,\n        uint32 nCheckpoints,\n        uint224 oldVotes,\n        uint224 newVotes\n    ) private {\n        uint32 blockNumber = uint32(block.number);\n\n        if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].blockNumber == blockNumber) {\n            checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;\n        } else {\n            checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);\n            numCheckpoints[delegatee] = nCheckpoints + 1;\n        }\n\n        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);\n    }\n\n    /**\n     * @notice Approve spender on behalf of owner.\n     * @param owner Address on behalf of whom tokens can be spent by `spender`.\n     * @param spender Address to authorize for token expenditure.\n     * @param amount The number of tokens `spender` is allowed to spend.\n     */\n    function _approve(\n        address owner,\n        address spender,\n        uint256 amount\n    ) private {\n        require(owner != address(0), \"FLOKI:_approve:OWNER_ZERO: Cannot approve for the zero address.\");\n        require(spender != address(0), \"FLOKI:_approve:SPENDER_ZERO: Cannot approve to the zero address.\");\n\n        _allowances[owner][spender] = amount;\n\n        emit Approval(owner, spender, amount);\n    }\n\n    /**\n     * @notice Transfer `amount` tokens from account `from` to account `to`.\n     * @param from Address the tokens are moved out of.\n     * @param to Address the tokens are moved to.\n     * @param amount The number of tokens to transfer.\n     */\n    function _transfer(\n        address from,\n        address to,\n        uint256 amount\n    ) private {\n        require(from != address(0), \"FLOKI:_transfer:FROM_ZERO: Cannot transfer from the zero address.\");\n        require(to != address(0), \"FLOKI:_transfer:TO_ZERO: Cannot transfer to the zero address.\");\n        require(amount > 0, \"FLOKI:_transfer:ZERO_AMOUNT: Transfer amount must be greater than zero.\");\n        require(amount <= _balances[from], \"FLOKI:_transfer:INSUFFICIENT_BALANCE: Transfer amount exceeds balance.\");\n\n        treasuryHandler.beforeTransferHandler(from, to, amount);\n\n        uint256 tax = taxHandler.getTax(from, to, amount);\n        uint256 taxedAmount = amount - tax;\n\n        _balances[from] -= amount;\n        _balances[to] += taxedAmount;\n        _moveDelegates(delegates[from], delegates[to], uint224(taxedAmount));\n\n        if (tax > 0) {\n            _balances[address(treasuryHandler)] += tax;\n\n            _moveDelegates(delegates[from], delegates[address(treasuryHandler)], uint224(tax));\n\n            emit Transfer(from, address(treasuryHandler), tax);\n        }\n\n        treasuryHandler.afterTransferHandler(from, to, amount);\n\n        emit Transfer(from, to, taxedAmount);\n    }\n}\n","deployed_bytecode":"0x608060405234801561001057600080fd5b50600436106101b95760003560e01c80636fcfff45116100f9578063a9059cbb11610097578063dd62ed3e11610071578063dd62ed3e14610420578063e7a324dc14610459578063f1127ed814610480578063f2fde38b146104e857600080fd5b8063a9059cbb146103e7578063a9373b7b146103fa578063c3cda5201461040d57600080fd5b80637ecebe00116100d35780637ecebe001461039b5780638da5cb5b146103bb57806395d89b41146103cc578063a457c2d7146103d457600080fd5b80636fcfff451461032f57806370a082311461036a578063715018a61461039357600080fd5b806323b872dd11610166578063395093511161014057806339509351146102cb578063488d4a51146102de578063587cde1e146102f35780635c19a95c1461031c57600080fd5b806323b872dd1461027e578063271a452914610291578063313ce567146102bc57600080fd5b80631788963311610197578063178896331461022a57806318160ddd1461023d57806320606b701461025757600080fd5b806306fdde03146101be578063095ea7b3146101dc57806312280ba8146101ff575b600080fd5b6101c66104fb565b6040516101d39190611bfa565b60405180910390f35b6101ef6101ea366004611c6b565b61058d565b60405190151581526020016101d3565b600754610212906001600160a01b031681565b6040516001600160a01b0390911681526020016101d3565b600854610212906001600160a01b031681565b69021e19e0c9bab24000005b6040519081526020016101d3565b6102497f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6101ef61028c366004611c95565b6105a4565b6102a461029f366004611cd1565b61068e565b6040516001600160e01b0390911681526020016101d3565b604051600981526020016101d3565b6101ef6102d9366004611c6b565b610968565b6102f16102ec366004611d11565b6109a4565b005b610212610301366004611d11565b6003602052600090815260409020546001600160a01b031681565b6102f161032a366004611d11565b610a6c565b61035561033d366004611d11565b60056020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101d3565b610249610378366004611d11565b6001600160a01b031660009081526001602052604090205490565b6102f1610a79565b6102496103a9366004611d11565b60046020526000908152604090205481565b6000546001600160a01b0316610212565b6101c6610adf565b6101ef6103e2366004611c6b565b610aee565b6101ef6103f5366004611c6b565b610bc5565b6102f1610408366004611d11565b610bd2565b6102f161041b366004611d33565b610c93565b61024961042e366004611d93565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6102497fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6104c461048e366004611cd1565b600660209081526000928352604080842090915290825290205463ffffffff81169064010000000090046001600160e01b031682565b6040805163ffffffff90931683526001600160e01b039091166020830152016101d3565b6102f16104f6366004611d11565b610fed565b60606009805461050a90611dc6565b80601f016020809104026020016040519081016040528092919081815260200182805461053690611dc6565b80156105835780601f1061055857610100808354040283529160200191610583565b820191906000526020600020905b81548152906001019060200180831161056657829003601f168201915b5050505050905090565b600061059a3384846110cc565b5060015b92915050565b60006105b1848484611227565b6001600160a01b0384166000908152600260209081526040808320338452909152902054828110156106765760405162461bcd60e51b815260206004820152604960248201527f464c4f4b493a7472616e7366657246726f6d3a414c4c4f57414e43455f45584360448201527f45454445443a205472616e7366657220616d6f756e742065786365656473206160648201527f6c6c6f77616e63652e0000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b61068385338584036110cc565b506001949350505050565b6000438263ffffffff16106107315760405162461bcd60e51b815260206004820152604e60248201527f464c4f4b493a676574566f7465734174426c6f636b3a4655545552455f424c4f60448201527f434b3a2043616e6e6f742067657420766f746573206174206120626c6f636b2060648201527f696e20746865206675747572652e000000000000000000000000000000000000608482015260a40161066d565b6001600160a01b03831660009081526005602052604090205463ffffffff168061075f57600091505061059e565b6001600160a01b038416600090815260066020526040812063ffffffff85169161078a600185611e17565b63ffffffff908116825260208201929092526040016000205416116107fe576001600160a01b0384166000908152600660205260408120906107cd600184611e17565b63ffffffff16815260208101919091526040016000205464010000000090046001600160e01b0316915061059e9050565b6001600160a01b038416600090815260066020908152604080832083805290915290205463ffffffff8085169116111561083c57600091505061059e565b60008061084a600184611e17565b90505b8163ffffffff168163ffffffff161115610922576000600261086f8484611e17565b6108799190611e3c565b6108839083611e17565b6001600160a01b038816600090815260066020908152604080832063ffffffff8581168552908352928190208151808301909252548084168083526401000000009091046001600160e01b03169282019290925292935090881614156108f35760200151945061059e9350505050565b805163ffffffff8089169116101561090d5781935061091b565b610918600183611e17565b92505b505061084d565b506001600160a01b038516600090815260066020908152604080832063ffffffff909416835292905220546001600160e01b036401000000009091041691505092915050565b3360008181526002602090815260408083206001600160a01b0387168452909152812054909161059a91859061099f908690611e6d565b6110cc565b6000546001600160a01b031633146109fe5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b600780546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff1983168117909355604080519190921680825260208201939093527ed910c9481701ba32afe0c247572aaece27072f230c8ec769bf245fc0b38de691015b60405180910390a15050565b610a7633826117c2565b50565b6000546001600160a01b03163314610ad35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b610add6000611861565b565b6060600a805461050a90611dc6565b3360009081526002602090815260408083206001600160a01b038616845290915281205482811015610bae5760405162461bcd60e51b815260206004820152605760248201527f464c4f4b493a6465637265617365416c6c6f77616e63653a414c4c4f57414e4360448201527f455f554e444552464c4f573a205375627472616374696f6e20726573756c747360648201527f20696e207375622d7a65726f20616c6c6f77616e63652e000000000000000000608482015260a40161066d565b610bbb33858584036110cc565b5060019392505050565b600061059a338484611227565b6000546001600160a01b03163314610c2c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b600880546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff1983168117909355604080519190921680825260208201939093527f1bf87992a35ee29395ab494f9adb9a500a7fa60c3082cba0ef02701bb35900d99101610a60565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866610cbe6104fb565b8051602091820120604080518084019490945283810191909152466060840152306080808501919091528151808503909101815260a0840182528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c08501526001600160a01b038b1660e085015261010084018a90526101208085018a90528251808603909101815261014085019092528151919092012061190160f01b61016084015261016283018290526101828301819052909250906000906101a20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015610def573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610e9e5760405162461bcd60e51b815260206004820152604660248201527f464c4f4b493a64656c656761746542795369673a494e56414c49445f5349474e60448201527f41545552453a205265636569766564207369676e61747572652077617320696e60648201527f76616c69642e0000000000000000000000000000000000000000000000000000608482015260a40161066d565b87421115610f3a5760405162461bcd60e51b815260206004820152604660248201527f464c4f4b493a64656c656761746542795369673a455850495245445f5349474e60448201527f41545552453a205265636569766564207369676e61747572652068617320657860648201527f70697265642e0000000000000000000000000000000000000000000000000000608482015260a40161066d565b6001600160a01b0381166000908152600460205260408120805491610f5e83611e85565b919050558914610fd65760405162461bcd60e51b815260206004820152603e60248201527f464c4f4b493a64656c656761746542795369673a494e56414c49445f4e4f4e4360448201527f453a205265636569766564206e6f6e63652077617320696e76616c69642e0000606482015260840161066d565b610fe0818b6117c2565b505050505b505050505050565b6000546001600160a01b031633146110475760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b6001600160a01b0381166110c35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161066d565b610a7681611861565b6001600160a01b0383166111485760405162461bcd60e51b815260206004820152603f60248201527f464c4f4b493a5f617070726f76653a4f574e45525f5a45524f3a2043616e6e6f60448201527f7420617070726f766520666f7220746865207a65726f20616464726573732e00606482015260840161066d565b6001600160a01b0382166111c6576040805162461bcd60e51b81526020600482015260248101919091527f464c4f4b493a5f617070726f76653a5350454e4445525f5a45524f3a2043616e60448201527f6e6f7420617070726f766520746f20746865207a65726f20616464726573732e606482015260840161066d565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166112ad5760405162461bcd60e51b815260206004820152604160248201527f464c4f4b493a5f7472616e736665723a46524f4d5f5a45524f3a2043616e6e6f60448201527f74207472616e736665722066726f6d20746865207a65726f20616464726573736064820152601760f91b608482015260a40161066d565b6001600160a01b0382166113295760405162461bcd60e51b815260206004820152603d60248201527f464c4f4b493a5f7472616e736665723a544f5f5a45524f3a2043616e6e6f742060448201527f7472616e7366657220746f20746865207a65726f20616464726573732e000000606482015260840161066d565b600081116113c55760405162461bcd60e51b815260206004820152604760248201527f464c4f4b493a5f7472616e736665723a5a45524f5f414d4f554e543a2054726160448201527f6e7366657220616d6f756e74206d75737420626520677265617465722074686160648201527f6e207a65726f2e00000000000000000000000000000000000000000000000000608482015260a40161066d565b6001600160a01b0383166000908152600160205260409020548111156114795760405162461bcd60e51b815260206004820152604660248201527f464c4f4b493a5f7472616e736665723a494e53554646494349454e545f42414c60448201527f414e43453a205472616e7366657220616d6f756e74206578636565647320626160648201527f6c616e63652e0000000000000000000000000000000000000000000000000000608482015260a40161066d565b6008546040517fc6512cc10000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152604482018490529091169063c6512cc190606401600060405180830381600087803b1580156114e857600080fd5b505af11580156114fc573d6000803e3d6000fd5b50506007546040517fd7ad21ac0000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015286811660248301526044820186905260009450909116915063d7ad21ac90606401602060405180830381865afa158015611575573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115999190611ea0565b905060006115a78284611eb9565b6001600160a01b0386166000908152600160205260408120805492935085929091906115d4908490611eb9565b90915550506001600160a01b03841660009081526001602052604081208054839290611601908490611e6d565b90915550506001600160a01b03808616600090815260036020526040808220548784168352912054611638929182169116836118be565b81156116e7576008546001600160a01b031660009081526001602052604081208054849290611668908490611e6d565b90915550506001600160a01b0380861660009081526003602052604080822054600854841683529120546116a1929182169116846118be565b6008546040518381526001600160a01b03918216918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b6008546040517fe613b1cd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528681166024830152604482018690529091169063e613b1cd90606401600060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516117b391815260200190565b60405180910390a35050505050565b6001600160a01b038281166000818152600360208181526040808420805460018452948290205493835287871673ffffffffffffffffffffffffffffffffffffffff198616811790915581519586529390951690840181905293830191909152907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9060600160405180910390a161185b8284836118be565b50505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b816001600160a01b0316836001600160a01b031614156118dd57505050565b6001600160e01b0381166118f057505050565b6001600160a01b03831615611998576001600160a01b03831660009081526005602052604081205463ffffffff16908161192b576000611978565b6001600160a01b03851660009081526006602052604081209061194f600185611e17565b63ffffffff16815260208101919091526040016000205464010000000090046001600160e01b03165b905060006119868483611ed0565b905061199486848484611a41565b5050505b6001600160a01b03821615611a3c576001600160a01b03821660009081526005602052604081205463ffffffff1690816119d3576000611a20565b6001600160a01b0384166000908152600660205260408120906119f7600185611e17565b63ffffffff16815260208101919091526040016000205464010000000090046001600160e01b03165b90506000611a2e8483611ef0565b9050610fe585848484611a41565b505050565b4363ffffffff841615801590611a9957506001600160a01b038516600090815260066020526040812063ffffffff831691611a7d600188611e17565b63ffffffff908116825260208201929092526040016000205416145b15611b09576001600160a01b03851660009081526006602052604081208391611ac3600188611e17565b63ffffffff1663ffffffff16815260200190815260200160002060000160046101000a8154816001600160e01b0302191690836001600160e01b03160217905550611ba1565b60408051808201825263ffffffff80841682526001600160e01b0380861660208085019182526001600160a01b038b166000908152600682528681208b86168252909152949094209251935116640100000000029216919091179055611b70846001611f1b565b6001600160a01b0386166000908152600560205260409020805463ffffffff191663ffffffff929092169190911790555b604080516001600160a01b03871681526001600160e01b03858116602083015284168183015290517fda5a64c2947c0b7bf4d6e7bf736c6f84d9d1c5f991770f88bbeb3fe19c85a1349181900360600190a15050505050565b600060208083528351808285015260005b81811015611c2757858101830151858201604001528201611c0b565b81811115611c39576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114611c6657600080fd5b919050565b60008060408385031215611c7e57600080fd5b611c8783611c4f565b946020939093013593505050565b600080600060608486031215611caa57600080fd5b611cb384611c4f565b9250611cc160208501611c4f565b9150604084013590509250925092565b60008060408385031215611ce457600080fd5b611ced83611c4f565b9150602083013563ffffffff81168114611d0657600080fd5b809150509250929050565b600060208284031215611d2357600080fd5b611d2c82611c4f565b9392505050565b60008060008060008060c08789031215611d4c57600080fd5b611d5587611c4f565b95506020870135945060408701359350606087013560ff81168114611d7957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215611da657600080fd5b611daf83611c4f565b9150611dbd60208401611c4f565b90509250929050565b600181811c90821680611dda57607f821691505b60208210811415611dfb57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015611e3457611e34611e01565b039392505050565b600063ffffffff80841680611e6157634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b60008219821115611e8057611e80611e01565b500190565b6000600019821415611e9957611e99611e01565b5060010190565b600060208284031215611eb257600080fd5b5051919050565b600082821015611ecb57611ecb611e01565b500390565b60006001600160e01b0383811690831681811015611e3457611e34611e01565b60006001600160e01b03808316818516808303821115611f1257611f12611e01565b01949350505050565b600063ffffffff808316818516808303821115611f1257611f12611e0156fea164736f6c634300080b000a","optimization_enabled":true,"verified_twin_address_hash":null,"is_verified":true,"compiler_settings":{"compilationTarget":{"contracts/Floki.sol":"FLOKI"},"evmVersion":"london","libraries":{},"metadata":{"bytecodeHash":"none"},"optimizer":{"enabled":true,"runs":888},"remappings":[]},"optimization_runs":888,"sourcify_repo_url":null,"decoded_constructor_args":[["FLOKI",{"internalType":"string","name":"name_","type":"string"}],["FLOKI",{"internalType":"string","name":"symbol_","type":"string"}],["0x4491C4C1d1Bf636057eaB66cD986DA08f619bD56",{"internalType":"address","name":"taxHandlerAddress","type":"address"}],["0xd2A64B48b33ff641058719D2b3Fa0f9ee5C24368",{"internalType":"address","name":"treasuryHandlerAddress","type":"address"}]],"compiler_version":"0.8.11+commit.d7f03943","is_verified_via_verifier_alliance":true,"verified_at":"2023-06-18T17:27:18.424246Z","implementations":[],"proxy_type":null,"external_libraries":[],"creation_bytecode":"0x60806040523480156200001157600080fd5b5060405162002322380380620023228339810160408190526200003491620002ff565b6200003f336200011f565b8351620000549060099060208701906200016f565b5082516200006a90600a9060208601906200016f565b50600780546001600160a01b038085166001600160a01b0319928316179092556008805492841692909116919091179055620000ad69021e19e0c9bab240000090565b60016000336001600160a01b03168152602081019190915260400160002055336001600160a01b031660007fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef69021e19e0c9bab240000060405190815260200160405180910390a350505050620003cb565b600080546001600160a01b038381166001600160a01b0319831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b8280546200017d906200038e565b90600052602060002090601f016020900481019282620001a15760008555620001ec565b82601f10620001bc57805160ff1916838001178555620001ec565b82800160010185558215620001ec579182015b82811115620001ec578251825591602001919060010190620001cf565b50620001fa929150620001fe565b5090565b5b80821115620001fa5760008155600101620001ff565b634e487b7160e01b600052604160045260246000fd5b600082601f8301126200023d57600080fd5b81516001600160401b03808211156200025a576200025a62000215565b604051601f8301601f19908116603f0116810190828211818310171562000285576200028562000215565b81604052838152602092508683858801011115620002a257600080fd5b600091505b83821015620002c65785820183015181830184015290820190620002a7565b83821115620002d85760008385830101525b9695505050505050565b80516001600160a01b0381168114620002fa57600080fd5b919050565b600080600080608085870312156200031657600080fd5b84516001600160401b03808211156200032e57600080fd5b6200033c888389016200022b565b955060208701519150808211156200035357600080fd5b5062000362878288016200022b565b9350506200037360408601620002e2565b91506200038360608601620002e2565b905092959194509250565b600181811c90821680620003a357607f821691505b60208210811415620003c557634e487b7160e01b600052602260045260246000fd5b50919050565b611f4780620003db6000396000f3fe608060405234801561001057600080fd5b50600436106101b95760003560e01c80636fcfff45116100f9578063a9059cbb11610097578063dd62ed3e11610071578063dd62ed3e14610420578063e7a324dc14610459578063f1127ed814610480578063f2fde38b146104e857600080fd5b8063a9059cbb146103e7578063a9373b7b146103fa578063c3cda5201461040d57600080fd5b80637ecebe00116100d35780637ecebe001461039b5780638da5cb5b146103bb57806395d89b41146103cc578063a457c2d7146103d457600080fd5b80636fcfff451461032f57806370a082311461036a578063715018a61461039357600080fd5b806323b872dd11610166578063395093511161014057806339509351146102cb578063488d4a51146102de578063587cde1e146102f35780635c19a95c1461031c57600080fd5b806323b872dd1461027e578063271a452914610291578063313ce567146102bc57600080fd5b80631788963311610197578063178896331461022a57806318160ddd1461023d57806320606b701461025757600080fd5b806306fdde03146101be578063095ea7b3146101dc57806312280ba8146101ff575b600080fd5b6101c66104fb565b6040516101d39190611bfa565b60405180910390f35b6101ef6101ea366004611c6b565b61058d565b60405190151581526020016101d3565b600754610212906001600160a01b031681565b6040516001600160a01b0390911681526020016101d3565b600854610212906001600160a01b031681565b69021e19e0c9bab24000005b6040519081526020016101d3565b6102497f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a86681565b6101ef61028c366004611c95565b6105a4565b6102a461029f366004611cd1565b61068e565b6040516001600160e01b0390911681526020016101d3565b604051600981526020016101d3565b6101ef6102d9366004611c6b565b610968565b6102f16102ec366004611d11565b6109a4565b005b610212610301366004611d11565b6003602052600090815260409020546001600160a01b031681565b6102f161032a366004611d11565b610a6c565b61035561033d366004611d11565b60056020526000908152604090205463ffffffff1681565b60405163ffffffff90911681526020016101d3565b610249610378366004611d11565b6001600160a01b031660009081526001602052604090205490565b6102f1610a79565b6102496103a9366004611d11565b60046020526000908152604090205481565b6000546001600160a01b0316610212565b6101c6610adf565b6101ef6103e2366004611c6b565b610aee565b6101ef6103f5366004611c6b565b610bc5565b6102f1610408366004611d11565b610bd2565b6102f161041b366004611d33565b610c93565b61024961042e366004611d93565b6001600160a01b03918216600090815260026020908152604080832093909416825291909152205490565b6102497fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf81565b6104c461048e366004611cd1565b600660209081526000928352604080842090915290825290205463ffffffff81169064010000000090046001600160e01b031682565b6040805163ffffffff90931683526001600160e01b039091166020830152016101d3565b6102f16104f6366004611d11565b610fed565b60606009805461050a90611dc6565b80601f016020809104026020016040519081016040528092919081815260200182805461053690611dc6565b80156105835780601f1061055857610100808354040283529160200191610583565b820191906000526020600020905b81548152906001019060200180831161056657829003601f168201915b5050505050905090565b600061059a3384846110cc565b5060015b92915050565b60006105b1848484611227565b6001600160a01b0384166000908152600260209081526040808320338452909152902054828110156106765760405162461bcd60e51b815260206004820152604960248201527f464c4f4b493a7472616e7366657246726f6d3a414c4c4f57414e43455f45584360448201527f45454445443a205472616e7366657220616d6f756e742065786365656473206160648201527f6c6c6f77616e63652e0000000000000000000000000000000000000000000000608482015260a4015b60405180910390fd5b61068385338584036110cc565b506001949350505050565b6000438263ffffffff16106107315760405162461bcd60e51b815260206004820152604e60248201527f464c4f4b493a676574566f7465734174426c6f636b3a4655545552455f424c4f60448201527f434b3a2043616e6e6f742067657420766f746573206174206120626c6f636b2060648201527f696e20746865206675747572652e000000000000000000000000000000000000608482015260a40161066d565b6001600160a01b03831660009081526005602052604090205463ffffffff168061075f57600091505061059e565b6001600160a01b038416600090815260066020526040812063ffffffff85169161078a600185611e17565b63ffffffff908116825260208201929092526040016000205416116107fe576001600160a01b0384166000908152600660205260408120906107cd600184611e17565b63ffffffff16815260208101919091526040016000205464010000000090046001600160e01b0316915061059e9050565b6001600160a01b038416600090815260066020908152604080832083805290915290205463ffffffff8085169116111561083c57600091505061059e565b60008061084a600184611e17565b90505b8163ffffffff168163ffffffff161115610922576000600261086f8484611e17565b6108799190611e3c565b6108839083611e17565b6001600160a01b038816600090815260066020908152604080832063ffffffff8581168552908352928190208151808301909252548084168083526401000000009091046001600160e01b03169282019290925292935090881614156108f35760200151945061059e9350505050565b805163ffffffff8089169116101561090d5781935061091b565b610918600183611e17565b92505b505061084d565b506001600160a01b038516600090815260066020908152604080832063ffffffff909416835292905220546001600160e01b036401000000009091041691505092915050565b3360008181526002602090815260408083206001600160a01b0387168452909152812054909161059a91859061099f908690611e6d565b6110cc565b6000546001600160a01b031633146109fe5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b600780546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff1983168117909355604080519190921680825260208201939093527ed910c9481701ba32afe0c247572aaece27072f230c8ec769bf245fc0b38de691015b60405180910390a15050565b610a7633826117c2565b50565b6000546001600160a01b03163314610ad35760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b610add6000611861565b565b6060600a805461050a90611dc6565b3360009081526002602090815260408083206001600160a01b038616845290915281205482811015610bae5760405162461bcd60e51b815260206004820152605760248201527f464c4f4b493a6465637265617365416c6c6f77616e63653a414c4c4f57414e4360448201527f455f554e444552464c4f573a205375627472616374696f6e20726573756c747360648201527f20696e207375622d7a65726f20616c6c6f77616e63652e000000000000000000608482015260a40161066d565b610bbb33858584036110cc565b5060019392505050565b600061059a338484611227565b6000546001600160a01b03163314610c2c5760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b600880546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff1983168117909355604080519190921680825260208201939093527f1bf87992a35ee29395ab494f9adb9a500a7fa60c3082cba0ef02701bb35900d99101610a60565b60007f8cad95687ba82c2ce50e74f7b754645e5117c3a5bec8151c0726d5857980a866610cbe6104fb565b8051602091820120604080518084019490945283810191909152466060840152306080808501919091528151808503909101815260a0840182528051908301207fe48329057bfd03d55e49b547132e39cffd9c1820ad7b9d4c5307691425d15adf60c08501526001600160a01b038b1660e085015261010084018a90526101208085018a90528251808603909101815261014085019092528151919092012061190160f01b61016084015261016283018290526101828301819052909250906000906101a20160408051601f198184030181528282528051602091820120600080855291840180845281905260ff8a169284019290925260608301889052608083018790529092509060019060a0016020604051602081039080840390855afa158015610def573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610e9e5760405162461bcd60e51b815260206004820152604660248201527f464c4f4b493a64656c656761746542795369673a494e56414c49445f5349474e60448201527f41545552453a205265636569766564207369676e61747572652077617320696e60648201527f76616c69642e0000000000000000000000000000000000000000000000000000608482015260a40161066d565b87421115610f3a5760405162461bcd60e51b815260206004820152604660248201527f464c4f4b493a64656c656761746542795369673a455850495245445f5349474e60448201527f41545552453a205265636569766564207369676e61747572652068617320657860648201527f70697265642e0000000000000000000000000000000000000000000000000000608482015260a40161066d565b6001600160a01b0381166000908152600460205260408120805491610f5e83611e85565b919050558914610fd65760405162461bcd60e51b815260206004820152603e60248201527f464c4f4b493a64656c656761746542795369673a494e56414c49445f4e4f4e4360448201527f453a205265636569766564206e6f6e63652077617320696e76616c69642e0000606482015260840161066d565b610fe0818b6117c2565b505050505b505050505050565b6000546001600160a01b031633146110475760405162461bcd60e51b815260206004820181905260248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e6572604482015260640161066d565b6001600160a01b0381166110c35760405162461bcd60e51b815260206004820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f6464726573730000000000000000000000000000000000000000000000000000606482015260840161066d565b610a7681611861565b6001600160a01b0383166111485760405162461bcd60e51b815260206004820152603f60248201527f464c4f4b493a5f617070726f76653a4f574e45525f5a45524f3a2043616e6e6f60448201527f7420617070726f766520666f7220746865207a65726f20616464726573732e00606482015260840161066d565b6001600160a01b0382166111c6576040805162461bcd60e51b81526020600482015260248101919091527f464c4f4b493a5f617070726f76653a5350454e4445525f5a45524f3a2043616e60448201527f6e6f7420617070726f766520746f20746865207a65726f20616464726573732e606482015260840161066d565b6001600160a01b0383811660008181526002602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b6001600160a01b0383166112ad5760405162461bcd60e51b815260206004820152604160248201527f464c4f4b493a5f7472616e736665723a46524f4d5f5a45524f3a2043616e6e6f60448201527f74207472616e736665722066726f6d20746865207a65726f20616464726573736064820152601760f91b608482015260a40161066d565b6001600160a01b0382166113295760405162461bcd60e51b815260206004820152603d60248201527f464c4f4b493a5f7472616e736665723a544f5f5a45524f3a2043616e6e6f742060448201527f7472616e7366657220746f20746865207a65726f20616464726573732e000000606482015260840161066d565b600081116113c55760405162461bcd60e51b815260206004820152604760248201527f464c4f4b493a5f7472616e736665723a5a45524f5f414d4f554e543a2054726160448201527f6e7366657220616d6f756e74206d75737420626520677265617465722074686160648201527f6e207a65726f2e00000000000000000000000000000000000000000000000000608482015260a40161066d565b6001600160a01b0383166000908152600160205260409020548111156114795760405162461bcd60e51b815260206004820152604660248201527f464c4f4b493a5f7472616e736665723a494e53554646494349454e545f42414c60448201527f414e43453a205472616e7366657220616d6f756e74206578636565647320626160648201527f6c616e63652e0000000000000000000000000000000000000000000000000000608482015260a40161066d565b6008546040517fc6512cc10000000000000000000000000000000000000000000000000000000081526001600160a01b0385811660048301528481166024830152604482018490529091169063c6512cc190606401600060405180830381600087803b1580156114e857600080fd5b505af11580156114fc573d6000803e3d6000fd5b50506007546040517fd7ad21ac0000000000000000000000000000000000000000000000000000000081526001600160a01b03878116600483015286811660248301526044820186905260009450909116915063d7ad21ac90606401602060405180830381865afa158015611575573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906115999190611ea0565b905060006115a78284611eb9565b6001600160a01b0386166000908152600160205260408120805492935085929091906115d4908490611eb9565b90915550506001600160a01b03841660009081526001602052604081208054839290611601908490611e6d565b90915550506001600160a01b03808616600090815260036020526040808220548784168352912054611638929182169116836118be565b81156116e7576008546001600160a01b031660009081526001602052604081208054849290611668908490611e6d565b90915550506001600160a01b0380861660009081526003602052604080822054600854841683529120546116a1929182169116846118be565b6008546040518381526001600160a01b03918216918716907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef9060200160405180910390a35b6008546040517fe613b1cd0000000000000000000000000000000000000000000000000000000081526001600160a01b0387811660048301528681166024830152604482018690529091169063e613b1cd90606401600060405180830381600087803b15801561175657600080fd5b505af115801561176a573d6000803e3d6000fd5b50505050836001600160a01b0316856001600160a01b03167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516117b391815260200190565b60405180910390a35050505050565b6001600160a01b038281166000818152600360208181526040808420805460018452948290205493835287871673ffffffffffffffffffffffffffffffffffffffff198616811790915581519586529390951690840181905293830191909152907f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9060600160405180910390a161185b8284836118be565b50505050565b600080546001600160a01b0383811673ffffffffffffffffffffffffffffffffffffffff19831681178455604051919092169283917f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e09190a35050565b816001600160a01b0316836001600160a01b031614156118dd57505050565b6001600160e01b0381166118f057505050565b6001600160a01b03831615611998576001600160a01b03831660009081526005602052604081205463ffffffff16908161192b576000611978565b6001600160a01b03851660009081526006602052604081209061194f600185611e17565b63ffffffff16815260208101919091526040016000205464010000000090046001600160e01b03165b905060006119868483611ed0565b905061199486848484611a41565b5050505b6001600160a01b03821615611a3c576001600160a01b03821660009081526005602052604081205463ffffffff1690816119d3576000611a20565b6001600160a01b0384166000908152600660205260408120906119f7600185611e17565b63ffffffff16815260208101919091526040016000205464010000000090046001600160e01b03165b90506000611a2e8483611ef0565b9050610fe585848484611a41565b505050565b4363ffffffff841615801590611a9957506001600160a01b038516600090815260066020526040812063ffffffff831691611a7d600188611e17565b63ffffffff908116825260208201929092526040016000205416145b15611b09576001600160a01b03851660009081526006602052604081208391611ac3600188611e17565b63ffffffff1663ffffffff16815260200190815260200160002060000160046101000a8154816001600160e01b0302191690836001600160e01b03160217905550611ba1565b60408051808201825263ffffffff80841682526001600160e01b0380861660208085019182526001600160a01b038b166000908152600682528681208b86168252909152949094209251935116640100000000029216919091179055611b70846001611f1b565b6001600160a01b0386166000908152600560205260409020805463ffffffff191663ffffffff929092169190911790555b604080516001600160a01b03871681526001600160e01b03858116602083015284168183015290517fda5a64c2947c0b7bf4d6e7bf736c6f84d9d1c5f991770f88bbeb3fe19c85a1349181900360600190a15050505050565b600060208083528351808285015260005b81811015611c2757858101830151858201604001528201611c0b565b81811115611c39576000604083870101525b50601f01601f1916929092016040019392505050565b80356001600160a01b0381168114611c6657600080fd5b919050565b60008060408385031215611c7e57600080fd5b611c8783611c4f565b946020939093013593505050565b600080600060608486031215611caa57600080fd5b611cb384611c4f565b9250611cc160208501611c4f565b9150604084013590509250925092565b60008060408385031215611ce457600080fd5b611ced83611c4f565b9150602083013563ffffffff81168114611d0657600080fd5b809150509250929050565b600060208284031215611d2357600080fd5b611d2c82611c4f565b9392505050565b60008060008060008060c08789031215611d4c57600080fd5b611d5587611c4f565b95506020870135945060408701359350606087013560ff81168114611d7957600080fd5b9598949750929560808101359460a0909101359350915050565b60008060408385031215611da657600080fd5b611daf83611c4f565b9150611dbd60208401611c4f565b90509250929050565b600181811c90821680611dda57607f821691505b60208210811415611dfb57634e487b7160e01b600052602260045260246000fd5b50919050565b634e487b7160e01b600052601160045260246000fd5b600063ffffffff83811690831681811015611e3457611e34611e01565b039392505050565b600063ffffffff80841680611e6157634e487b7160e01b600052601260045260246000fd5b92169190910492915050565b60008219821115611e8057611e80611e01565b500190565b6000600019821415611e9957611e99611e01565b5060010190565b600060208284031215611eb257600080fd5b5051919050565b600082821015611ecb57611ecb611e01565b500390565b60006001600160e01b0383811690831681811015611e3457611e34611e01565b60006001600160e01b03808316818516808303821115611f1257611f12611e01565b01949350505050565b600063ffffffff808316818516808303821115611f1257611f12611e0156fea164736f6c634300080b000a000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004491c4c1d1bf636057eab66cd986da08f619bd56000000000000000000000000d2a64b48b33ff641058719d2b3fa0f9ee5c243680000000000000000000000000000000000000000000000000000000000000005464c4f4b490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005464c4f4b49000000000000000000000000000000000000000000000000000000","name":"FLOKI","is_blueprint":false,"license_type":"none","is_fully_verified":true,"is_verified_via_eth_bytecode_db":true,"language":"solidity","evm_version":"london","can_be_visualized_via_sol2uml":true,"is_verified_via_sourcify":false,"additional_sources":[{"file_path":"@openzeppelin/contracts/access/Ownable.sol","source_code":"// SPDX-License-Identifier: MIT\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        _setOwner(_msgSender());\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 called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n        _;\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        _setOwner(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        _setOwner(newOwner);\n    }\n\n    function _setOwner(address newOwner) private {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"},{"file_path":"@openzeppelin/contracts/token/ERC20/IERC20.sol","source_code":"// SPDX-License-Identifier: MIT\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Interface of the ERC20 standard as defined in the EIP.\n */\ninterface IERC20 {\n    /**\n     * @dev Returns the amount of tokens in existence.\n     */\n    function totalSupply() external view returns (uint256);\n\n    /**\n     * @dev Returns the amount of tokens owned by `account`.\n     */\n    function balanceOf(address account) external view returns (uint256);\n\n    /**\n     * @dev Moves `amount` tokens from the caller's account to `recipient`.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transfer(address recipient, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Returns the remaining number of tokens that `spender` will be\n     * allowed to spend on behalf of `owner` through {transferFrom}. This is\n     * zero by default.\n     *\n     * This value changes when {approve} or {transferFrom} are called.\n     */\n    function allowance(address owner, address spender) external view returns (uint256);\n\n    /**\n     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * IMPORTANT: Beware that changing an allowance with this method brings the risk\n     * that someone may use both the old and the new allowance by unfortunate\n     * transaction ordering. One possible solution to mitigate this race\n     * condition is to first reduce the spender's allowance to 0 and set the\n     * desired value afterwards:\n     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729\n     *\n     * Emits an {Approval} event.\n     */\n    function approve(address spender, uint256 amount) external returns (bool);\n\n    /**\n     * @dev Moves `amount` tokens from `sender` to `recipient` using the\n     * allowance mechanism. `amount` is then deducted from the caller's\n     * allowance.\n     *\n     * Returns a boolean value indicating whether the operation succeeded.\n     *\n     * Emits a {Transfer} event.\n     */\n    function transferFrom(\n        address sender,\n        address recipient,\n        uint256 amount\n    ) external returns (bool);\n\n    /**\n     * @dev Emitted when `value` tokens are moved from one account (`from`) to\n     * another (`to`).\n     *\n     * Note that `value` may be zero.\n     */\n    event Transfer(address indexed from, address indexed to, uint256 value);\n\n    /**\n     * @dev Emitted when the allowance of a `spender` for an `owner` is set by\n     * a call to {approve}. `value` is the new allowance.\n     */\n    event Approval(address indexed owner, address indexed spender, uint256 value);\n}\n"},{"file_path":"@openzeppelin/contracts/utils/Context.sol","source_code":"// SPDX-License-Identifier: MIT\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"},{"file_path":"contracts/governance/IGovernanceToken.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.11;\r\n\r\n/**\r\n * @title Governance token interface.\r\n */\r\ninterface IGovernanceToken {\r\n    /// @notice A checkpoint for marking number of votes as of a given block.\r\n    struct Checkpoint {\r\n        // The 32-bit unsigned integer is valid until these estimated dates for these given chains:\r\n        //  - BSC: Sat Dec 23 2428 18:23:11 UTC\r\n        //  - ETH: Tue Apr 18 3826 09:27:12 UTC\r\n        // This assumes that block mining rates don't speed up.\r\n        uint32 blockNumber;\r\n        // This type is set to `uint224` for optimizations purposes (i.e., specifically to fit in a 32-byte block). It\r\n        // assumes that the number of votes for the implementing governance token never exceeds the maximum value for a\r\n        // 224-bit number.\r\n        uint224 votes;\r\n    }\r\n\r\n    /**\r\n     * @notice Determine the number of votes for an account as of a block number.\r\n     * @dev Block number must be a finalized block or else this function will revert to prevent misinformation.\r\n     * @param account The address of the account to check.\r\n     * @param blockNumber The block number to get the vote balance at.\r\n     * @return The number of votes the account had as of the given block.\r\n     */\r\n    function getVotesAtBlock(address account, uint32 blockNumber) external view returns (uint224);\r\n\r\n    /// @notice Emitted whenever a new delegate is set for an account.\r\n    event DelegateChanged(address delegator, address currentDelegate, address newDelegate);\r\n\r\n    /// @notice Emitted when a delegate's vote count changes.\r\n    event DelegateVotesChanged(address delegatee, uint224 oldVotes, uint224 newVotes);\r\n}\r\n"},{"file_path":"contracts/tax/ITaxHandler.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.11;\r\n\r\n/**\r\n * @title Tax handler interface\r\n * @dev Any class that implements this interface can be used for protocol-specific tax calculations.\r\n */\r\ninterface ITaxHandler {\r\n    /**\r\n     * @notice Get number of tokens to pay as tax.\r\n     * @param benefactor Address of the benefactor.\r\n     * @param beneficiary Address of the beneficiary.\r\n     * @param amount Number of tokens in the transfer.\r\n     * @return Number of tokens to pay as tax.\r\n     */\r\n    function getTax(\r\n        address benefactor,\r\n        address beneficiary,\r\n        uint256 amount\r\n    ) external view returns (uint256);\r\n}\r\n"},{"file_path":"contracts/treasury/ITreasuryHandler.sol","source_code":"// SPDX-License-Identifier: MIT\r\npragma solidity 0.8.11;\r\n\r\n/**\r\n * @title Treasury handler interface\r\n * @dev Any class that implements this interface can be used for protocol-specific operations pertaining to the treasury.\r\n */\r\ninterface ITreasuryHandler {\r\n    /**\r\n     * @notice Perform operations before a transfer is executed.\r\n     * @param benefactor Address of the benefactor.\r\n     * @param beneficiary Address of the beneficiary.\r\n     * @param amount Number of tokens in the transfer.\r\n     */\r\n    function beforeTransferHandler(\r\n        address benefactor,\r\n        address beneficiary,\r\n        uint256 amount\r\n    ) external;\r\n\r\n    /**\r\n     * @notice Perform operations after a transfer is executed.\r\n     * @param benefactor Address of the benefactor.\r\n     * @param beneficiary Address of the beneficiary.\r\n     * @param amount Number of tokens in the transfer.\r\n     */\r\n    function afterTransferHandler(\r\n        address benefactor,\r\n        address beneficiary,\r\n        uint256 amount\r\n    ) external;\r\n}\r\n"}],"certified":false,"conflicting_implementations":null,"abi":[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"address","name":"taxHandlerAddress","type":"address"},{"internalType":"address","name":"treasuryHandlerAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"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":false,"internalType":"address","name":"delegator","type":"address"},{"indexed":false,"internalType":"address","name":"currentDelegate","type":"address"},{"indexed":false,"internalType":"address","name":"newDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"delegatee","type":"address"},{"indexed":false,"internalType":"uint224","name":"oldVotes","type":"uint224"},{"indexed":false,"internalType":"uint224","name":"newVotes","type":"uint224"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"TaxHandlerChanged","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"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAddress","type":"address"},{"indexed":false,"internalType":"address","name":"newAddress","type":"address"}],"name":"TreasuryHandlerChanged","type":"event"},{"inputs":[],"name":"DELEGATION_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DOMAIN_TYPEHASH","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"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":[{"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":"","type":"address"},{"internalType":"uint32","name":"","type":"uint32"}],"name":"checkpoints","outputs":[{"internalType":"uint32","name":"blockNumber","type":"uint32"},{"internalType":"uint224","name":"votes","type":"uint224"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","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":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"delegateBySig","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint32","name":"blockNumber","type":"uint32"}],"name":"getVotesAtBlock","outputs":[{"internalType":"uint224","name":"","type":"uint224"}],"stateMutability":"view","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":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"numCheckpoints","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"taxHandlerAddress","type":"address"}],"name":"setTaxHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"treasuryHandlerAddress","type":"address"}],"name":"setTreasuryHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"taxHandler","outputs":[{"internalType":"contract ITaxHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"treasuryHandler","outputs":[{"internalType":"contract ITreasuryHandler","name":"","type":"address"}],"stateMutability":"view","type":"function"}],"is_changed_bytecode":false,"is_partially_verified":false,"constructor_args":"0x000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000004491c4c1d1bf636057eab66cd986da08f619bd56000000000000000000000000d2a64b48b33ff641058719d2b3fa0f9ee5c243680000000000000000000000000000000000000000000000000000000000000005464c4f4b490000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000005464c4f4b49000000000000000000000000000000000000000000000000000000"}