diff --git a/packages/hardhat/.envexample b/packages/hardhat/.env.example similarity index 100% rename from packages/hardhat/.envexample rename to packages/hardhat/.env.example diff --git a/packages/hardhat/.gitignore b/packages/hardhat/.gitignore index e36f7e18..00dad773 100644 --- a/packages/hardhat/.gitignore +++ b/packages/hardhat/.gitignore @@ -3,11 +3,9 @@ node_modules coverage coverage.json typechain +typechain-types -#Hardhat files +# Hardhat files cache artifacts -deployments -# hardhat typechain generated files -types/ diff --git a/packages/hardhat/.npmrc b/packages/hardhat/.npmrc deleted file mode 100644 index 4fd02195..00000000 --- a/packages/hardhat/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true \ No newline at end of file diff --git a/packages/hardhat/README.md b/packages/hardhat/README.md index 6363c8eb..c1b3a957 100644 --- a/packages/hardhat/README.md +++ b/packages/hardhat/README.md @@ -1,124 +1,23 @@ -# Hardhat | Celo Composer +# Celo Composer | Hardhat -This project demonstrates a basic Hardhat use case. It comes with a sample contract, a test for that contract, a sample script that deploys that contract, and an example of a task implementation, which simply lists the available accounts. +## How to use -## Setup & Installation +1. Create a copy of `.env.example` and rename it to `.env`. -### Alfajores Testnet Setup +2. For Deploying you will need `PRIVATE_KEY` set in `.env`. -**Note** This setup is not required when using a local development blockchain (like celo-devchain or Ganache). +3. For verification you will need [Celoscan API Key](https://celoscan.io/myapikey) `CELOSCAN_API_KEY` set in `.env`. -1. Create a `.env` file similar to `.envexample`. -2. Paste the private key in `.env`. - -Alternatively, you can also run the following command to generate a new account - -```sh -npx hardhat create-account -``` - -> **Note** : Depending on how you generate your private key, you may have to prepend `0x` in the private key does not already have it prepended. - -3. Faucet your account with the Alfajores testnet faucet [here](https://celo.org/developers/faucet). - -## Develop - -1. Write your contracts in `./contracts`. -2. Update contract deployment scripts in `./deploy`. -3. Deploy contracts with `yarn deploy` from the **root directory**. Optionally add the reset flag (`yarn deploy --reset`) to overwrite previous deployment info. The default deployment network is specified in `hardhat.config.js` and is set to `alfajores` initially. You can also overwrite previous deployments and redeploy when there are changes to the deployment script or contracts automatically by running `yarn deploy-reset-watch`. You can specify a specific network deployment directly with - -```bash -npx hardhat deploy --network [network name] -``` - -Network configs are defined in `hardhat.config.js`. - -## [Celo devchain](https://github.com/terminal-fi/celo-devchain) - -Run a local development Celo chain with `yarn devchain` in the `packages/hardhat` folder. You can print the addresses of the [Celo protocol contracts](https://github.com/celo-org/celo-monorepo/tree/master/packages/protocol) with `npx @terminal-fi/celo-devchain --test`. - -This is a version of Ganache (@celo/ganache-cli) that deploys the Celo core protocol contracts when it starts. - -**NOTE:** @celo/ganache-cli works only with Node 10 or Node 12 versions. Using Node 14 or later will result in errors. - -**NOTE:** @celo/ganache-cli currently doesn't support locally signed transactions. If you send a locally signed transaction it will throw: Error: Number can only safely store up to 53 bits error and crash. Thus you have to make sure your ContractKit doesn't actually have the private keys for test addresses and send transactions to be signed by ganache-cli itself. - -### Start - -```bash -npx celo-devchain --port 8545 -``` - -or - -```bash -yarn devchain -``` - -### Generate Typescript bindings - -This setting defaults to the web3 v1 bindings because that is what is used by use-contractkit in `packages/react-app`. - -You can change the output directory and target in `hardhat.config.js`. - -```bash -npx hardhat typechain -``` - -Read more about Typechain [here](https://github.com/dethcrypto/TypeChain) and more about the hardhat plugin [here](https://github.com/dethcrypto/TypeChain/tree/master/packages/hardhat). - -### Run sanity tests and print all core contract addresses - -```bash -npx @terminal-fi/celo-devchain --test -``` - -## Fork mainnet with [Ganache](https://trufflesuite.com/blog/introducing-ganache-7/index.html#1-zero-config-mainnet-forking) - -You can get a local copy of mainnet by forking with Ganache. Learn more about [forking mainnet with Ganache here.](https://trufflesuite.com/blog/introducing-ganache-7/index.html#1-zero-config-mainnet-forking) - -There is a script provided (`yarn fork-mainnet`) to fork mainnet and fund the same test accounts that come with Celo devchain. Sometimes sending transactions from the first account (which defaults to `0x5409ED021D9299bf6814279A6A1411A7e866A631`) is delayed and sending test transactions from the other accounts works better for some reason. :shrug: The private keys of the associated test accounts are printed in `account_keys.json`. - -## Celo Core Contracts - -You can easily import Celo Core contracts to be used by your contracts like so: - -```solidity -import '@celo/contracts/common/Accounts.sol'; -``` - -## Verify your contracts - -### hardhat-celo - -You can easily verify your contracts deployed to the associated networks with hardhat-celo. - -[Reference](https://docs.celo.org/developer/verify/hardhat) - -```bash -npx hardhat verify smart-contract-address parameter(s) --network alfajores -``` - -On Mainnet: +For Alfajores (Testnet) Verification ```bash -npx hardhat verify smart-contract-address parameter(s) --network celo +npx hardhat verify [CONTRACT_ADDRESS] [...CONSTRUCTOR_ARGS] --network alfajores ``` -### Sourcify - -Additionally, you can easily verify your contracts deployed to the associated networks with the following commands. - -[Reference](https://docs.celo.org/blog/hardhat-deploy-verify) - -On Alfajores: +For Mainnet Verification ```bash -npx hardhat --network alfajores sourcify +npx hardhat verify [CONTRACT_ADDRESS] [...CONSTRUCTOR_ARGS] --network celo ``` -On Mainnet: - -```bash -npx hardhat --network celo sourcify -``` +Check the file `hardhat.config.js` for Celo specific hardhat configuration. diff --git a/packages/hardhat/account_keys.json b/packages/hardhat/account_keys.json deleted file mode 100644 index 03627dd9..00000000 --- a/packages/hardhat/account_keys.json +++ /dev/null @@ -1 +0,0 @@ -{"addresses":{"0x5409ed021d9299bf6814279a6a1411a7e866a631":"0x5409ed021d9299bf6814279a6a1411a7e866a631","0x6ecbe1db9ef729cbe972c83fb886247691fb6beb":"0x6ecbe1db9ef729cbe972c83fb886247691fb6beb","0xe36ea790bc9d7ab70c55260c66d52b1eca985f84":"0xe36ea790bc9d7ab70c55260c66d52b1eca985f84","0xe834ec434daba538cd1b9fe1582052b880bd7e63":"0xe834ec434daba538cd1b9fe1582052b880bd7e63","0x78dc5d2d739606d31509c31d654056a45185ecb6":"0x78dc5d2d739606d31509c31d654056a45185ecb6","0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872":"0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872","0x06cef8e666768cc40cc78cf93d9611019ddcb628":"0x06cef8e666768cc40cc78cf93d9611019ddcb628","0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d":"0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d","0x7457d5e02197480db681d3fdf256c7aca21bdc12":"0x7457d5e02197480db681d3fdf256c7aca21bdc12","0x91c987bf62d25945db517bdaa840a6c661374402":"0x91c987bf62d25945db517bdaa840a6c661374402"},"private_keys":{"0x5409ed021d9299bf6814279a6a1411a7e866a631":"0xf2f48ee19680706196e2e339e5da3491186e0c4c5030670656b0e0164837257d","0x6ecbe1db9ef729cbe972c83fb886247691fb6beb":"0x5d862464fe9303452126c8bc94274b8c5f9874cbd219789b3eb2128075a76f72","0xe36ea790bc9d7ab70c55260c66d52b1eca985f84":"0xdf02719c4df8b9b8ac7f551fcb5d9ef48fa27eef7a66453879f4d8fdc6e78fb1","0xe834ec434daba538cd1b9fe1582052b880bd7e63":"0xff12e391b79415e941a94de3bf3a9aee577aed0731e297d5cfa0b8a1e02fa1d0","0x78dc5d2d739606d31509c31d654056a45185ecb6":"0x752dd9cf65e68cfaba7d60225cbdbc1f4729dd5e5507def72815ed0d8abc6249","0xa8dda8d7f5310e4a9e24f8eba77e091ac264f872":"0xefb595a0178eb79a8df953f87c5148402a224cdf725e88c0146727c6aceadccd","0x06cef8e666768cc40cc78cf93d9611019ddcb628":"0x83c6d2cc5ddcf9711a6d59b417dc20eb48afd58d45290099e5987e3d768f328f","0x4404ac8bd8f9618d27ad2f1485aa1b2cfd82482d":"0xbb2d3f7c9583780a7d3904a2f55d792707c345f21de1bacb2d389934d82796b2","0x7457d5e02197480db681d3fdf256c7aca21bdc12":"0xb2fd4d29c1390b71b8795ae81196bfd60293adf99f9d32a0aff06288fcdac55f","0x91c987bf62d25945db517bdaa840a6c661374402":"0x23cb7121166b9a2f93ae0b7c05bde02eae50d64449b2cbb42bc84e9d38d6cc89"}} \ No newline at end of file diff --git a/packages/hardhat/contracts/ERC1155.sol b/packages/hardhat/contracts/ERC1155.sol deleted file mode 100644 index e953e911..00000000 --- a/packages/hardhat/contracts/ERC1155.sol +++ /dev/null @@ -1,473 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC1155/ERC1155.sol) - -pragma solidity ^0.8.19; - -import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; -import "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol"; -import "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol"; -import "@openzeppelin/contracts/utils/Context.sol"; -import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; - -/** - * @dev Implementation of the basic standard multi-token. - * See https://eips.ethereum.org/EIPS/eip-1155 - * Originally based on code by Enjin: https://github.com/enjin/erc-1155 - * - * _Available since v3.1._ - */ -contract ERC1155 is Context, ERC165, IERC1155, IERC1155MetadataURI { - // Mapping from token ID to account balances - mapping(uint256 => mapping(address => uint256)) private _balances; - - // Mapping from account to operator approvals - mapping(address => mapping(address => bool)) private _operatorApprovals; - - // Used as the URI for all token types by relying on ID substitution, e.g. https://token-cdn-domain/{id}.json - string private _uri; - - /** - * @dev See {_setURI}. - */ - constructor(string memory uri_) { - _setURI(uri_); - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165, IERC165) returns (bool) { - return - interfaceId == type(IERC1155).interfaceId || - interfaceId == type(IERC1155MetadataURI).interfaceId || - super.supportsInterface(interfaceId); - } - - /** - * @dev See {IERC1155MetadataURI-uri}. - * - * This implementation returns the same URI for *all* token types. It relies - * on the token type ID substitution mechanism - * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. - * - * Clients calling this function must replace the `\{id\}` substring with the - * actual token type ID. - */ - function uri(uint256) public view virtual returns (string memory) { - return _uri; - } - - /** - * @dev See {IERC1155-balanceOf}. - * - * Requirements: - * - * - `account` cannot be the zero address. - */ - function balanceOf( - address account, - uint256 id - ) public view virtual returns (uint256) { - return _balances[id][account]; - } - - /** - * @dev See {IERC1155-balanceOfBatch}. - * - * Requirements: - * - * - `accounts` and `ids` must have the same length. - */ - function balanceOfBatch( - address[] memory accounts, - uint256[] memory ids - ) public view virtual returns (uint256[] memory) { - require( - accounts.length == ids.length, - "ERC1155: accounts and ids length mismatch" - ); - - uint256[] memory batchBalances = new uint256[](accounts.length); - - for (uint256 i = 0; i < accounts.length; ++i) { - batchBalances[i] = balanceOf(accounts[i], ids[i]); - } - - return batchBalances; - } - - /** - * @dev See {IERC1155-setApprovalForAll}. - */ - function setApprovalForAll(address operator, bool approved) public virtual { - _setApprovalForAll(_msgSender(), operator, approved); - } - - /** - * @dev See {IERC1155-isApprovedForAll}. - */ - function isApprovedForAll( - address account, - address operator - ) public view virtual returns (bool) { - return _operatorApprovals[account][operator]; - } - - /** - * @dev See {IERC1155-safeTransferFrom}. - */ - function safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) public virtual { - require( - from == _msgSender() || isApprovedForAll(from, _msgSender()), - "ERC1155: caller is not token owner or approved" - ); - _safeTransferFrom(from, to, id, amount, data); - } - - /** - * @dev See {IERC1155-safeBatchTransferFrom}. - */ - function safeBatchTransferFrom( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) public virtual { - require( - from == _msgSender() || isApprovedForAll(from, _msgSender()), - "ERC1155: caller is not token owner or approved" - ); - _safeBatchTransferFrom(from, to, ids, amounts, data); - } - - /** - * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. Will mint (or burn) if `from` (or `to`) is the zero address. - * - * Emits a {TransferSingle} event if the arrays contain one element, and {TransferBatch} otherwise. - * - * Requirements: - * - * - If `to` refers to a smart contract, it must implement either {IERC1155Receiver-onERC1155Received} - * or {IERC1155Receiver-onERC1155BatchReceived} and return the acceptance magic value. - */ - function _update( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal virtual { - require( - ids.length == amounts.length, - "ERC1155: ids and amounts length mismatch" - ); - - address operator = _msgSender(); - - for (uint256 i = 0; i < ids.length; ++i) { - uint256 id = ids[i]; - uint256 amount = amounts[i]; - - if (from != address(0)) { - uint256 fromBalance = _balances[id][from]; - require( - fromBalance >= amount, - "ERC1155: insufficient balance for transfer" - ); - unchecked { - _balances[id][from] = fromBalance - amount; - } - } - - if (to != address(0)) { - _balances[id][to] += amount; - } - } - - if (ids.length == 1) { - uint256 id = ids[0]; - uint256 amount = amounts[0]; - emit TransferSingle(operator, from, to, id, amount); - if (to != address(0)) { - _doSafeTransferAcceptanceCheck( - operator, - from, - to, - id, - amount, - data - ); - } - } else { - emit TransferBatch(operator, from, to, ids, amounts); - if (to != address(0)) { - _doSafeBatchTransferAcceptanceCheck( - operator, - from, - to, - ids, - amounts, - data - ); - } - } - } - - /** - * @dev Transfers `amount` tokens of token type `id` from `from` to `to`. - * - * Emits a {TransferSingle} event. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - `from` must have a balance of tokens of type `id` of at least `amount`. - * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the - * acceptance magic value. - */ - function _safeTransferFrom( - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) internal { - require(to != address(0), "ERC1155: transfer to the zero address"); - require(from != address(0), "ERC1155: transfer from the zero address"); - (uint256[] memory ids, uint256[] memory amounts) = _asSingletonArrays( - id, - amount - ); - _update(from, to, ids, amounts, data); - } - - /** - * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_safeTransferFrom}. - * - * Emits a {TransferBatch} event. - * - * Requirements: - * - * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the - * acceptance magic value. - */ - function _safeBatchTransferFrom( - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal { - require(to != address(0), "ERC1155: transfer to the zero address"); - require(from != address(0), "ERC1155: transfer from the zero address"); - _update(from, to, ids, amounts, data); - } - - /** - * @dev Sets a new URI for all token types, by relying on the token type ID - * substitution mechanism - * https://eips.ethereum.org/EIPS/eip-1155#metadata[defined in the EIP]. - * - * By this mechanism, any occurrence of the `\{id\}` substring in either the - * URI or any of the amounts in the JSON file at said URI will be replaced by - * clients with the token type ID. - * - * For example, the `https://token-cdn-domain/\{id\}.json` URI would be - * interpreted by clients as - * `https://token-cdn-domain/000000000000000000000000000000000000000000000000000000000004cce0.json` - * for token type ID 0x4cce0. - * - * See {uri}. - * - * Because these URIs cannot be meaningfully represented by the {URI} event, - * this function emits no events. - */ - function _setURI(string memory newuri) internal virtual { - _uri = newuri; - } - - /** - * @dev Creates `amount` tokens of token type `id`, and assigns them to `to`. - * - * Emits a {TransferSingle} event. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the - * acceptance magic value. - */ - function _mint( - address to, - uint256 id, - uint256 amount, - bytes memory data - ) internal { - require(to != address(0), "ERC1155: mint to the zero address"); - (uint256[] memory ids, uint256[] memory amounts) = _asSingletonArrays( - id, - amount - ); - _update(address(0), to, ids, amounts, data); - } - - /** - * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_mint}. - * - * Emits a {TransferBatch} event. - * - * Requirements: - * - * - `ids` and `amounts` must have the same length. - * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the - * acceptance magic value. - */ - function _mintBatch( - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) internal { - require(to != address(0), "ERC1155: mint to the zero address"); - _update(address(0), to, ids, amounts, data); - } - - /** - * @dev Destroys `amount` tokens of token type `id` from `from` - * - * Emits a {TransferSingle} event. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `from` must have at least `amount` tokens of token type `id`. - */ - function _burn(address from, uint256 id, uint256 amount) internal { - require(from != address(0), "ERC1155: burn from the zero address"); - (uint256[] memory ids, uint256[] memory amounts) = _asSingletonArrays( - id, - amount - ); - _update(from, address(0), ids, amounts, ""); - } - - /** - * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {_burn}. - * - * Emits a {TransferBatch} event. - * - * Requirements: - * - * - `ids` and `amounts` must have the same length. - */ - function _burnBatch( - address from, - uint256[] memory ids, - uint256[] memory amounts - ) internal { - require(from != address(0), "ERC1155: burn from the zero address"); - _update(from, address(0), ids, amounts, ""); - } - - /** - * @dev Approve `operator` to operate on all of `owner` tokens - * - * Emits an {ApprovalForAll} event. - */ - function _setApprovalForAll( - address owner, - address operator, - bool approved - ) internal virtual { - require(owner != operator, "ERC1155: setting approval status for self"); - _operatorApprovals[owner][operator] = approved; - emit ApprovalForAll(owner, operator, approved); - } - - function _doSafeTransferAcceptanceCheck( - address operator, - address from, - address to, - uint256 id, - uint256 amount, - bytes memory data - ) private { - if (to.code.length > 0) { - try - IERC1155Receiver(to).onERC1155Received( - operator, - from, - id, - amount, - data - ) - returns (bytes4 response) { - if (response != IERC1155Receiver.onERC1155Received.selector) { - revert("ERC1155: ERC1155Receiver rejected tokens"); - } - } catch Error(string memory reason) { - revert(reason); - } catch { - revert("ERC1155: transfer to non-ERC1155Receiver implementer"); - } - } - } - - function _doSafeBatchTransferAcceptanceCheck( - address operator, - address from, - address to, - uint256[] memory ids, - uint256[] memory amounts, - bytes memory data - ) private { - if (to.code.length > 0) { - try - IERC1155Receiver(to).onERC1155BatchReceived( - operator, - from, - ids, - amounts, - data - ) - returns (bytes4 response) { - if ( - response != IERC1155Receiver.onERC1155BatchReceived.selector - ) { - revert("ERC1155: ERC1155Receiver rejected tokens"); - } - } catch Error(string memory reason) { - revert(reason); - } catch { - revert("ERC1155: transfer to non-ERC1155Receiver implementer"); - } - } - } - - function _asSingletonArrays( - uint256 element1, - uint256 element2 - ) private pure returns (uint256[] memory array1, uint256[] memory array2) { - /// @solidity memory-safe-assembly - assembly { - array1 := mload(0x40) - mstore(array1, 1) - mstore(add(array1, 0x20), element1) - - array2 := add(array1, 0x40) - mstore(array2, 1) - mstore(add(array2, 0x20), element2) - - mstore(0x40, add(array2, 0x40)) - } - } -} diff --git a/packages/hardhat/contracts/ERC20.sol b/packages/hardhat/contracts/ERC20.sol deleted file mode 100644 index 87629d72..00000000 --- a/packages/hardhat/contracts/ERC20.sol +++ /dev/null @@ -1,360 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) - -pragma solidity ^0.8.19; - -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; -import "@openzeppelin/contracts/utils/Context.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 ERC20 - * applications. - * - * Additionally, an {Approval} event is emitted on calls to {transferFrom}. - * This allows applications to reconstruct the allowance for all accounts just - * by listening to said events. Other implementations of the EIP may not emit - * these events, as it isn't required by the specification. - * - * Finally, the non-standard {decreaseAllowance} and {increaseAllowance} - * functions have been added to mitigate the well-known issues around setting - * allowances. See {IERC20-approve}. - */ -contract ERC20 is Context, IERC20, IERC20Metadata { - mapping(address => uint256) private _balances; - - mapping(address => mapping(address => uint256)) private _allowances; - - uint256 private _totalSupply; - - string private _name; - string private _symbol; - - /** - * @dev Sets the values for {name} and {symbol}. - * - * All two of these 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; - } - - /** - * @dev See {IERC20-totalSupply}. - */ - function totalSupply() public view virtual returns (uint256) { - return _totalSupply; - } - - /** - * @dev See {IERC20-balanceOf}. - */ - 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 `amount`. - */ - function transfer( - address to, - uint256 amount - ) public virtual returns (bool) { - address owner = _msgSender(); - _transfer(owner, to, amount); - return true; - } - - /** - * @dev See {IERC20-allowance}. - */ - function allowance( - address owner, - address spender - ) public view virtual returns (uint256) { - return _allowances[owner][spender]; - } - - /** - * @dev See {IERC20-approve}. - * - * NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on - * `transferFrom`. This is semantically equivalent to an infinite approval. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function approve( - address spender, - uint256 amount - ) public virtual returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, amount); - return true; - } - - /** - * @dev See {IERC20-transferFrom}. - * - * Emits an {Approval} event indicating the updated allowance. This is not - * required by the EIP. See the note at the beginning of {ERC20}. - * - * NOTE: Does not update the allowance if the current allowance - * is the maximum `uint256`. - * - * Requirements: - * - * - `from` and `to` cannot be the zero address. - * - `from` must have a balance of at least `amount`. - * - the caller must have allowance for ``from``'s tokens of at least - * `amount`. - */ - function transferFrom( - address from, - address to, - uint256 amount - ) public virtual returns (bool) { - address spender = _msgSender(); - _spendAllowance(from, spender, amount); - _transfer(from, to, amount); - return true; - } - - /** - * @dev Atomically increases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - */ - function increaseAllowance( - address spender, - uint256 addedValue - ) public virtual returns (bool) { - address owner = _msgSender(); - _approve(owner, spender, allowance(owner, spender) + addedValue); - return true; - } - - /** - * @dev Atomically decreases the allowance granted to `spender` by the caller. - * - * This is an alternative to {approve} that can be used as a mitigation for - * problems described in {IERC20-approve}. - * - * Emits an {Approval} event indicating the updated allowance. - * - * Requirements: - * - * - `spender` cannot be the zero address. - * - `spender` must have allowance for the caller of at least - * `subtractedValue`. - */ - function decreaseAllowance( - address spender, - uint256 subtractedValue - ) public virtual returns (bool) { - address owner = _msgSender(); - uint256 currentAllowance = allowance(owner, spender); - require( - currentAllowance >= subtractedValue, - "ERC20: decreased allowance below zero" - ); - unchecked { - _approve(owner, spender, currentAllowance - subtractedValue); - } - - return true; - } - - /** - * @dev Moves `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 amount) internal { - require(from != address(0), "ERC20: transfer from the zero address"); - require(to != address(0), "ERC20: transfer to the zero address"); - _update(from, to, amount); - } - - /** - * @dev Transfers `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 amount - ) internal virtual { - if (from == address(0)) { - _totalSupply += amount; - } else { - uint256 fromBalance = _balances[from]; - require( - fromBalance >= amount, - "ERC20: transfer amount exceeds balance" - ); - unchecked { - // Overflow not possible: amount <= fromBalance <= totalSupply. - _balances[from] = fromBalance - amount; - } - } - - if (to == address(0)) { - unchecked { - // Overflow not possible: amount <= totalSupply or amount <= fromBalance <= totalSupply. - _totalSupply -= amount; - } - } else { - unchecked { - // Overflow not possible: balance + amount is at most totalSupply, which we know fits into a uint256. - _balances[to] += amount; - } - } - - emit Transfer(from, to, amount); - } - - /** - * @dev Creates `amount` 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 amount) internal { - require(account != address(0), "ERC20: mint to the zero address"); - _update(address(0), account, amount); - } - - /** - * @dev Destroys `amount` tokens from `account`, by transferring it to address(0). - * 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 amount) internal { - require(account != address(0), "ERC20: burn from the zero address"); - _update(account, address(0), amount); - } - - /** - * @dev Sets `amount` 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. - */ - function _approve( - address owner, - address spender, - uint256 amount - ) internal virtual { - require(owner != address(0), "ERC20: approve from the zero address"); - require(spender != address(0), "ERC20: approve to the zero address"); - - _allowances[owner][spender] = amount; - emit Approval(owner, spender, amount); - } - - /** - * @dev Updates `owner` s allowance for `spender` based on spent `amount`. - * - * Does not update the allowance amount in case of infinite allowance. - * Revert if not enough allowance is available. - * - * Might emit an {Approval} event. - */ - function _spendAllowance( - address owner, - address spender, - uint256 amount - ) internal virtual { - uint256 currentAllowance = allowance(owner, spender); - if (currentAllowance != type(uint256).max) { - require( - currentAllowance >= amount, - "ERC20: insufficient allowance" - ); - unchecked { - _approve(owner, spender, currentAllowance - amount); - } - } - } -} diff --git a/packages/hardhat/contracts/ERC721.sol b/packages/hardhat/contracts/ERC721.sol deleted file mode 100644 index bb797829..00000000 --- a/packages/hardhat/contracts/ERC721.sol +++ /dev/null @@ -1,551 +0,0 @@ -// SPDX-License-Identifier: MIT -// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol) - -pragma solidity ^0.8.19; - -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol"; -import "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol"; -import "@openzeppelin/contracts/utils/Context.sol"; -import "@openzeppelin/contracts/utils/Strings.sol"; -import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; - -/** - * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including - * the Metadata extension, but not including the Enumerable extension, which is available separately as - * {ERC721Enumerable}. - */ -contract ERC721 is Context, ERC165, IERC721, IERC721Metadata { - using Strings for uint256; - - // Token name - string private _name; - - // Token symbol - string private _symbol; - - // Mapping from token ID to owner address - mapping(uint256 => address) private _owners; - - // Mapping owner address to token count - mapping(address => uint256) private _balances; - - // Mapping from token ID to approved address - mapping(uint256 => address) private _tokenApprovals; - - // Mapping from owner to operator approvals - mapping(address => mapping(address => bool)) private _operatorApprovals; - - /** - * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection. - */ - constructor(string memory name_, string memory symbol_) { - _name = name_; - _symbol = symbol_; - } - - /** - * @dev See {IERC165-supportsInterface}. - */ - function supportsInterface( - bytes4 interfaceId - ) public view virtual override(ERC165, IERC165) returns (bool) { - return - interfaceId == type(IERC721).interfaceId || - interfaceId == type(IERC721Metadata).interfaceId || - super.supportsInterface(interfaceId); - } - - /** - * @dev See {IERC721-balanceOf}. - */ - function balanceOf(address owner) public view virtual returns (uint256) { - require( - owner != address(0), - "ERC721: address zero is not a valid owner" - ); - return _balances[owner]; - } - - /** - * @dev See {IERC721-ownerOf}. - */ - function ownerOf(uint256 tokenId) public view virtual returns (address) { - address owner = _ownerOf(tokenId); - require(owner != address(0), "ERC721: invalid token ID"); - return owner; - } - - /** - * @dev See {IERC721Metadata-name}. - */ - function name() public view virtual returns (string memory) { - return _name; - } - - /** - * @dev See {IERC721Metadata-symbol}. - */ - function symbol() public view virtual returns (string memory) { - return _symbol; - } - - /** - * @dev See {IERC721Metadata-tokenURI}. - */ - function tokenURI( - uint256 tokenId - ) public view virtual returns (string memory) { - _requireMinted(tokenId); - - string memory baseURI = _baseURI(); - return - bytes(baseURI).length > 0 - ? string(abi.encodePacked(baseURI, tokenId.toString())) - : ""; - } - - /** - * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each - * token will be the concatenation of the `baseURI` and the `tokenId`. Empty - * by default, can be overridden in child contracts. - */ - function _baseURI() internal view virtual returns (string memory) { - return ""; - } - - /** - * @dev See {IERC721-approve}. - */ - function approve(address to, uint256 tokenId) public virtual { - address owner = ownerOf(tokenId); - require(to != owner, "ERC721: approval to current owner"); - - require( - _msgSender() == owner || isApprovedForAll(owner, _msgSender()), - "ERC721: approve caller is not token owner or approved for all" - ); - - _approve(to, tokenId); - } - - /** - * @dev See {IERC721-getApproved}. - */ - function getApproved( - uint256 tokenId - ) public view virtual returns (address) { - _requireMinted(tokenId); - - return _tokenApprovals[tokenId]; - } - - /** - * @dev See {IERC721-setApprovalForAll}. - */ - function setApprovalForAll(address operator, bool approved) public virtual { - _setApprovalForAll(_msgSender(), operator, approved); - } - - /** - * @dev See {IERC721-isApprovedForAll}. - */ - function isApprovedForAll( - address owner, - address operator - ) public view virtual returns (bool) { - return _operatorApprovals[owner][operator]; - } - - /** - * @dev See {IERC721-transferFrom}. - */ - function transferFrom( - address from, - address to, - uint256 tokenId - ) public virtual { - //solhint-disable-next-line max-line-length - require( - _isApprovedOrOwner(_msgSender(), tokenId), - "ERC721: caller is not token owner or approved" - ); - - _transfer(from, to, tokenId); - } - - /** - * @dev See {IERC721-safeTransferFrom}. - */ - function safeTransferFrom( - address from, - address to, - uint256 tokenId - ) public virtual { - safeTransferFrom(from, to, tokenId, ""); - } - - /** - * @dev See {IERC721-safeTransferFrom}. - */ - function safeTransferFrom( - address from, - address to, - uint256 tokenId, - bytes memory data - ) public virtual { - require( - _isApprovedOrOwner(_msgSender(), tokenId), - "ERC721: caller is not token owner or approved" - ); - _safeTransfer(from, to, tokenId, data); - } - - /** - * @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients - * are aware of the ERC721 protocol to prevent tokens from being forever locked. - * - * `data` is additional data, it has no specified format and it is sent in call to `to`. - * - * This internal function is equivalent to {safeTransferFrom}, and can be used to e.g. - * implement alternative mechanisms to perform token transfer, such as signature-based. - * - * Requirements: - * - * - `from` cannot be the zero address. - * - `to` cannot be the zero address. - * - `tokenId` token must exist and be owned by `from`. - * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. - * - * Emits a {Transfer} event. - */ - function _safeTransfer( - address from, - address to, - uint256 tokenId, - bytes memory data - ) internal virtual { - _transfer(from, to, tokenId); - require( - _checkOnERC721Received(from, to, tokenId, data), - "ERC721: transfer to non ERC721Receiver implementer" - ); - } - - /** - * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist - */ - function _ownerOf(uint256 tokenId) internal view virtual returns (address) { - return _owners[tokenId]; - } - - /** - * @dev Returns whether `tokenId` exists. - * - * Tokens can be managed by their owner or approved accounts via {approve} or {setApprovalForAll}. - * - * Tokens start existing when they are minted (`_mint`), - * and stop existing when they are burned (`_burn`). - */ - function _exists(uint256 tokenId) internal view virtual returns (bool) { - return _ownerOf(tokenId) != address(0); - } - - /** - * @dev Returns whether `spender` is allowed to manage `tokenId`. - * - * Requirements: - * - * - `tokenId` must exist. - */ - function _isApprovedOrOwner( - address spender, - uint256 tokenId - ) internal view virtual returns (bool) { - address owner = ownerOf(tokenId); - return (spender == owner || - isApprovedForAll(owner, spender) || - getApproved(tokenId) == spender); - } - - /** - * @dev Safely mints `tokenId` and transfers it to `to`. - * - * Requirements: - * - * - `tokenId` must not exist. - * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. - * - * Emits a {Transfer} event. - */ - function _safeMint(address to, uint256 tokenId) internal virtual { - _safeMint(to, tokenId, ""); - } - - /** - * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is - * forwarded in {IERC721Receiver-onERC721Received} to contract recipients. - */ - function _safeMint( - address to, - uint256 tokenId, - bytes memory data - ) internal virtual { - _mint(to, tokenId); - require( - _checkOnERC721Received(address(0), to, tokenId, data), - "ERC721: transfer to non ERC721Receiver implementer" - ); - } - - /** - * @dev Mints `tokenId` and transfers it to `to`. - * - * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible - * - * Requirements: - * - * - `tokenId` must not exist. - * - `to` cannot be the zero address. - * - * Emits a {Transfer} event. - */ - function _mint(address to, uint256 tokenId) internal virtual { - require(to != address(0), "ERC721: mint to the zero address"); - require(!_exists(tokenId), "ERC721: token already minted"); - - _beforeTokenTransfer(address(0), to, tokenId, 1); - - // Check that tokenId was not minted by `_beforeTokenTransfer` hook - require(!_exists(tokenId), "ERC721: token already minted"); - - unchecked { - // Will not overflow unless all 2**256 token ids are minted to the same owner. - // Given that tokens are minted one by one, it is impossible in practice that - // this ever happens. Might change if we allow batch minting. - // The ERC fails to describe this case. - _balances[to] += 1; - } - - _owners[tokenId] = to; - - emit Transfer(address(0), to, tokenId); - - _afterTokenTransfer(address(0), to, tokenId, 1); - } - - /** - * @dev Destroys `tokenId`. - * The approval is cleared when the token is burned. - * This is an internal function that does not check if the sender is authorized to operate on the token. - * - * Requirements: - * - * - `tokenId` must exist. - * - * Emits a {Transfer} event. - */ - function _burn(uint256 tokenId) internal virtual { - address owner = ownerOf(tokenId); - - _beforeTokenTransfer(owner, address(0), tokenId, 1); - - // Update ownership in case tokenId was transferred by `_beforeTokenTransfer` hook - owner = ownerOf(tokenId); - - // Clear approvals - delete _tokenApprovals[tokenId]; - - // Decrease balance with checked arithmetic, because an `ownerOf` override may - // invalidate the assumption that `_balances[from] >= 1`. - _balances[owner] -= 1; - - delete _owners[tokenId]; - - emit Transfer(owner, address(0), tokenId); - - _afterTokenTransfer(owner, address(0), tokenId, 1); - } - - /** - * @dev Transfers `tokenId` from `from` to `to`. - * As opposed to {transferFrom}, this imposes no restrictions on msg.sender. - * - * Requirements: - * - * - `to` cannot be the zero address. - * - `tokenId` token must be owned by `from`. - * - * Emits a {Transfer} event. - */ - function _transfer( - address from, - address to, - uint256 tokenId - ) internal virtual { - require( - ownerOf(tokenId) == from, - "ERC721: transfer from incorrect owner" - ); - require(to != address(0), "ERC721: transfer to the zero address"); - - _beforeTokenTransfer(from, to, tokenId, 1); - - // Check that tokenId was not transferred by `_beforeTokenTransfer` hook - require( - ownerOf(tokenId) == from, - "ERC721: transfer from incorrect owner" - ); - - // Clear approvals from the previous owner - delete _tokenApprovals[tokenId]; - - // Decrease balance with checked arithmetic, because an `ownerOf` override may - // invalidate the assumption that `_balances[from] >= 1`. - _balances[from] -= 1; - - unchecked { - // `_balances[to]` could overflow in the conditions described in `_mint`. That would require - // all 2**256 token ids to be minted, which in practice is impossible. - _balances[to] += 1; - } - - _owners[tokenId] = to; - - emit Transfer(from, to, tokenId); - - _afterTokenTransfer(from, to, tokenId, 1); - } - - /** - * @dev Approve `to` to operate on `tokenId` - * - * Emits an {Approval} event. - */ - function _approve(address to, uint256 tokenId) internal virtual { - _tokenApprovals[tokenId] = to; - emit Approval(ownerOf(tokenId), to, tokenId); - } - - /** - * @dev Approve `operator` to operate on all of `owner` tokens - * - * Emits an {ApprovalForAll} event. - */ - function _setApprovalForAll( - address owner, - address operator, - bool approved - ) internal virtual { - require(owner != operator, "ERC721: approve to caller"); - _operatorApprovals[owner][operator] = approved; - emit ApprovalForAll(owner, operator, approved); - } - - /** - * @dev Reverts if the `tokenId` has not been minted yet. - */ - function _requireMinted(uint256 tokenId) internal view virtual { - require(_exists(tokenId), "ERC721: invalid token ID"); - } - - /** - * @dev Internal function to invoke {IERC721Receiver-onERC721Received} on a target address. - * The call is not executed if the target address is not a contract. - * - * @param from address representing the previous owner of the given token ID - * @param to target address that will receive the tokens - * @param tokenId uint256 ID of the token to be transferred - * @param data bytes optional data to send along with the call - * @return bool whether the call correctly returned the expected magic value - */ - function _checkOnERC721Received( - address from, - address to, - uint256 tokenId, - bytes memory data - ) private returns (bool) { - if (to.code.length > 0) { - try - IERC721Receiver(to).onERC721Received( - _msgSender(), - from, - tokenId, - data - ) - returns (bytes4 retval) { - return retval == IERC721Receiver.onERC721Received.selector; - } catch (bytes memory reason) { - if (reason.length == 0) { - revert( - "ERC721: transfer to non ERC721Receiver implementer" - ); - } else { - /// @solidity memory-safe-assembly - assembly { - revert(add(32, reason), mload(reason)) - } - } - } - } else { - return true; - } - } - - /** - * @dev Hook that is called before any token transfer. This includes minting and burning. If {ERC721Consecutive} is - * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. - * - * Calling conditions: - * - * - When `from` and `to` are both non-zero, ``from``'s tokens will be transferred to `to`. - * - When `from` is zero, the tokens will be minted for `to`. - * - When `to` is zero, ``from``'s tokens will be burned. - * - `from` and `to` are never both zero. - * - `batchSize` is non-zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _beforeTokenTransfer( - address from, - address to, - uint256 firstTokenId, - uint256 batchSize - ) internal virtual {} - - /** - * @dev Hook that is called after any token transfer. This includes minting and burning. If {ERC721Consecutive} is - * used, the hook may be called as part of a consecutive (batch) mint, as indicated by `batchSize` greater than 1. - * - * Calling conditions: - * - * - When `from` and `to` are both non-zero, ``from``'s tokens were transferred to `to`. - * - When `from` is zero, the tokens were minted for `to`. - * - When `to` is zero, ``from``'s tokens were burned. - * - `from` and `to` are never both zero. - * - `batchSize` is non-zero. - * - * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks]. - */ - function _afterTokenTransfer( - address from, - address to, - uint256 firstTokenId, - uint256 batchSize - ) internal virtual {} - - /** - * @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override. - * - * WARNING: Anyone calling this MUST ensure that the balances remain consistent with the ownership. The invariant - * being that for any address `a` the value returned by `balanceOf(a)` must be equal to the number of tokens such - * that `ownerOf(tokenId)` is `a`. - */ - // solhint-disable-next-line func-name-mixedcase - function __unsafe_increaseBalance( - address account, - uint256 amount - ) internal { - _balances[account] += amount; - } -} diff --git a/packages/hardhat/contracts/Greeter.sol b/packages/hardhat/contracts/Greeter.sol deleted file mode 100644 index f97d23b0..00000000 --- a/packages/hardhat/contracts/Greeter.sol +++ /dev/null @@ -1,21 +0,0 @@ -//SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -contract Greeter { - event newGreeting(string greeting, address sender); - - string private greeting; - - constructor(string memory _greet) { - greeting = _greet; - } - - function greet() external view returns (string memory) { - return greeting; - } - - function setGreeting(string calldata _greeting) external { - greeting = _greeting; - emit newGreeting(_greeting, msg.sender); - } -} diff --git a/packages/hardhat/contracts/Lock.sol b/packages/hardhat/contracts/Lock.sol new file mode 100644 index 00000000..50935f61 --- /dev/null +++ b/packages/hardhat/contracts/Lock.sol @@ -0,0 +1,34 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.9; + +// Uncomment this line to use console.log +// import "hardhat/console.sol"; + +contract Lock { + uint public unlockTime; + address payable public owner; + + event Withdrawal(uint amount, uint when); + + constructor(uint _unlockTime) payable { + require( + block.timestamp < _unlockTime, + "Unlock time should be in the future" + ); + + unlockTime = _unlockTime; + owner = payable(msg.sender); + } + + function withdraw() public { + // Uncomment this line, and the import of "hardhat/console.sol", to print a log in your terminal + // console.log("Unlock time is %o and block timestamp is %o", unlockTime, block.timestamp); + + require(block.timestamp >= unlockTime, "You can't withdraw yet"); + require(msg.sender == owner, "You aren't the owner"); + + emit Withdrawal(address(this).balance, block.timestamp); + + owner.transfer(address(this).balance); + } +} diff --git a/packages/hardhat/contracts/Storage.sol b/packages/hardhat/contracts/Storage.sol deleted file mode 100644 index aff4c81c..00000000 --- a/packages/hardhat/contracts/Storage.sol +++ /dev/null @@ -1,29 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -/** - * @title Storage - * @dev Store & retrieve value in a variable - */ -contract Storage { - event newNumber(uint256 number, address sender); - - uint256 private number = 1; - - /** - * @dev Store value in variable - * @param num value to store - */ - function store(uint256 num) external { - number = num; - emit newNumber(num, msg.sender); - } - - /** - * @dev Return value - * @return value of 'number' - */ - function retrieve() public view returns (uint256) { - return number; - } -} diff --git a/packages/hardhat/deploy/00-greeter.js b/packages/hardhat/deploy/00-greeter.js deleted file mode 100644 index d914dc10..00000000 --- a/packages/hardhat/deploy/00-greeter.js +++ /dev/null @@ -1,60 +0,0 @@ -// deploy/00_deploy_my_contract.js - -// const { ethers } = require("hardhat"); - -// const sleep = (ms) => -// new Promise((r) => -// setTimeout(() => { -// console.log(`waited for ${(ms / 1000).toFixed(3)} seconds`); -// r(); -// }, ms) -// ); - -module.exports = async ({ getNamedAccounts, deployments }) => { - const { deploy } = deployments; - - // Named Accounts are for improving developer experience, can be configured in hardhat.config.js - const { deployer } = await getNamedAccounts(); - - await deploy("Greeter", { - from: deployer, - args: ["hello world"], - log: true, - }); - - // Getting a previously deployed contract - // const Greeter = new ethers.Contract("Greeter", deployer); - - // await Greeter.setGreeting("Hello Celo!"); - - /* - // If you want to send value to an address from the deployer - - const deployerWallet = ethers.provider.getSigner() - await deployerWallet.sendTransaction({ - to: "0x34aA3F359A9D614239015126635CE7732c18fDF3", - value: ethers.utils.parseEther("0.001") - }) - */ - - /* - //If you want to send some CELO to a contract on deploy (make your constructor payable!) - const yourContract = await deploy("YourContract", [], { - value: ethers.utils.parseEther("0.05") - }); - */ - - /* - //If you want to link a library into your contract: - // reference: https://github.com/austintgriffith/scaffold-eth/blob/using-libraries-example/packages/hardhat/scripts/deploy.js#L19 - const yourContract = await deploy("YourContract", [], {}, { - LibraryName: **LibraryAddress** - }); - */ -}; - -/** - * Use tags to run specific deploy scripts - * For example:- npx hardhat deploy --tags Greeter will run only this script - */ -module.exports.tags = ["Greeter"]; diff --git a/packages/hardhat/deploy/01-storage.js b/packages/hardhat/deploy/01-storage.js deleted file mode 100644 index ecb6ce80..00000000 --- a/packages/hardhat/deploy/01-storage.js +++ /dev/null @@ -1,16 +0,0 @@ -module.exports = async ({ getNamedAccounts, deployments }) => { - const { deploy } = deployments; - const { deployer } = await getNamedAccounts(); - await deploy("Storage", { - // Learn more about args here: https://www.npmjs.com/package/hardhat-deploy#deploymentsdeploy - from: deployer, - //args: [ "Hello", ethers.utils.parseEther("1.5") ], - log: true, - }); -}; - -/** - * Use tags to run specific deploy scripts - * For example:- npx hardhat deploy --tags Storage will run only this script - */ -module.exports.tags = ["Storage"]; diff --git a/packages/hardhat/deploy/02-erc20.js b/packages/hardhat/deploy/02-erc20.js deleted file mode 100644 index 739d9726..00000000 --- a/packages/hardhat/deploy/02-erc20.js +++ /dev/null @@ -1,21 +0,0 @@ -const { ethers } = require("hardhat"); - -module.exports = async ({ getNamedAccounts, deployments }) => { - // Named Accounts are for improving developer experience, can be configured in hardhat.config.js - const { deployer, alice } = await getNamedAccounts(); - const { deploy } = deployments; - - let ERC20 = await deploy("ERC20 Token", { - from: deployer, - contract: "ERC20", - args: ["Test Token", "TT"], - log: true, - }); - - let erc20 = await ethers.getContractAt("ERC20", ERC20.address); - - let allowance = await erc20.allowance(erc20.address, alice); - console.log(allowance); -}; - -module.exports.tags = ["ERC20"]; diff --git a/packages/hardhat/deploy/03-erc721.js b/packages/hardhat/deploy/03-erc721.js deleted file mode 100644 index fde11fa1..00000000 --- a/packages/hardhat/deploy/03-erc721.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = async ({ getNamedAccounts, deployments }) => { - const { deployer } = await getNamedAccounts(); - const { deploy } = deployments; - - await deploy("ERC721 Token", { - from: deployer, - contract: "ERC721", - args: ["Test Token", "TT"], - log: true, - }); -}; - -module.exports.tags = ["ERC721"]; diff --git a/packages/hardhat/deploy/04-erc1155.js b/packages/hardhat/deploy/04-erc1155.js deleted file mode 100644 index 17d3b41d..00000000 --- a/packages/hardhat/deploy/04-erc1155.js +++ /dev/null @@ -1,13 +0,0 @@ -module.exports = async ({ getNamedAccounts, deployments }) => { - const { deployer } = await getNamedAccounts(); - const { deploy } = deployments; - - await deploy("ERC1155 Token", { - from: deployer, - contract: "ERC1155", - args: ["some uri"], - log: true, - }); -}; - -module.exports.tags = ["ERC1155"]; diff --git a/packages/hardhat/hardhat.config.js b/packages/hardhat/hardhat.config.js index 9fb628fc..22cc9dbe 100644 --- a/packages/hardhat/hardhat.config.js +++ b/packages/hardhat/hardhat.config.js @@ -1,104 +1,41 @@ -require("dotenv").config({ path: ".env" }); -require("hardhat-deploy"); -const { task } = require("hardhat/config"); -require("hardhat-celo"); +require("@nomicfoundation/hardhat-toolbox"); +require("dotenv").config(); -const defaultNetwork = "alfajores"; - -// This is the mnemonic used by celo-devchain -const DEVCHAIN_MNEMONIC = - "concert load couple harbor equip island argue ramp clarify fence smart topic"; - -// You need to export an object to set up your config -// Go to https://hardhat.org/config/ to learn more - -/** - * @type import('hardhat/config').HardhatUserConfig - */ +/** @type import('hardhat/config').HardhatUserConfig */ module.exports = { - defaultNetwork, + solidity: "0.8.17", networks: { - localhost: { - url: "http://127.0.0.1:8545", - accounts: { - mnemonic: DEVCHAIN_MNEMONIC, - }, - }, alfajores: { url: "https://alfajores-forno.celo-testnet.org", accounts: [process.env.PRIVATE_KEY], - chainId: 44787, }, celo: { url: "https://forno.celo.org", accounts: [process.env.PRIVATE_KEY], - chainId: 42220, }, }, etherscan: { apiKey: { - // Get it from here: https://celoscan.io/myapikey alfajores: process.env.CELOSCAN_API_KEY, celo: process.env.CELOSCAN_API_KEY, }, - }, - solidity: { - version: "0.8.19", - }, - /** - * Named Accounts become available as variable names in scripts - * Learn more: https://github.com/wighawag/hardhat-deploy#1-namedaccounts-ability-to-name-addresses - */ - namedAccounts: { - deployer: 0, - alice: 1, - bob: 2, - }, - typechain: { - outDir: "types", - target: "web3-v1", - alwaysGenerateOverloads: false, // should overloads with full signatures like deposit(uint256) be generated always, even if there are no overloads? - externalArtifacts: ["externalArtifacts/*.json"], // optional array of glob patterns with external artifacts to process (for example external libs from node_modules) + customChains: [ + { + network: "alfajores", + chainId: 44787, + urls: { + apiURL: "https://api-alfajores.celoscan.io/api", + browserURL: "https://alfajores.celoscan.io", + }, + }, + { + network: "celo", + chainId: 42220, + urls: { + apiURL: "https://api.celoscan.io/api", + browserURL: "https://celoscan.io/", + }, + }, + ], }, }; - -// This is a sample Hardhat task. To learn how to create your own go to -// https://hardhat.org/guides/create-task.html - -task("accounts", "Prints the list of accounts", async (taskArgs, hre) => { - const accounts = await hre.ethers.getSigners(); - - for (const account of accounts) { - console.log(account.address); - } -}); - -task( - "devchain-keys", - "Prints the private keys associated with the devchain", - async (taskArgs, hre) => { - const accounts = await hre.ethers.getSigners(); - const hdNode = hre.ethers.utils.HDNode.fromMnemonic(DEVCHAIN_MNEMONIC); - for (let i = 0; i < accounts.length; i++) { - const account = hdNode.derivePath(`m/44'/60'/0'/0/${i}`); - console.log( - `Account ${i}\nAddress: ${account.address}\nKey: ${account.privateKey}` - ); - } - } -); - -task("create-account", "Prints a new private key", async () => { - const wallet = new hre.ethers.Wallet.createRandom(); - console.log(`PRIVATE_KEY="` + wallet.privateKey + `"`); - console.log(`Your account address: `, wallet.address); -}); - -task( - "print-account", - "Prints the address of the account associated with the private key in .env file", - () => { - const wallet = new hre.ethers.Wallet(process.env.PRIVATE_KEY); - console.log(`Account: `, wallet.address); - } -); diff --git a/packages/hardhat/package.json b/packages/hardhat/package.json index bb7a1099..547bb815 100644 --- a/packages/hardhat/package.json +++ b/packages/hardhat/package.json @@ -2,30 +2,28 @@ "name": "@celo-composer/hardhat", "version": "1.0.0", "license": "MIT", - "scripts": { - "test": "hardhat test", - "test-local": "hardhat test --network hardhat", - "create-account": "hardhat create-account", - "accounts": "hardhat accounts", - "devchain": "npx celo-devchain --port 8545", - "deploy": "hardhat deploy --export-all deployments/hardhat_contracts.json", - "deploy-reset-watch": "hardhat deploy --reset --watch --export-all deployments/hardhat_contracts.json", - "watch": "node scripts/watch.js", - "fork-mainnet": "ganache --fork.url https://forno.celo.org --wallet.mnemonic 'concert load couple harbor equip island argue ramp clarify fence smart topic' --wallet.accountKeysPath './account_keys.json' --gasPrice 875000000" - }, "devDependencies": { - "@terminal-fi/celo-devchain": "^4.0.1", - "@typechain/web3-v1": "^6.0.1", - "bip39": "^3.0.4", - "dotenv": "^16.0.3", - "hardhat-celo": "^0.0.6", - "hardhat-deploy": "^0.11.19", - "node-watch": "^0.7.3" + "@nomicfoundation/hardhat-chai-matchers": "^1.0.0", + "@nomicfoundation/hardhat-network-helpers": "^1.0.0", + "@nomicfoundation/hardhat-toolbox": "^2.0.2", + "@nomiclabs/hardhat-ethers": "^2.0.0", + "@nomiclabs/hardhat-etherscan": "^3.0.0", + "@typechain/ethers-v5": "^10.1.0", + "@typechain/hardhat": "^6.1.2", + "@types/chai": "^4.2.0", + "@types/mocha": ">=9.1.0", + "chai": "^4.2.0", + "hardhat": "^2.19.1", + "hardhat-gas-reporter": "^1.0.8", + "solidity-coverage": "^0.8.1", + "ts-node": ">=8.0.0", + "typechain": "^8.1.0", + "typescript": ">=4.5.0" + }, + "scripts": { + "compile": "npx hardhat compile" }, "dependencies": { - "@celo/contracts": "^9.0.0", - "@openzeppelin/contracts": "^4.9.3", - "ganache": "^7.5.0", - "typescript": "^4.8.4" + "dotenv": "^16.3.1" } } diff --git a/packages/hardhat/scripts/deploy.js b/packages/hardhat/scripts/deploy.js new file mode 100644 index 00000000..bd0cd6c2 --- /dev/null +++ b/packages/hardhat/scripts/deploy.js @@ -0,0 +1,33 @@ +// We require the Hardhat Runtime Environment explicitly here. This is optional +// but useful for running the script in a standalone fashion through `node