Cryo Explorer Ethereum Mainnet

Address Contract Verified

Address 0x053A4EC128d6788dfE5b1f89dd6a6019E0532f2D
Balance 0 ETH
Nonce 1
Code Size 8654 bytes
Indexed Transactions 0
External Etherscan · Sourcify

Contract Bytecode

8654 bytes
0x6080806040526004361015610059575b50361561001a575f80fd5b60ff600754161561002757005b60405162461bcd60e51b815260206004820152600a602482015269141c9bda1a589a5d195960b21b6044820152606490fd5b5f3560e01c90816306fdde031461173357508063095ea7b31461168657806318160ddd14611669578063191a48451461161757806323b872dd1461150d578063249b7c19146114d357806328a678b1146113ee578063313ce567146113d35780634020b317146113995780634555a5aa146112865780634632f560146112185780634f5f21cf146111de57806361d027b31461119a57806363e1289b1461106b5780636a576112146110095780636b7cbf1114610fcf57806370a0823114610f97578063756c79db14610c3457806395d89b4114610b30578063a1af3e5e14610b04578063a7c6402c14610ad6578063a9059cbb14610a7a578063b753bfe914610a36578063bd977c75146109ea578063c154b2851461091f578063c841c4af1461054a578063cab64bcd14610506578063cc32d4da1461038f578063d0e30db014610324578063d5d0e9eb146102d6578063d7e66d141461029c578063dd62ed3e1461024c578063ed338ff1146102125763f75a854e146101db575f61000f565b3461020e5760206102066101f76101f136611898565b90611e27565b670de0b6b3a764000090611e3a565b604051908152f35b5f80fd5b3461020e575f36600319011261020e5760206040517f000000000000000000000000000000000000000000000000000000006955b8ff8152f35b3461020e57604036600319011261020e57610265611815565b61026d61182b565b6001600160a01b039182165f908152600160209081526040808320949093168252928352819020549051908152f35b3461020e575f36600319011261020e5760206040517f00000000000000000000000000000000000000000000000000000000000001f48152f35b3461020e575f36600319011261020e576001600160a01b037f00000000000000000000000023038526217fe168e46ac887cf9ebf80a2e93589165f9081526020818152604090912054610206565b5f36600319011261020e57610363337f000000000000000000000000d0b1d8125de0f8a9f3c0f60b4d6197e6adc1f2b66001600160a01b03161461195a565b7fa1ab46d0e38f33a7b1f03853088a305927deb55c906370ff5d6d2bc732f150956020604051348152a1005b3461020e57602036600319011261020e576004356103ce7f000000000000000000000000000000000000000000000000000000006955b8ff42116118e4565b6103f97f000000000000000000000000000000000000000000000000000000006b36ec7f4210611a38565b610401611edc565b61040c811515611e58565b335f5260066020528060405f2054106104b05761044c6101f77f000000000000000000000000000000000000000000000000000016bcc41e900083611e27565b809161047782159161045e8315611e9b565b335f52600660205260405f2081815403905530336120ee565b5f906104a7575b5f80809381933390f11561049c576020906001600555604051908152f35b6040513d5f823e3d90fd5b506108fc61047e565b60405162461bcd60e51b815260206004820152602860248201527f496e73756666696369656e742070726573616c65206275796261636b20656c69604482015267676962696c69747960c01b6064820152608490fd5b3461020e575f36600319011261020e576040517f00000000000000000000000023038526217fe168e46ac887cf9ebf80a2e935896001600160a01b03168152602090f35b3461020e57608036600319011261020e57610563611815565b60243560443567ffffffffffffffff811161020e57610586903690600401611867565b606492919235936105b97f000000000000000000000000000000000000000000000000000000006955b8ff421115611921565b6105e47f00000000000000000000000000000000000000000000000000000000692e2bff42116119f8565b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b039190911693906020816064815f895af1801561049c57610633915f91610900575b50611ad0565b60405163095ea7b360e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d6004820152602481018490526020816044815f895af1801561049c57610682915f916108e1575b50611b1c565b600282018083116108085761069690611b91565b91846106a184611bc3565b525f5b8181106108a55750506040516315ab88c960e31b8152939050602084600481737a250d5630b4cf539739df2c5dacb4c659f2488d5afa93841561049c575f94610874575b5081515f198101949085116108085761070461073f9584611be4565b9060018060a01b031690525f4793600160ff196007541617600755604051809681926318cbafe560e01b83524290878b309260048701611ca3565b038183737a250d5630b4cf539739df2c5dacb4c659f2488d5af193841561049c575f9461084b575b5060205f9160ff196007541660075560446040518094819363095ea7b360e01b8352737a250d5630b4cf539739df2c5dacb4c659f2488d60048401528160248401525af1801561049c576107c2915f9161081c575b50611d0b565b515f19810192908311610808576020936107fb6107f5936107e96102069661080295611be4565b51948593841015611d6f565b47611c1c565b1015611dcb565b33611efc565b634e487b7160e01b5f52601160045260245ffd5b61083e915060203d602011610844575b61083681836118ae565b810190611ab8565b866107bc565b503d61082c565b5f91945061086c6020913d8085833e61086481836118ae565b810190611c29565b949150610767565b61089791945060203d60201161089e575b61088f81836118ae565b810190611996565b92856106e8565b503d610885565b6108b86108b3828486611bf8565b611c08565b906001810191828211610808576108d160019387611be4565b90838060a01b03169052016106a4565b6108fa915060203d6020116108445761083681836118ae565b8761067c565b610919915060203d6020116108445761083681836118ae565b8761062d565b3461020e57602036600319011261020e577f29d244d11de399832a378f3590408ea4c6aa2b1af6230d5fbc74a35d83df1143602060043561098a337f000000000000000000000000d0b1d8125de0f8a9f3c0f60b4d6197e6adc1f2b66001600160a01b03161461195a565b6109b67f000000000000000000000000000000000000000000000000000000006955b8ff421115611921565b6109e181307f00000000000000000000000081ddebe780e4b27395e7bbc55017fc2fd0d2a9966120ee565b604051908152a1005b602036600319011261020e576020610206610a03611815565b610a2f7f00000000000000000000000000000000000000000000000000000000692e2bff421115611a7c565b3433611f58565b3461020e575f36600319011261020e576040517f00000000000000000000000081ddebe780e4b27395e7bbc55017fc2fd0d2a9966001600160a01b03168152602090f35b3461020e57604036600319011261020e57610acb610a96611815565b610ac17f000000000000000000000000000000000000000000000000000000006955b8ff42116118e4565b60243590336120ee565b602060405160018152f35b3461020e575f36600319011261020e576020604051737a250d5630b4cf539739df2c5dacb4c659f2488d8152f35b3461020e576020610206610b2b610b1a36611898565b9190670de0b6b3a764000090611e27565b611e3a565b3461020e575f36600319011261020e576040515f6004548060011c90600181168015610c2a575b602083108114610c1657828552908115610bf25750600114610b94575b610b9083610b84818503826118ae565b604051918291826117eb565b0390f35b91905060045f527f8a35acfbc15ff81a39ae7d344fd709f28e8600b4aa8c65c6b64bfe7fe36bd19b915f905b808210610bd857509091508101602001610b84610b74565b919260018160209254838588010152019101909291610bc0565b60ff191660208086019190915291151560051b84019091019150610b849050610b74565b634e487b7160e01b5f52602260045260245ffd5b91607f1691610b57565b3461020e5760a036600319011261020e57610c4d611815565b60243560443567ffffffffffffffff811161020e57610c70903690600401611867565b606435939192608435929091906001600160a01b038416840361020e57610cb97f00000000000000000000000000000000000000000000000000000000692e2bff421115611a7c565b6040516323b872dd60e01b8152336004820152306024820152604481018490526001600160a01b039190911694906020816064815f8a5af1801561049c57610d07915f91610f785750611ad0565b60405163095ea7b360e01b8152737a250d5630b4cf539739df2c5dacb4c659f2488d6004820152602481018490526020816044815f8a5af1801561049c57610d55915f91610f595750611b1c565b6002820180831161080857610d6990611b91565b9185610d7484611bc3565b525f5b818110610f225750506040516315ab88c960e31b8152949050602085600481737a250d5630b4cf539739df2c5dacb4c659f2488d5afa94851561049c575f95610f01575b5081515f1981019590861161080857610dd7610e129684611be4565b9060018060a01b031690525f4793600160ff196007541617600755604051809781926318cbafe560e01b83524290878c309260048701611ca3565b038183737a250d5630b4cf539739df2c5dacb4c659f2488d5af194851561049c575f95610ee0575b5060205f9160ff196007541660075560446040518094819363095ea7b360e01b8352737a250d5630b4cf539739df2c5dacb4c659f2488d60048401528160248401525af1801561049c57610e94915f91610ec15750611d0b565b515f19810193908411610808576020946107fb6107f5936107e961020697610ebb95611be4565b33611f58565b610eda915060203d6020116108445761083681836118ae565b876107bc565b5f919550610ef96020913d8085833e61086481836118ae565b959150610e3a565b610f1b91955060203d60201161089e5761088f81836118ae565b9386610dbb565b610f306108b3828486611bf8565b90600181019182821161080857610f4960019387611be4565b90838060a01b0316905201610d77565b610f72915060203d6020116108445761083681836118ae565b8861067c565b610f91915060203d6020116108445761083681836118ae565b8861062d565b3461020e57602036600319011261020e576020610206610fb5611815565b6001600160a01b03165f9081526020819052604090205490565b3461020e575f36600319011261020e5760206040517f00000000000000000000000000000000000000000000000000002d79883d20008152f35b3461020e57602036600319011261020e57611022611815565b61104d7f000000000000000000000000000000000000000000000000000000006b36ec7f4210611a38565b60018060a01b03165f526006602052602060405f2054604051908152f35b3461020e575f36600319011261020e576110af337f000000000000000000000000d0b1d8125de0f8a9f3c0f60b4d6197e6adc1f2b66001600160a01b03161461195a565b6110da7f000000000000000000000000000000000000000000000000000000006955b8ff42116118e4565b305f525f60205260405f2054301561118757305f525f60205260405f205481811061116e57817fea2cd71ff9f81e81845e4657ef26f3929886b98613e064faa2dc3105cbb9a7ad92602092305f525f84520360405f205580600254036002555f6040518281527fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef843092a3604051908152a1005b63391434e360e21b5f523060045260245260445260645ffd5b634b637e8f60e11b5f525f60045260245ffd5b3461020e575f36600319011261020e576040517f000000000000000000000000d0b1d8125de0f8a9f3c0f60b4d6197e6adc1f2b66001600160a01b03168152602090f35b3461020e575f36600319011261020e5760206040517f000000000000000000000000000000000000000000000000000016bcc41e90008152f35b5f36600319011261020e5761124f7f000000000000000000000000000000000000000000000000000000006955b8ff421115611921565b61127a7f00000000000000000000000000000000000000000000000000000000692e2bff42116119f8565b60206102063433611efc565b3461020e5761129436611841565b906112c9337f000000000000000000000000d0b1d8125de0f8a9f3c0f60b4d6197e6adc1f2b66001600160a01b03161461195a565b6112d1611edc565b6040516315daf18f60e11b8152906001600160a01b0316602082600481845afa91821561049c57602092611317915f9161137c575b506001600160a01b031630146119b5565b60046040518094819363023197ab60e51b83525af1801561049c575f90611349575b6020906001600555604051908152f35b506020813d602011611374575b81611363602093836118ae565b8101031261020e5760209051611339565b3d9150611356565b6113939150843d861161089e5761088f81836118ae565b85611306565b3461020e575f36600319011261020e5760206040517f000000000000000000000000000000000000000000000000000000006b36ec7f8152f35b3461020e575f36600319011261020e57602060405160128152f35b3461020e576113fc36611841565b90611431337f000000000000000000000000d0b1d8125de0f8a9f3c0f60b4d6197e6adc1f2b66001600160a01b03161461195a565b611439611edc565b6040516315daf18f60e11b8152906001600160a01b0316602082600481845afa801561049c575f9361148160249260209587916114b657506001600160a01b031630146119b5565b604051948593849263f417fbed60e01b845260048401525af1801561049c575f90611349576020906001600555604051908152f35b6114cd9150863d881161089e5761088f81836118ae565b87611306565b3461020e575f36600319011261020e5760206040517f00000000000000000000000000000000000000000000000000000000692e2bff8152f35b3461020e57606036600319011261020e57611526611815565b61152e61182b565b6044359061155d7f000000000000000000000000000000000000000000000000000000006955b8ff42116118e4565b6001600160a01b0383165f8181526001602090815260408083203384529091529020549093905f198110611597575b50610acb93506120ee565b8381106115fc5784156115e95733156115d657610acb945f52600160205260405f2060018060a01b0333165f526020528360405f20910390558461158c565b634a1406b160e11b5f525f60045260245ffd5b63e602df0560e01b5f525f60045260245ffd5b8390637dc7a0d960e11b5f523360045260245260445260645ffd5b3461020e575f36600319011261020e576116537f000000000000000000000000000000000000000000000000000000006955b8ff421115611921565b305f525f602052602060405f2054604051908152f35b3461020e575f36600319011261020e576020600254604051908152f35b3461020e57604036600319011261020e5761169f611815565b602435906116ce7f000000000000000000000000000000000000000000000000000000006955b8ff42116118e4565b33156115e9576001600160a01b03169081156115d657335f52600160205260405f20825f526020528060405f20556040519081527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560203392a3602060405160018152f35b3461020e575f36600319011261020e575f6003548060011c906001811680156117e1575b602083108114610c1657828552908115610bf2575060011461178357610b9083610b84818503826118ae565b91905060035f527fc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b915f905b8082106117c757509091508101602001610b84610b74565b9192600181602092548385880101520191019092916117af565b91607f1691611757565b602060409281835280519182918282860152018484015e5f828201840152601f01601f1916010190565b600435906001600160a01b038216820361020e57565b602435906001600160a01b038216820361020e57565b604090600319011261020e576004356001600160a01b038116810361020e579060243590565b9181601f8401121561020e5782359167ffffffffffffffff831161020e576020808501948460051b01011161020e57565b604090600319011261020e576004359060243590565b90601f8019910116810190811067ffffffffffffffff8211176118d057604052565b634e487b7160e01b5f52604160045260245ffd5b156118eb57565b60405162461bcd60e51b815260206004820152600e60248201526d14d85b19481b9bdd08195b99195960921b6044820152606490fd5b1561192857565b60405162461bcd60e51b815260206004820152600a60248201526914d85b1948195b99195960b21b6044820152606490fd5b1561196157565b60405162461bcd60e51b815260206004820152600d60248201526c1058d8d95cdcc819195b9a5959609a1b6044820152606490fd5b9081602091031261020e57516001600160a01b038116810361020e5790565b156119bc57565b60405162461bcd60e51b815260206004820152601460248201527324b73b30b634b210313934b233b2903a37b5b2b760611b6044820152606490fd5b156119ff57565b60405162461bcd60e51b8152602060048201526011602482015270141c995cd85b19481b9bdd08195b991959607a1b6044820152606490fd5b15611a3f57565b60405162461bcd60e51b8152602060048201526015602482015274141c995cd85b1948189d5e589858dac8195b991959605a1b6044820152606490fd5b15611a8357565b60405162461bcd60e51b815260206004820152600d60248201526c141c995cd85b1948195b991959609a1b6044820152606490fd5b9081602091031261020e5751801515810361020e5790565b15611ad757565b60405162461bcd60e51b815260206004820152601f60248201527f4661696c656420746f207472616e7366657220696e70757420746f6b656e73006044820152606490fd5b15611b2357565b60405162461bcd60e51b815260206004820152602860248201527f4661696c656420746f20617070726f766520696e70757420746f6b656e73207460448201526737903937baba32b960c11b6064820152608490fd5b67ffffffffffffffff81116118d05760051b60200190565b90611b9b82611b79565b611ba860405191826118ae565b8281528092611bb9601f1991611b79565b0190602036910137565b805115611bd05760200190565b634e487b7160e01b5f52603260045260245ffd5b8051821015611bd05760209160051b010190565b9190811015611bd05760051b0190565b356001600160a01b038116810361020e5790565b9190820391821161080857565b60208183031261020e5780519067ffffffffffffffff821161020e57019080601f8301121561020e578151611c5d81611b79565b92611c6b60405194856118ae565b81845260208085019260051b82010192831161020e57602001905b828210611c935750505090565b8151815260209182019101611c86565b92919594939560a08401918452602084015260a060408401528151809152602060c084019201905f5b818110611cec575050506001600160a01b03909416606082015260800152565b82516001600160a01b0316845260209384019390920191600101611ccc565b15611d1257565b60405162461bcd60e51b815260206004820152602f60248201527f4661696c656420746f20726573657420696e70757420746f6b656e732061707060448201526e3937bb30b6103a37903937baba32b960891b6064820152608490fd5b15611d7657565b60405162461bcd60e51b815260206004820152602760248201527f53776170206f75747075742045544820616d6f756e742069732062656c6f77206044820152666d696e696d756d60c81b6064820152608490fd5b15611dd257565b60405162461bcd60e51b815260206004820152602760248201527f53776170206f75747075742045544820616d6f756e7420776173206e6f7420726044820152661958d95a5d995960ca1b6064820152608490fd5b8181029291811591840414171561080857565b8115611e44570490565b634e487b7160e01b5f52601260045260245ffd5b15611e5f57565b60405162461bcd60e51b8152602060048201526014602482015273546f6b656e20616d6f756e74206973207a65726f60601b6044820152606490fd5b15611ea257565b60405162461bcd60e51b815260206004820152601260248201527145544820616d6f756e74206973207a65726f60701b6044820152606490fd5b600260055414611eed576002600555565b633ee5aeb560e01b5f5260045ffd5b90611f42611f5591611f0f811515611e9b565b610b2b670de0b6b3a76400007f00000000000000000000000000000000000000000000000000002d79883d200092611e27565b8092611f4f821515611e58565b306120ee565b90565b9190611f65811515611e9b565b6001600160a01b0383811693908316918285146120b757611fb390610b2b670de0b6b3a76400007f000000000000000000000000000000000000000000000000000016bcc41e900092611e27565b93611fbf851515611e58565b5f52600660205260405f2080549185830180931161080857611fe492869255306120ee565b7f00000000000000000000000023038526217fe168e46ac887cf9ebf80a2e935899160018060a01b0383165f525f60205260405f20549115158061208e575b80612085575b612034575b50505090565b612075926127106120657f00000000000000000000000000000000000000000000000000000000000001f487611e27565b049280841161207d575b506120ee565b5f808061202e565b92505f61206f565b50811515612029565b507f00000000000000000000000000000000000000000000000000000000000001f41515612023565b60405162461bcd60e51b815260206004820152600f60248201526e24b73b30b634b2103932b332b932b960891b6044820152606490fd5b6001600160a01b0316908115611187576001600160a01b031691821561218557815f525f60205260405f205481811061216c57817fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef92602092855f525f84520360405f2055845f525f825260405f20818154019055604051908152a3565b8263391434e360e21b5f5260045260245260445260645ffd5b63ec442f0560e01b5f525f60045260245ffdfea26469706673582212201d6f9d5b1934ef4e324749f0251aa764ea08cfd39fe53199d0898d30647eb8d464736f6c634300081c0033

Verified Source Code Full Match

Compiler: v0.8.28+commit.7893614a EVM: cancun Optimization: Yes (200 runs)
draft-IERC6093.sol 161 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (interfaces/draft-IERC6093.sol)
pragma solidity >=0.8.4;

/**
 * @dev Standard ERC-20 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
 */
interface IERC20Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC20InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC20InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     * @param allowance Amount of tokens a `spender` is allowed to operate with.
     * @param needed Minimum amount required to perform a transfer.
     */
    error ERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC20InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `spender` to be approved. Used in approvals.
     * @param spender Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC20InvalidSpender(address spender);
}

/**
 * @dev Standard ERC-721 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
 */
interface IERC721Errors {
    /**
     * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
     * Used in balance queries.
     * @param owner Address of the current owner of a token.
     */
    error ERC721InvalidOwner(address owner);

    /**
     * @dev Indicates a `tokenId` whose `owner` is the zero address.
     * @param tokenId Identifier number of a token.
     */
    error ERC721NonexistentToken(uint256 tokenId);

    /**
     * @dev Indicates an error related to the ownership over a particular token. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param tokenId Identifier number of a token.
     * @param owner Address of the current owner of a token.
     */
    error ERC721IncorrectOwner(address sender, uint256 tokenId, address owner);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC721InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC721InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param tokenId Identifier number of a token.
     */
    error ERC721InsufficientApproval(address operator, uint256 tokenId);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC721InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC721InvalidOperator(address operator);
}

/**
 * @dev Standard ERC-1155 Errors
 * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
 */
interface IERC1155Errors {
    /**
     * @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     * @param balance Current balance for the interacting account.
     * @param needed Minimum amount required to perform a transfer.
     * @param tokenId Identifier number of a token.
     */
    error ERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);

    /**
     * @dev Indicates a failure with the token `sender`. Used in transfers.
     * @param sender Address whose tokens are being transferred.
     */
    error ERC1155InvalidSender(address sender);

    /**
     * @dev Indicates a failure with the token `receiver`. Used in transfers.
     * @param receiver Address to which tokens are being transferred.
     */
    error ERC1155InvalidReceiver(address receiver);

    /**
     * @dev Indicates a failure with the `operator`’s approval. Used in transfers.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     * @param owner Address of the current owner of a token.
     */
    error ERC1155MissingApprovalForAll(address operator, address owner);

    /**
     * @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
     * @param approver Address initiating an approval operation.
     */
    error ERC1155InvalidApprover(address approver);

    /**
     * @dev Indicates a failure with the `operator` to be approved. Used in approvals.
     * @param operator Address that may be allowed to operate on tokens without being their owner.
     */
    error ERC1155InvalidOperator(address operator);

    /**
     * @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
     * Used in batch transfers.
     * @param idsLength Length of the array of token identifiers
     * @param valuesLength Length of the array of token amounts
     */
    error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}
ERC20.sol 305 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/ERC20.sol)

pragma solidity ^0.8.20;

import {IERC20} from "./IERC20.sol";
import {IERC20Metadata} from "./extensions/IERC20Metadata.sol";
import {Context} from "../../utils/Context.sol";
import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol";

/**
 * @dev Implementation of the {IERC20} interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using {_mint}.
 *
 * TIP: For a detailed writeup see our guide
 * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
 * to implement supply mechanisms].
 *
 * The default value of {decimals} is 18. To change this, you should override
 * this function so it returns a different value.
 *
 * We have followed general OpenZeppelin Contracts guidelines: functions revert
 * instead returning `false` on failure. This behavior is nonetheless
 * conventional and does not conflict with the expectations of ERC-20
 * applications.
 */
abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors {
    mapping(address account => uint256) private _balances;

    mapping(address account => mapping(address spender => uint256)) private _allowances;

    uint256 private _totalSupply;

    string private _name;
    string private _symbol;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * Both values are immutable: they can only be set once during construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual returns (string memory) {
        return _symbol;
    }

    /**
     * @dev 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 default value returned by this function, unless
     * it's 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}.
     */
    function decimals() public view virtual returns (uint8) {
        return 18;
    }

    /// @inheritdoc IERC20
    function totalSupply() public view virtual returns (uint256) {
        return _totalSupply;
    }

    /// @inheritdoc IERC20
    function balanceOf(address account) public view virtual returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See {IERC20-transfer}.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - the caller must have a balance of at least `value`.
     */
    function transfer(address to, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _transfer(owner, to, value);
        return true;
    }

    /// @inheritdoc IERC20
    function allowance(address owner, address spender) public view virtual returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `value` 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.
     */
    function approve(address spender, uint256 value) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, value);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Skips emitting an {Approval} event indicating an allowance update. This is not
     * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].
     *
     * 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 `value`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `value`.
     */
    function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, value);
        _transfer(from, to, value);
        return true;
    }

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to`.
     *
     * This internal function is equivalent to {transfer}, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a {Transfer} event.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _transfer(address from, address to, uint256 value) internal {
        if (from == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        if (to == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(from, to, value);
    }

    /**
     * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`
     * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding
     * this function.
     *
     * Emits a {Transfer} event.
     */
    function _update(address from, address to, uint256 value) internal virtual {
        if (from == address(0)) {
            // Overflow check required: The rest of the code assumes that totalSupply never overflows
            _totalSupply += value;
        } else {
            uint256 fromBalance = _balances[from];
            if (fromBalance < value) {
                revert ERC20InsufficientBalance(from, fromBalance, value);
            }
            unchecked {
                // Overflow not possible: value <= fromBalance <= totalSupply.
                _balances[from] = fromBalance - value;
            }
        }

        if (to == address(0)) {
            unchecked {
                // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.
                _totalSupply -= value;
            }
        } else {
            unchecked {
                // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.
                _balances[to] += value;
            }
        }

        emit Transfer(from, to, value);
    }

    /**
     * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).
     * Relies on the `_update` mechanism
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead.
     */
    function _mint(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidReceiver(address(0));
        }
        _update(address(0), account, value);
    }

    /**
     * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.
     * Relies on the `_update` mechanism.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * NOTE: This function is not virtual, {_update} should be overridden instead
     */
    function _burn(address account, uint256 value) internal {
        if (account == address(0)) {
            revert ERC20InvalidSender(address(0));
        }
        _update(account, address(0), value);
    }

    /**
     * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.
     *
     * This internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     *
     * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        _approve(owner, spender, value, true);
    }

    /**
     * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.
     *
     * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by
     * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any
     * `Approval` event during `transferFrom` operations.
     *
     * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to
     * true using the following override:
     *
     * ```solidity
     * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {
     *     super._approve(owner, spender, value, true);
     * }
     * ```
     *
     * Requirements are the same as {_approve}.
     */
    function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {
        if (owner == address(0)) {
            revert ERC20InvalidApprover(address(0));
        }
        if (spender == address(0)) {
            revert ERC20InvalidSpender(address(0));
        }
        _allowances[owner][spender] = value;
        if (emitEvent) {
            emit Approval(owner, spender, value);
        }
    }

    /**
     * @dev Updates `owner`'s allowance for `spender` based on spent `value`.
     *
     * Does not update the allowance value in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Does not emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 value) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance < type(uint256).max) {
            if (currentAllowance < value) {
                revert ERC20InsufficientAllowance(spender, currentAllowance, value);
            }
            unchecked {
                _approve(owner, spender, currentAllowance - value, false);
            }
        }
    }
}
IERC20.sol 79 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/IERC20.sol)

pragma solidity >=0.4.16;

/**
 * @dev Interface of the ERC-20 standard as defined in the ERC.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the value of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the value of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves a `value` amount of tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 value) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets a `value` amount of tokens as the allowance of `spender` over the
     * caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 value) external returns (bool);

    /**
     * @dev Moves a `value` amount of tokens from `from` to `to` using the
     * allowance mechanism. `value` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 value) external returns (bool);
}
IERC20Metadata.sol 26 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.4.0) (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity >=0.6.2;

import {IERC20} from "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC-20 standard.
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}
Context.sol 28 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)

pragma solidity ^0.8.20;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}
ReentrancyGuard.sol 87 lines
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
 * consider using {ReentrancyGuardTransient} instead.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}
IUniswapV2Router01.sol 95 lines
pragma solidity >=0.6.2;

interface IUniswapV2Router01 {
    function factory() external pure returns (address);
    function WETH() external pure returns (address);

    function addLiquidity(
        address tokenA,
        address tokenB,
        uint amountADesired,
        uint amountBDesired,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB, uint liquidity);
    function addLiquidityETH(
        address token,
        uint amountTokenDesired,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external payable returns (uint amountToken, uint amountETH, uint liquidity);
    function removeLiquidity(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETH(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountToken, uint amountETH);
    function removeLiquidityWithPermit(
        address tokenA,
        address tokenB,
        uint liquidity,
        uint amountAMin,
        uint amountBMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountA, uint amountB);
    function removeLiquidityETHWithPermit(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountToken, uint amountETH);
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] calldata path,
        address to,
        uint deadline
    ) external returns (uint[] memory amounts);
    function swapExactETHForTokens(uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);
    function swapTokensForExactETH(uint amountOut, uint amountInMax, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapExactTokensForETH(uint amountIn, uint amountOutMin, address[] calldata path, address to, uint deadline)
        external
        returns (uint[] memory amounts);
    function swapETHForExactTokens(uint amountOut, address[] calldata path, address to, uint deadline)
        external
        payable
        returns (uint[] memory amounts);

    function quote(uint amountA, uint reserveA, uint reserveB) external pure returns (uint amountB);
    function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) external pure returns (uint amountOut);
    function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) external pure returns (uint amountIn);
    function getAmountsOut(uint amountIn, address[] calldata path) external view returns (uint[] memory amounts);
    function getAmountsIn(uint amountOut, address[] calldata path) external view returns (uint[] memory amounts);
}
IUniswapV2Router02.sol 44 lines
pragma solidity >=0.6.2;

import './IUniswapV2Router01.sol';

interface IUniswapV2Router02 is IUniswapV2Router01 {
    function removeLiquidityETHSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline
    ) external returns (uint amountETH);
    function removeLiquidityETHWithPermitSupportingFeeOnTransferTokens(
        address token,
        uint liquidity,
        uint amountTokenMin,
        uint amountETHMin,
        address to,
        uint deadline,
        bool approveMax, uint8 v, bytes32 r, bytes32 s
    ) external returns (uint amountETH);

    function swapExactTokensForTokensSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
    function swapExactETHForTokensSupportingFeeOnTransferTokens(
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external payable;
    function swapExactTokensForETHSupportingFeeOnTransferTokens(
        uint amountIn,
        uint amountOutMin,
        address[] calldata path,
        address to,
        uint deadline
    ) external;
}
MockUnigate.sol 45 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "./Unigate.sol";

contract MockUnigateToken is UnigateToken {
    IUniswapV2Router02 private immutable _uniswapV2Router02;

    constructor(
        address treasury_,
        uint256 treasuryAllocationToken_,
        address liquidityReserve_,
        uint256 liquidityReserveAllocationToken_,
        address rewardReserve_,
        uint256 rewardReserveAllocationToken_,
        uint256 saleEndTime_,
        uint256 salePriceETH_,
        uint256 presaleEndTime_,
        uint256 presalePriceETH_,
        uint256 presaleReferralRewardFactor_,
        uint256 presaleBuybackGuaranteeEndTime_,
        IUniswapV2Router02 uniswapV2Router02_
    )
        UnigateToken(
            treasury_,
            treasuryAllocationToken_,
            liquidityReserve_,
            liquidityReserveAllocationToken_,
            rewardReserve_,
            rewardReserveAllocationToken_,
            saleEndTime_,
            salePriceETH_,
            presaleEndTime_,
            presalePriceETH_,
            presaleReferralRewardFactor_,
            presaleBuybackGuaranteeEndTime_
        )
    {
        _uniswapV2Router02 = uniswapV2Router02_;
    }

    function uniswapV2Router02() public view override returns (IUniswapV2Router02) {
        return _uniswapV2Router02;
    }
}
Unigate.sol 817 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";

import "@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol";

/**
 * @title Unigate Bridge Token
 * @author Unigate
 * @notice Unigate bridge token base contract.
 */
abstract contract UnigateBridgeToken is ERC20 {
    /**
     * @notice Master token contract address.
     */
    address public immutable masterToken;

    /**
     * @notice Initializes token parameters.
     *
     * @param name_ Token name.
     * @param symbol_ Token symbol.
     * @param masterToken_ Master token contract address.
     */
    constructor(
        string memory name_,
        string memory symbol_,
        address masterToken_
    ) ERC20(name_, symbol_) {
        require(masterToken_ != address(0), "Master token contract address is zero");
        masterToken = masterToken_;
    }

    /**
     * @notice Checks that the caller (`_msgSender()`) is master token (`masterToken`).
     */
    modifier onlyMaster() {
        require(_msgSender() == masterToken, "Access denied");

        _;
    }

    /**
     * @notice Buys bridge tokens for ETH and transfers them to the caller (`_msgSender()`).
     *
     *         ONLY avaiable to master token caller (`masterToken`).
     *
     * @return Token amount (in base units) transferred.
     */
    function buyTokensForETH() external payable onlyMaster returns (uint256) {
        // Calculate token amount
        uint256 amountToken = (msg.value * (10 ** decimals())) / _priceETH();

        // Transfer tokens from token reserve (token balance if `this`) to caller
        _transfer(address(this), _msgSender(), amountToken);

        return amountToken;
    }

    /**
     * @notice Sells bridge tokens for ETH and transfers ETH to the caller (`_msgSender()`).
     *
     *         ONLY avaiable to master token caller (`masterToken`).
     *
     * @param amountToken Token amount (in base units) to sell.
     *
     * @return ETH amount (in wei) transferred.
     */
    function sellTokensForETH(uint256 amountToken) external onlyMaster returns (uint256) {
        // Calculate ETH amount
        uint256 amountETH = (amountToken * _priceETH()) / (10 ** decimals());

        // Transfer tokens from caller to token reserve (token balance if `this`)
        _transfer(_msgSender(), address(this), amountToken);

        // Transfer ETH to caller
        payable(_msgSender()).transfer(amountETH);

        return amountETH;
    }

    /**
     * @notice Gets token price.
     *
     * @return ETH amount (in wei) for 1 token.
     */
    function _priceETH() internal virtual returns (uint256);
}

/**
 * @title Unigate Token
 * @author Unigate
 * @notice Unigate token contract.
 */
contract UnigateToken is ERC20, ReentrancyGuard {
    /**
     * @notice Treasury address.
     */
    address public immutable treasury;

    /**
     * @notice Liquidity reserve address.
     */
    address public immutable liquidityReserve;

    /**
     * @notice Reward reserve address.
     */
    address public immutable rewardReserve;

    /**
     * @notice Sale end time.
     */
    uint256 public immutable saleEndTime;

    /**
     * @notice Sale price in ETH amount (in wei) for 1 token.
     */
    uint256 public immutable salePriceETH;

    /**
     * @notice Presale end time.
     */
    uint256 public immutable presaleEndTime;

    /**
     * @notice Presale price in ETH amount (in wei) for 1 token.
     */
    uint256 public immutable presalePriceETH;

    /**
     * @notice Presale referral reward factor in percent (with two decimals).
     *
     *         A value of 10000 represents 100.00%.
     */
    uint256 public immutable presaleReferralRewardFactorPercent;

    /**
     * @notice Presale buyback end time.
     */
    uint256 public immutable presaleBuybackEndTime;

    /**
     * @notice Token amount (in base units) eligible for presale buyback per account.
     */
    mapping(address => uint256) private _presaleBuybackEligibileToken;

    /**
     * @notice Initializes token parameters.
     *
     * @param treasury_ Treasury address.
     * @param treasuryAllocationToken_ Treasury initial allocation token amount (in base units).
     * @param liquidityReserve_ Liquidity reserve address.
     * @param liquidityReserveAllocationToken_ Liquidity reserve initial allocation token amount (in base units).
     * @param rewardReserve_ Reward reserve address.
     * @param rewardReserveAllocationToken_ Reward reserve initial allocation token amount (in base units).
     * @param saleEndTime_ Sale end time.
     * @param salePriceETH_ Sale price in ETH amount (in wei) per 1 token.
     * @param presaleEndTime_ Presale end time.
     * @param presalePriceETH_ Presale price in ETH amount (in wei) per 1 token.
     * @param presaleReferralRewardFactorPercent_ Presale referral reward factor in percent (with two decimals).
     * @param presaleBuybackEndTime_ Presale buyback end time.
     */
    constructor(
        address treasury_,
        uint256 treasuryAllocationToken_,
        address liquidityReserve_,
        uint256 liquidityReserveAllocationToken_,
        address rewardReserve_,
        uint256 rewardReserveAllocationToken_,
        uint256 saleEndTime_,
        uint256 salePriceETH_,
        uint256 presaleEndTime_,
        uint256 presalePriceETH_,
        uint256 presaleReferralRewardFactorPercent_,
        uint256 presaleBuybackEndTime_
    ) ERC20("UnigateToken", "UGTT") {
        // Set up treasury
        require(treasury_ != address(0), "Treasury address is zero");
        treasury = treasury_;
        _mint(treasury_, treasuryAllocationToken_);

        // Set up liquidity reserve
        require(liquidityReserve_ != address(0), "Liquidity reserve address is zero");
        require(liquidityReserveAllocationToken_ > 0, "Liquidity reserve allocation is zero");
        liquidityReserve = liquidityReserve_;
        _mint(liquidityReserve_, liquidityReserveAllocationToken_);

        // Set up reward reserve
        require(rewardReserve_ != address(0), "Reward reserve address is zero");
        rewardReserve = rewardReserve_;
        _mint(rewardReserve_, rewardReserveAllocationToken_);

        // Set up sale
        require(saleEndTime_ > block.timestamp, "Sale end time already passed");
        require(salePriceETH_ > 0, "Sale price is zero");
        saleEndTime = saleEndTime_;
        salePriceETH = salePriceETH_;

        // Set up presale
        require(presaleEndTime_ > block.timestamp, "Presale end time already passed");
        require(presaleEndTime_ < saleEndTime, "Presale end time later than sale end time");
        require(presalePriceETH_ > 0, "Presale price is zero");
        require(
            presaleBuybackEndTime_ > presaleEndTime_,
            "Buyback end time earlier than presale end time"
        );
        presaleEndTime = presaleEndTime_;
        presalePriceETH = presalePriceETH_;
        presaleReferralRewardFactorPercent = presaleReferralRewardFactorPercent_;
        presaleBuybackEndTime = presaleBuybackEndTime_;
    }

    /**
     * @notice Calculates token amount for ETH amount.
     *
     * @param amountETH ETH amount (in wei).
     * @param rateETH Conversion rate in ETH amount (in wei) per 1 token.
     *
     * @return Token amount (in base units).
     */
    function calcTokenFromETH(uint256 amountETH, uint256 rateETH) public view returns (uint256) {
        return (amountETH * (10 ** decimals())) / rateETH;
    }

    /**
     * @notice Calculates ETH amount for token amount.
     *
     * @param amountToken Token amount (in base units).
     * @param rateETH Conversion rate in ETH amount (in wei) per 1 token.
     *
     * @return ETH amount (in wei).
     */
    function calcETHFromToken(uint256 amountToken, uint256 rateETH) public view returns (uint256) {
        return (amountToken * rateETH) / (10 ** decimals());
    }

    /**
     * @notice Checks that the caller (`_msgSender()`) is treasury (`treasury`).
     */
    modifier onlyTreasury() {
        require(_msgSender() == treasury, "Access denied");

        _;
    }

    /**
     * @notice Checks that sale is running.
     */
    modifier onlyDuringSale() {
        require(block.timestamp <= saleEndTime, "Sale ended");

        _;
    }

    /**
     * @notice Checks that sale has ended.
     */
    modifier onlyAfterSale() {
        require(block.timestamp > saleEndTime, "Sale not ended");

        _;
    }

    /**
     * @notice Checks that presale is running.
     */
    modifier onlyDuringPresale() {
        require(block.timestamp <= presaleEndTime, "Presale ended");

        _;
    }

    /**
     * @notice Checks that presale has ended.
     */
    modifier onlyAfterPresale() {
        require(block.timestamp > presaleEndTime, "Presale not ended");

        _;
    }

    /**
     * @notice Checks that presale buyback is running.
     */
    modifier onlyDuringPresaleBuyback() {
        require(block.timestamp < presaleBuybackEndTime, "Presale buyback ended");

        _;
    }

    /**
     * @inheritdoc ERC20
     *
     * @notice ONLY available AFTER sale ends (`saleEndTime`).
     */
    function transfer(address to, uint256 value) public override onlyAfterSale returns (bool) {
        return super.transfer(to, value);
    }

    /**
     * @inheritdoc ERC20
     *
     * @notice ONLY available AFTER sale ends (`saleEndTime`).
     */
    function approve(address spender, uint256 value) public override onlyAfterSale returns (bool) {
        return super.approve(spender, value);
    }

    /**
     * @inheritdoc ERC20
     *
     * @notice ONLY available AFTER sale ends (`saleEndTime`).
     */
    function transferFrom(
        address from,
        address to,
        uint256 value
    ) public override onlyAfterSale returns (bool) {
        return super.transferFrom(from, to, value);
    }

    /**
     * @notice Gets balance of reward reserve (`rewardReserve`).
     *
     * @return Token amount (in base units).
     */
    function balanceOfRewardReserve() external view returns (uint256) {
        return balanceOf(rewardReserve);
    }

    /**
     * @notice Gets balance of sale reserve (`this`).
     *
     *         ONLY available BEFORE sale ends (`saleEndTime`).
     *
     * @return Token amount (in base units).
     */
    function balanceOfSaleReserve() external view onlyDuringSale returns (uint256) {
        return balanceOf(address(this));
    }

    /**
     * @notice Buys tokens for ETH at sale price (`salePriceETH`) and
     *         transfers them to the caller (`_msgSender()`).
     *
     *         ONLY available AFTER presale ends (`presaleEndTime`) and
     *         BEFORE sale ends (`saleEndTime`).
     *
     * @return Token amount (in base units) transferred.
     */
    function buyTokensForETH() external payable onlyDuringSale onlyAfterPresale returns (uint256) {
        // Credit tokens - ETH is received directly by contract
        return _commitSale(_msgSender(), msg.value);
    }

    /**
     * @notice Buys tokens for input tokens at sale price (`salePriceETH`),
     *         swapping input tokens for ETH via Uniswap (`uniswapV2Router02`) and
     *         transfers them to the caller (`_msgSender()`).
     *
     *         ONLY available AFTER presale ends (`presaleEndTime`) and
     *         BEFORE sale ends (`saleEndTime`).
     *
     * @param inputToken Input token contract address.
     * @param amountInputToken Input token amount (in base units).
     * @param swapPath Intermediate token contract addresses, if any.
     * @param minAmountETH Minimum output ETH amount (in wei).
     *
     * @return Token amount (in base units) transferred.
     */
    function buyTokensForTokens(
        IERC20 inputToken,
        uint256 amountInputToken,
        address[] calldata swapPath,
        uint256 minAmountETH
    ) external onlyDuringSale onlyAfterPresale returns (uint256) {
        // Collect input tokens from caller
        require(
            inputToken.transferFrom(_msgSender(), address(this), amountInputToken),
            "Failed to transfer input tokens"
        );

        IUniswapV2Router02 router = uniswapV2Router02();

        // Set allowance on input tokens for router
        require(
            inputToken.approve(address(router), amountInputToken),
            "Failed to approve input tokens to router"
        );

        // Build full swap path, including input and output tokens
        address[] memory fullSwapPath = new address[](swapPath.length + 2);
        fullSwapPath[0] = address(inputToken);
        for (uint256 i = 0; i < swapPath.length; i++) {
            fullSwapPath[i + 1] = swapPath[i];
        }
        fullSwapPath[fullSwapPath.length - 1] = router.WETH();

        // Store initial balance
        uint256 initialBalanceETH = address(this).balance;

        // Enable direct receive
        _expectReceive = true;

        // Swap input tokens for ETH
        uint256[] memory amounts = router.swapExactTokensForETH(
            amountInputToken,
            minAmountETH,
            fullSwapPath,
            address(this),
            block.timestamp
        );

        // Disable direct receive
        _expectReceive = false;

        // Reset allowance on input tokens for router
        require(
            inputToken.approve(address(router), 0),
            "Failed to reset input tokens approval to router"
        );

        // Determine output ETH amount
        uint256 amountETH = amounts[fullSwapPath.length - 1];
        require(amountETH >= minAmountETH, "Swap output ETH amount is below minimum");

        // Check balance after swap
        require(
            (address(this).balance - initialBalanceETH) >= amountETH,
            "Swap output ETH amount was not received"
        );

        // Credit tokens to caller
        return _commitSale(_msgSender(), amountETH);
    }

    /**
     * @notice Buys tokens for ETH at presale price (`presalePriceETH`) and
     *         transfers them to the caller (`_msgSender()`).
     *
     *         Credits presale buyback eligibility (`presaleBuybackEligibilityOf`) to
     *         caller for purchased token amount.
     *
     *         If referrer (`referrer`) is non-zero, transfers referral reward,
     *         according to referral reward factor (`presaleReferralRewardFactorPercent`)
     *         and the purchased token amount, from reward reserve (`rewardReserve`)
     *         to referrer. Referrer MAY NOT be the same as caller.
     *
     *         ONLY available BEFORE presale ends (`presaleEndTime`).
     *
     * @param referer Referer account address or zero address.
     *
     * @return Token amount (in base units) transferred.
     */
    function presaleBuyTokensForETH(
        address referer
    ) external payable onlyDuringPresale returns (uint256) {
        // Credit tokens - ETH is received directly by contract
        return _commitPresale(_msgSender(), msg.value, referer);
    }

    /**
     * @notice Buys tokens for input tokens at presale price (`presalePriceETH`),
     *         swapping input tokens for ETH via Uniswap (`UniswapV2Router02`) and
     *         transfers them to the caller (`_msgSender()`).
     *
     *         Credits presale buyback eligibility (`presaleBuybackEligibilityOf`) to
     *         caller for purchased tokens.
     *
     *         If referrer (`referrer`) is non-zero, transfers referral reward,
     *         according to referral reward factor (`presaleReferralRewardFactorPercent`)
     *         and the purchased token amount, from reward reserve (`rewardReserve`)
     *         to referrer. Referrer MAY NOT be the same as caller.
     *
     *         ONLY available BEFORE presale ends (`presaleEndTime`).
     *
     * @param inputToken Input token contract address.
     * @param amountInputToken Input token amount (in base units).
     * @param swapPath Intermediate token contract addresses, if any.
     * @param minAmountETH Minimum ETH amount (in wei).
     * @param referer Referer account address or zero address.
     *
     * @return Token amount (in base units) transferred.
     */
    function presaleBuyTokensForTokens(
        IERC20 inputToken,
        uint256 amountInputToken,
        address[] calldata swapPath,
        uint256 minAmountETH,
        address referer
    ) external onlyDuringPresale returns (uint256) {
        // Collect input tokens from caller
        require(
            inputToken.transferFrom(_msgSender(), address(this), amountInputToken),
            "Failed to transfer input tokens"
        );

        IUniswapV2Router02 router = uniswapV2Router02();

        // Set allowance on input tokens for router
        require(
            inputToken.approve(address(router), amountInputToken),
            "Failed to approve input tokens to router"
        );

        // Build full swap path, including input and output tokens
        address[] memory fullSwapPath = new address[](swapPath.length + 2);
        fullSwapPath[0] = address(inputToken);
        for (uint256 i = 0; i < swapPath.length; i++) {
            fullSwapPath[i + 1] = swapPath[i];
        }
        fullSwapPath[fullSwapPath.length - 1] = router.WETH();

        // Store initial balance
        uint256 initialBalanceETH = address(this).balance;

        // Enable direct receive
        _expectReceive = true;

        // Swap input tokens for ETH
        uint256[] memory amounts = router.swapExactTokensForETH(
            amountInputToken,
            minAmountETH,
            fullSwapPath,
            address(this),
            block.timestamp
        );

        // Disable direct receive
        _expectReceive = false;

        // Reset allowance on input tokens for router
        require(
            inputToken.approve(address(router), 0),
            "Failed to reset input tokens approval to router"
        );

        // Determine output ETH amount
        uint256 amountETH = amounts[fullSwapPath.length - 1];
        require(amountETH >= minAmountETH, "Swap output ETH amount is below minimum");

        // Check balance after swap
        require(
            (address(this).balance - initialBalanceETH) >= amountETH,
            "Swap output ETH amount was not received"
        );

        // Credit tokens to caller
        return _commitPresale(_msgSender(), amountETH, referer);
    }

    /**
     * @notice Gets presale buyback eligibility for the specified account.
     *
     *         ONLY available BEFORE presale buyback ends (`presaleBuybackEndTime`).
     *
     * @param account Account address.
     *
     * @return Token amount (in base units) eligible for presale buyback.
     */
    function presaleBuybackEligibilityOf(
        address account
    ) external view onlyDuringPresaleBuyback returns (uint256) {
        return _presaleBuybackEligibileToken[account];
    }

    /**
     * @notice Sells tokens back for ETH at presale price (`presalePriceETH`)
     *         and transfers ETH amount to the caller (`_msgSender()`).
     *
     *         Debits caller presale buyback eligibility (`presaleBuybackEligibilityOf`).
     *         FAILS if insufficient.
     *
     *         ONLY available AFTER sale ends (`saleEndTime`) and
     *         BEFORE presale buyback ends (`presaleBuybackEndTime`).
     *
     * @param amountToken Token amount (in base units) to sell.
     *
     * @return ETH amount (in wei) transferred.
     */
    function sellPresaleBuybackTokensForETH(
        uint256 amountToken
    ) external onlyAfterSale onlyDuringPresaleBuyback nonReentrant returns (uint256) {
        require(amountToken > 0, "Token amount is zero");
        require(
            _presaleBuybackEligibileToken[_msgSender()] >= amountToken,
            "Insufficient presale buyback eligibility"
        );

        // Calculate ETH amount
        uint256 amountETH = calcETHFromToken(amountToken, presalePriceETH);
        require(amountETH > 0, "ETH amount is zero");

        // Presale buyback eligibility already verified via `require`
        unchecked {
            // Debit presale buyback eligibility from caller
            _presaleBuybackEligibileToken[_msgSender()] -= amountToken;
        }

        // Transfer tokens from caller to sale reserve (token balance of `this`)
        _transfer(_msgSender(), address(this), amountToken);

        // Transfer ETH to caller
        payable(_msgSender()).transfer(amountETH);

        return amountETH;
    }

    /**
     * @notice Transfers tokens from sale reserve (`this`) to recipient (`recipient`)
     *         for the specified ETH amount at sale price (`salePriceETH`).
     *
     * @param recipient Recipient account.
     * @param amountETH ETH amount (in wei).
     *
     * @return Token amount (in base units) transferred.
     */
    function _commitSale(address recipient, uint256 amountETH) internal returns (uint256) {
        require(amountETH > 0, "ETH amount is zero");

        // Calculate token amount
        uint256 amountToken = calcTokenFromETH(amountETH, salePriceETH);
        require(amountToken > 0, "Token amount is zero");

        // Transfer tokens to buyer
        // NOTE: Fails if sale reserve (token balance of `this`) is exhausted
        _transfer(address(this), recipient, amountToken);

        return amountToken;
    }

    /**
     * @notice Transfers tokens from sale reserve (`this`) to recipient (`recipient`)
     *         for the specified ETH amount at presale price (`presalePriceETH`).
     *
     *         Credits presale buyback eligibility (`presaleBuybackEligibilityOf`) to
     *         caller for purchased token amount.
     *
     *         If referrer (`referrer`) is non-zero, transfers referral reward,
     *         according to referral reward factor (`presaleReferralRewardFactor`)
     *         and the purchased token amount, from reward reserve (`rewardReserve`)
     *         to referrer. Referrer MAY NOT be the same as caller.
     *
     * @param recipient Recipient account.
     * @param amountETH ETH amount (in wei).
     * @param referer Referer account or zero.
     *
     * @return Token amount (in base units) transferred.
     */
    function _commitPresale(
        address recipient,
        uint256 amountETH,
        address referer
    ) internal returns (uint256) {
        require(amountETH > 0, "ETH amount is zero");
        require(referer != recipient, "Invalid referer");

        // Calculate token amount
        uint256 amountToken = calcTokenFromETH(amountETH, presalePriceETH);
        require(amountToken > 0, "Token amount is zero");

        // Credit presale buyback eligibility to recipient
        _presaleBuybackEligibileToken[recipient] += amountToken;

        // Transfer tokens to buyer
        // NOTE: Fails if sale reserve (token balance of `this`) is exhausted
        _transfer(address(this), recipient, amountToken);

        // Query reward reserve token balance
        uint256 rewardReserveBalanceToken = balanceOf(rewardReserve);

        if (
            referer != address(0) &&
            presaleReferralRewardFactorPercent > 0 &&
            rewardReserveBalanceToken > 0
        ) {
            // Calculate referral reward token amount
            uint256 referralRewardAmountToken = (amountToken * presaleReferralRewardFactorPercent) /
                10000;

            // Clamp referral reward token amount to reward reserve balance
            if (referralRewardAmountToken > rewardReserveBalanceToken) {
                referralRewardAmountToken = rewardReserveBalanceToken;
            }

            // Transfer referral reward
            _transfer(rewardReserve, referer, referralRewardAmountToken);
        }

        return amountToken;
    }

    /**
     * @notice Uniswap router.
     *
     * @dev Returns constant. Exists as a virtual method to facilitate testing.
     *
     * @return Uniswap router instance.
     */
    function uniswapV2Router02() public view virtual returns (IUniswapV2Router02) {
        return IUniswapV2Router02(0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D);
    }

    /**
     * @notice Emitted when sale resereve (`this`) is allocated via `allocateSaleReserve`.
     *
     * @param amountToken Token amount (in base units) allocated.
     */
    event SaleReserveAllocated(uint256 amountToken);

    /**
     * @notice Transfers tokens from liquidity reserve (`liquidityReserve`) to
     *         sale reserve (`this`).
     *
     *         ONLY avaiable to treasury caller (`treasury`) BEFORE sale
     *         ends (`saleEndTime`).
     */
    function allocateSaleReserve(uint256 amountToken) external onlyTreasury onlyDuringSale {
        _transfer(liquidityReserve, address(this), amountToken);

        emit SaleReserveAllocated(amountToken);
    }

    /**
     * @notice Emitted when sale resereve (`this`) is burned via `burnSaleReserve`.
     *
     * @param amountToken Token amount (in base units) burned.
     */
    event SaleReserveBurned(uint256 amountToken);

    /**
     * @notice Burns all tokens on sale reserve (`this`).
     *
     *         ONLY avaiable to treasury caller (`treasury`) AFTER sale
     *         ends (`saleEndTime`).
     */
    function burnSaleReserve() external onlyTreasury onlyAfterSale {
        uint256 saleReserveBalance = balanceOf(address(this));

        _burn(address(this), saleReserveBalance);

        emit SaleReserveBurned(saleReserveBalance);
    }

    /**
     * @notice Emitted when a deposit is received via `deposit`.
     *
     * @param amountETH ETH amount (in wei).
     */
    event DepositReceived(uint256 amountETH);

    /**
     * @notice Deposits ETH.
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     */
    function deposit() external payable onlyTreasury {
        emit DepositReceived(msg.value);
    }

    /**
     * @notice Buys bridge tokens to the token account (`this`).
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     *
     * @param token Bridge token contract address.
     * @param amountETH ETH amount (in wei) to spend.
     *
     * @return Token amount (in base units) transferred.
     */
    function buyBridgeTokens(
        UnigateBridgeToken token,
        uint256 amountETH
    ) external onlyTreasury nonReentrant returns (uint256) {
        require(token.masterToken() == address(this), "Invalid bridge token");

        return token.buyTokensForETH{value: amountETH}();
    }

    /**
     * @notice Sells bridge tokens from the token account (`this`).
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     *
     * @param token Bridge token contract address.
     * @param amountToken Token amount (in base units) to sell.
     *
     * @return ETH amount (in wei) transferred.
     */
    function sellBridgeTokens(
        UnigateBridgeToken token,
        uint256 amountToken
    ) external onlyTreasury nonReentrant returns (uint256) {
        require(token.masterToken() == address(this), "Invalid bridge token");

        return token.sellTokensForETH(amountToken);
    }

    /**
     * @notice Specifies whether raw ETH receipt (via `receive`) is expected.
     *
     *         Currently, only temporarily enabled for swap operations.
     */
    bool private _expectReceive;

    /**
     * @notice Receives ETH.
     *
     *         ONLY allowed when `_expectReceive` is truthy.
     */
    receive() external payable {
        require(_expectReceive, "Prohibited");
    }
}
UnigateBridges.sol 134 lines
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";

import "./Unigate.sol";

/**
 * @title Unigate Treasury Bridge Token
 * @author Unigate
 * @notice Unigate Treasury bridge token contract.
 */
contract UnigateTreasuryBridgeToken is UnigateBridgeToken {
    /**
     * @notice Treasury address.
     */
    address public immutable treasury;

    /**
     * @notice Price in ETH amount (in wei) for 1 token.
     */
    uint256 public immutable priceETH;

    /**
     * @notice Initializes token parameters.
     *
     * @param treasury_ Treasury address.
     * @param priceETH_ ETH amount (in wei) for 1 token.
     * @param initialAllocationToken_ Initial allocation token amount (in base units).
     * @param masterToken_ Master token contract address.
     */
    constructor(
        address treasury_,
        uint256 priceETH_,
        uint256 initialAllocationToken_,
        address masterToken_
    ) UnigateBridgeToken("UnigateTreasuryBridge", "UGTT/T", masterToken_) {
        // Set up treasury
        require(treasury_ != address(0), "Treasury address is zero");
        treasury = treasury_;

        // Set up price
        require(priceETH_ > 0, "Price is zero");
        priceETH = priceETH_;

        // Initial allocation
        _mint(address(this), initialAllocationToken_);
    }

    /**
     * @notice Checks that the caller (`_msgSender()`) is treasury (`treasury`).
     */
    modifier onlyTreasury() {
        require(_msgSender() == treasury, "Access denied");

        _;
    }

    /**
     * @notice Mints tokens to token reserve (`this`).
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     *
     * @param amountToken Token amount (in base units).
     */
    function mint(uint256 amountToken) external onlyTreasury {
        _mint(address(this), amountToken);
    }

    /**
     * @notice Burns tokens from token reserve (`this`).
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     *
     * @param amountToken Token amount (in base units).
     */
    function burn(uint256 amountToken) external onlyTreasury {
        _burn(address(this), amountToken);
    }

    /**
     * @notice Emitted when a deposit is received via `deposit`.
     *
     * @param amountETH ETH amount (in wei).
     */
    event DepositReceived(uint256 amountETH);

    /**
     * @notice Deposits ETH.
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     */
    function deposit() external payable onlyTreasury {
        emit DepositReceived(msg.value);
    }

    /**
     * @notice Emitted when a withdraw is completed via `withdraw`.
     *
     * @param amountETH ETH amount (in wei).
     */
    event WithdrawCompleted(uint256 amountETH);

    /**
     * @notice Withdraws ETH.
     *
     *         ONLY avaiable to treasury caller (`treasury`).
     *
     * @param amountETH ETH amount (in wei).
     */
    function withdraw(uint256 amountETH) external onlyTreasury {
        payable(_msgSender()).transfer(amountETH);

        emit WithdrawCompleted(amountETH);
    }

    /**
     * @notice Gets token price.
     *
     * @return ETH amount (in wei) for 1 token.
     */
    function _priceETH() internal view override returns (uint256) {
        return priceETH;
    }

    /**
     * @notice Receives ETH.
     *
     *         NOT ALLOWED.
     */
    receive() external payable {
        revert("Prohibited");
    }
}

Read Contract

allowance 0xdd62ed3e → uint256
balanceOf 0x70a08231 → uint256
balanceOfRewardReserve 0xd5d0e9eb → uint256
balanceOfSaleReserve 0x191a4845 → uint256
calcETHFromToken 0xf75a854e → uint256
calcTokenFromETH 0xa1af3e5e → uint256
decimals 0x313ce567 → uint8
liquidityReserve 0xb753bfe9 → address
name 0x06fdde03 → string
presaleBuybackEligibilityOf 0x6a576112 → uint256
presaleBuybackEndTime 0x4020b317 → uint256
presaleEndTime 0x249b7c19 → uint256
presalePriceETH 0x4f5f21cf → uint256
presaleReferralRewardFactorPercent 0xd7e66d14 → uint256
rewardReserve 0xcab64bcd → address
saleEndTime 0xed338ff1 → uint256
salePriceETH 0x6b7cbf11 → uint256
symbol 0x95d89b41 → string
totalSupply 0x18160ddd → uint256
treasury 0x61d027b3 → address
uniswapV2Router02 0xa7c6402c → address

Write Contract 13 functions

These functions modify contract state and require a wallet transaction to execute.

allocateSaleReserve 0xc154b285
uint256 amountToken
approve 0x095ea7b3
address spender
uint256 value
returns: bool
burnSaleReserve 0x63e1289b
No parameters
buyBridgeTokens 0x4555a5aa
address token
uint256 amountETH
returns: uint256
buyTokensForETH 0x4632f560
No parameters
returns: uint256
buyTokensForTokens 0xc841c4af
address inputToken
uint256 amountInputToken
address[] swapPath
uint256 minAmountETH
returns: uint256
deposit 0xd0e30db0
No parameters
presaleBuyTokensForETH 0xbd977c75
address referer
returns: uint256
presaleBuyTokensForTokens 0x756c79db
address inputToken
uint256 amountInputToken
address[] swapPath
uint256 minAmountETH
address referer
returns: uint256
sellBridgeTokens 0x28a678b1
address token
uint256 amountToken
returns: uint256
sellPresaleBuybackTokensForETH 0xcc32d4da
uint256 amountToken
returns: uint256
transfer 0xa9059cbb
address to
uint256 value
returns: bool
transferFrom 0x23b872dd
address from
address to
uint256 value
returns: bool

Recent Transactions

No transactions found for this address