diff --git a/.gitmodules b/.gitmodules index ba4d322..3d98e21 100644 --- a/.gitmodules +++ b/.gitmodules @@ -12,4 +12,4 @@ url = https://github.com/transmissions11/solmate [submodule "icy-btc/lib/solady"] path = icy-btc/lib/solady - url = https://github.com/vectorized/solady + url = https://github.com/vectorized/solady \ No newline at end of file diff --git a/memo-nft/.editorconfig b/memo-nft/.editorconfig new file mode 100644 index 0000000..746ae31 --- /dev/null +++ b/memo-nft/.editorconfig @@ -0,0 +1,19 @@ +# EditorConfig http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# All files +[*] +charset = utf-8 +end_of_line = lf +indent_size = 2 +indent_style = space +insert_final_newline = true +trim_trailing_whitespace = true + +[*.sol] +indent_size = 4 + +[*.tree] +indent_size = 1 diff --git a/memo-nft/.env.example b/memo-nft/.env.example new file mode 100644 index 0000000..c15991c --- /dev/null +++ b/memo-nft/.env.example @@ -0,0 +1,4 @@ +ETHERSCAN_API_KEY= +BASE_SEPOLIA_RPC= +BASE_RPC= +WALLET_PRIVATE_KEY= \ No newline at end of file diff --git a/memo-nft/.gitignore b/memo-nft/.gitignore new file mode 100644 index 0000000..532f85f --- /dev/null +++ b/memo-nft/.gitignore @@ -0,0 +1,20 @@ +# directories +cache +coverage +node_modules +out + +# files +*.env +*.log +.DS_Store +.pnp.* +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock + +# broadcasts +# !broadcast +# broadcast/* +# broadcast/*/31337/ diff --git a/memo-nft/.prettierignore b/memo-nft/.prettierignore new file mode 100644 index 0000000..3996d20 --- /dev/null +++ b/memo-nft/.prettierignore @@ -0,0 +1,17 @@ +# directories +broadcast +cache +coverage +node_modules +out + +# files +*.env +*.log +.DS_Store +.pnp.* +bun.lockb +lcov.info +package-lock.json +pnpm-lock.yaml +yarn.lock diff --git a/memo-nft/.prettierrc.yml b/memo-nft/.prettierrc.yml new file mode 100644 index 0000000..8e7d153 --- /dev/null +++ b/memo-nft/.prettierrc.yml @@ -0,0 +1,3 @@ +printWidth: 120 +proseWrap: "always" +trailingComma: "all" diff --git a/memo-nft/.solhint.json b/memo-nft/.solhint.json new file mode 100644 index 0000000..fe78add --- /dev/null +++ b/memo-nft/.solhint.json @@ -0,0 +1,14 @@ +{ + "extends": "solhint:recommended", + "rules": { + "code-complexity": ["error", 8], + "compiler-version": ["error", ">=0.8.28"], + "func-name-mixedcase": "off", + "func-visibility": ["error", { "ignoreConstructors": true }], + "max-line-length": ["error", 120], + "named-parameters-mapping": "warn", + "no-console": "off", + "not-rely-on-time": "off", + "one-contract-per-file": "off" + } +} diff --git a/memo-nft/README.md b/memo-nft/README.md new file mode 100644 index 0000000..387c46c --- /dev/null +++ b/memo-nft/README.md @@ -0,0 +1,57 @@ +# This repo is an implementation of the Memo NFT contract. + +## Contract + +- [DwarvesMemo.sol](./src/DwarvesMemo.sol) + +## Overview +We're developing an upgradable ERC1155 smart contract that integrates with Arweave for storing NFT metadata. This contract will allow the owner to create new NFT types mapped to Arweave transaction IDs, while enabling anyone to mint tokens of these established types. + +### Features +- Upgradable +- ERC1155 +- Integrates with Arweave +- ... + +### Smart Contract Functionalities +1. `createTokenType (onlyOwner)` -> Maps a new NFT ID to an Arweave transaction ID +2. `updateTokenType (onlyOwner)` -> Updates the Arweave transaction ID for an existing NFT ID +3. `mintNFT (public)` -> Mints a new NFT token +4. `readNFT (public)` -> Returns the Arweave gateway URL for the token's metadata +5. `getUniqueMinterCount (public)` -> Returns the total number of unique addresses that have minted at least one NFT + +## Usage +### Prerequisites +- Install `Bun` CLI (https://bun.sh/docs/installation) +- Install `Foundry` (https://getfoundry.sh/) +- Install dependencies: `bun install` +- Update `.env` file with your own values (see `.env.example`) + +### Available commands +1. Build commands +- `bun run build` -> Build the contract (always run this before deploying) + +2. Deploy commands +- `bun run deploy:testnet` -> Deploy to Base Sepolia +- `bun run deploy:mainnet` -> Deploy to Base Mainnet + +3. Upgrade commands +- `bun run upgrade:testnet` -> Upgrade on Base Sepolia +- `bun run upgrade:mainnet` -> Upgrade on Base Mainnet + +4. Other commands +- `bun run test` -> Run tests +- `bun run lint` -> Run lint +- `bun run format` -> Format code + +## Latest Deployments +1. Testnet +- [Proxy](https://sepolia.basescan.org/address/0xb1e052156676750D193D800D7D91eA0C7cEeAdF0) + +2. Mainnet +- ... + +## Resources +- [Arweave Integration](https://academy.developerdao.com/tracks/arweave-101/2) +- [Foundry Book](https://book.getfoundry.sh/) +- [Foundry Template](https://github.com/PaulRBerg/foundry-template) \ No newline at end of file diff --git a/memo-nft/broadcast/DeployScript.s.sol/8453/run-1742959126.json b/memo-nft/broadcast/DeployScript.s.sol/8453/run-1742959126.json new file mode 100644 index 0000000..6f8df8f --- /dev/null +++ b/memo-nft/broadcast/DeployScript.s.sol/8453/run-1742959126.json @@ -0,0 +1,190 @@ +{ + "transactions": [ + { + "hash": "0x6688ded770d780e68d27d66c9dd172fc41317a01e7fd49eccebe3422c8288c9e", + "transactionType": "CREATE", + "contractName": "DwarvesMemo", + "contractAddress": "0x7c842f982a02f665ed67e3c685c507d772a1d8aa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "gas": "0x3b17f7", + "value": "0x0", + "input": "0x60a06040523060805234801561001457600080fd5b5061001d610022565b6100d4565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100725760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d15780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6080516134d66100fd60003960008181611aa401528181611acd0152611c7d01526134d66000f3fe6080604052600436106101e25760003560e01c80637545511711610102578063c48283ff11610095578063f242432a11610064578063f242432a14610682578063f2fde38b146106a2578063f62d1888146106c2578063fa2a60b7146106e257600080fd5b8063c48283ff146105ba578063d547741f146105da578063e7c539e4146105fa578063e985e9c51461061a57600080fd5b8063a217fddf116100d1578063a217fddf1461051c578063a22cb46514610531578063ad3cb1cc14610551578063c407e27a1461059a57600080fd5b8063754551171461041c5780638da5cb5b1461045057806391d14854146104975780639a41f4df146104fc57600080fd5b806333c7ad3d1161017a5780634f1ef286116101495780634f1ef286146103ca57806352d1902d146103dd57806366a07714146103f2578063715018a61461040757600080fd5b806333c7ad3d1461034857806336568abe14610368578063410729db146103885780634e1273f41461039d57600080fd5b80631e7663bc116101b65780631e7663bc14610297578063248a9ca3146102b75780632eb2c2d6146103065780632f2ff15d1461032857600080fd5b8062fdd58e146101e757806301ffc9a71461021a5780630e89341c1461024a5780631a3e69b714610277575b600080fd5b3480156101f357600080fd5b50610207610202366004612aa9565b610702565b6040519081526020015b60405180910390f35b34801561022657600080fd5b5061023a610235366004612b01565b61074b565b6040519015158152602001610211565b34801561025657600080fd5b5061026a610265366004612b1e565b610756565b6040516102119190612b87565b34801561028357600080fd5b50610207610292366004612c71565b61082d565b3480156102a357600080fd5b506102076102b2366004612c71565b610a32565b3480156102c357600080fd5b506102076102d2366004612b1e565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561031257600080fd5b50610326610321366004612d3f565b610ac0565b005b34801561033457600080fd5b50610326610343366004612df5565b610b7e565b34801561035457600080fd5b50610326610363366004612e21565b610bc8565b34801561037457600080fd5b50610326610383366004612df5565b610c01565b34801561039457600080fd5b50600454610207565b3480156103a957600080fd5b506103bd6103b8366004612e3c565b610c52565b6040516102119190612f41565b6103266103d8366004612f54565b610d38565b3480156103e957600080fd5b50610207610d53565b3480156103fe57600080fd5b5061026a610d82565b34801561041357600080fd5b50610326610e10565b34801561042857600080fd5b506102077f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a2199598481565b34801561045c57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b039091168152602001610211565b3480156104a357600080fd5b5061023a6104b2366004612df5565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561050857600080fd5b50610326610517366004612f98565b610e24565b34801561052857600080fd5b50610207600081565b34801561053d57600080fd5b5061032661054c366004612fc9565b61112f565b34801561055d57600080fd5b5061026a6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b3480156105a657600080fd5b506103266105b5366004612c71565b61113a565b3480156105c657600080fd5b506103266105d5366004613005565b61118d565b3480156105e657600080fd5b506103266105f5366004612df5565b6112eb565b34801561060657600080fd5b5061026a610615366004612b1e565b61132f565b34801561062657600080fd5b5061023a610635366004613027565b6001600160a01b0391821660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45016020908152604080832093909416825291909152205460ff1690565b34801561068e57600080fd5b5061032661069d366004613051565b611463565b3480156106ae57600080fd5b506103266106bd366004612e21565b611519565b3480156106ce57600080fd5b506103266106dd366004612c71565b611570565b3480156106ee57600080fd5b506102076106fd366004612b1e565b611756565b60008181527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500602090815260408083206001600160a01b03861684529091529020545b92915050565b6000610745826117ee565b7f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c450280546060917f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500916107a7906130aa565b80601f01602080910402602001604051908101604052809291908181526020018280546107d3906130aa565b80156108205780601f106107f557610100808354040283529160200191610820565b820191906000526020600020905b81548152906001019060200180831161080357829003601f168201915b5050505050915050919050565b60007f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a2199598461085981611844565b60008351116108ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f41727765617665207472616e73616374696f6e2049442063616e6e6f7420626560448201527f20656d707479000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001836040516108ff91906130f7565b90815260200160405180910390205460001461099d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f41727765617665207472616e73616374696f6e20494420616c7265616479206960448201527f6e2075736500000000000000000000000000000000000000000000000000000060648201526084016108e6565b60058054600091826109ae83613142565b9091555060008181526002602052604090209091506109cd85826131c1565b50806001856040516109df91906130f7565b908152602001604051809103902081905550807f908dd6565f4c34376a0ff039f93dd3684f6adf7e9298e189190cd2a63fe6e59c85604051610a219190612b87565b60405180910390a291505b50919050565b600080600183604051610a4591906130f7565b908152602001604051809103902054905080600003610745576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b336001600160a01b0386168114801590610b1f57506001600160a01b0380871660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4501602090815260408083209385168352929052205460ff16155b15610b69576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152871660248201526044016108e6565b610b76868686868661184e565b505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610bb881611844565b610bc283836118e8565b50505050565b6000610bd381611844565b610bfd7f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a2199598483610b7e565b5050565b6001600160a01b0381163314610c43576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c4d82826119d5565b505050565b60608151835114610c9c57815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016108e6565b6000835167ffffffffffffffff811115610cb857610cb8612b9a565b604051908082528060200260200182016040528015610ce1578160200160208202803683370190505b50905060005b8451811015610d3057602080820286010151610d0b90602080840287010151610702565b828281518110610d1d57610d1d6132bc565b6020908102919091010152600101610ce7565b509392505050565b610d40611a99565b610d4982611b69565b610bfd8282611b71565b6000610d5d611c72565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60008054610d8f906130aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610dbb906130aa565b8015610e085780601f10610ddd57610100808354040283529160200191610e08565b820191906000526020600020905b815481529060010190602001808311610deb57829003601f168201915b505050505081565b610e18611cd4565b610e226000611d48565b565b7f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a21995984610e4e81611844565b6000825111610edf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f41727765617665207472616e73616374696f6e2049442063616e6e6f7420626560448201527f20656d707479000000000000000000000000000000000000000000000000000060648201526084016108e6565b60008381526002602052604081208054610ef8906130aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610f24906130aa565b8015610f715780601f10610f4657610100808354040283529160200191610f71565b820191906000526020600020905b815481529060010190602001808311610f5457829003601f168201915b505050505090506000815111610fe3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b600183604051610ff391906130f7565b908152602001604051809103902054600014611091576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4e65772041727765617665207472616e73616374696f6e20494420616c72656160448201527f647920696e20757365000000000000000000000000000000000000000000000060648201526084016108e6565b60006001826040516110a391906130f7565b90815260408051602092819003830190209290925560008681526002909152206110cd84826131c1565b50836001846040516110df91906130f7565b908152602001604051809103902081905550837fd5082771b8e8c48b49a0749b21fce448072a6be7d0e819387837d8138171f1ce846040516111219190612b87565b60405180910390a250505050565b610bfd338383611dd1565b600061114581611844565b600061115183826131c1565b507fa8f1b08951572f7d2ea88146630e414c5040efde11d0212ed888789182f66c67826040516111819190612b87565b60405180910390a15050565b600082815260026020526040812080546111a6906130aa565b90501161120f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b61122a33838360405180602001604052806000815250611ec3565b600082815260066020526040812080548392906112489084906132eb565b90915550503360009081526003602052604090205460ff166112b05733600090815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560048054916112aa83613142565b91905055505b604051818152829033907f96234cb3d6c373a1aaa06497a540bc166d4b0359243a088eaf95e21d7253d0be9060200160405180910390a35050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015461132581611844565b610bc283836119d5565b60008181526002602052604081208054606092919061134d906130aa565b80601f0160208091040260200160405190810160405280929190818152602001828054611379906130aa565b80156113c65780601f1061139b576101008083540402835291602001916113c6565b820191906000526020600020905b8154815290600101906020018083116113a957829003601f168201915b505050505090506000815111611438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b60008160405160200161144c9291906132fe565b604051602081830303815290604052915050919050565b336001600160a01b03861681148015906114c257506001600160a01b0380871660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4501602090815260408083209385168352929052205460ff16155b1561150c576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152871660248201526044016108e6565b610b768686868686611f39565b611521611cd4565b6001600160a01b038116611564576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b61156d81611d48565b50565b600061157a611ffa565b805490915060ff68010000000000000000820416159067ffffffffffffffff166000811580156115a75750825b905060008267ffffffffffffffff1660011480156115c45750303b155b9050811580156115d2575080155b15611609576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001178555831561166a5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b61167386612023565b61167c33612034565b611684612045565b61168c612045565b6116976000336118e8565b506116c27f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a21995984336118e8565b506001600555604080516060810190915260218082526134a960208301396000906116ed90826131c1565b508315610b765784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050505050565b60008181526002602052604081208054829190611772906130aa565b9050116117db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b5060009081526006602052604090205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061074557506107458261204d565b61156d8133612130565b6001600160a01b038416611891576040517f57f447ce000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6001600160a01b0385166118d4576040517f01a83514000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6118e185858585856121bd565b5050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff166119cb576000848152602082815260408083206001600160a01b0387168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556119813390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610745565b6000915050610745565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff16156119cb576000848152602082815260408083206001600160a01b038716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610745565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611b3257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b267f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15610e22576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61156d611cd4565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611bcb575060408051601f3d908101601f19168201909252611bc8918101906133a2565b60015b611c0c576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b03831660048201526024016108e6565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611c68576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016108e6565b610c4d8383612210565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e22576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33611d067f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610e22576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016108e6565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff000000000000000000000000000000000000000081166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45006001600160a01b038316611e35576040517fced3e100000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6001600160a01b03848116600081815260018401602090815260408083209488168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b6001600160a01b038416611f06576040517f57f447ce000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b60408051600180825260208201869052818301908152606082018590526080820190925290610b766000878484876121bd565b6001600160a01b038416611f7c576040517f57f447ce000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6001600160a01b038516611fbf576040517f01a83514000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b60408051600180825260208201869052818301908152606082018590526080820190925290611ff187878484876121bd565b50505050505050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610745565b61202b612266565b61156d816122a4565b61203c612266565b61156d816122b5565b610e22612266565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a260000000000000000000000000000000000000000000000000000000014806120e057507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061074557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610745565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16610bfd576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016108e6565b6121c9858585856122bd565b6001600160a01b038416156118e1578251339060010361220257602084810151908401516121fb838989858589612526565b5050610b76565b610b768187878787876126c6565b61221982612812565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561225e57610c4d82826128ba565b610bfd612930565b61226e612968565b610e22576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122ac612266565b61156d81612987565b611521612266565b805182517f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500911461232757825182516040517f5b059991000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016108e6565b3360005b8451811015612446576020818102868101820151908601909101516001600160a01b038916156123f7576000828152602086815260408083206001600160a01b038d168452909152902054818110156123d0576040517f03dee4c50000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526024810182905260448101839052606481018490526084016108e6565b6000838152602087815260408083206001600160a01b038e16845290915290209082900390555b6001600160a01b0388161561243c576000828152602086815260408083206001600160a01b038c168452909152812080548392906124369084906132eb565b90915550505b505060010161232b565b5083516001036124c75760208401516000906020850151909150866001600160a01b0316886001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516124b8929190918252602082015260400190565b60405180910390a45050610b76565b846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516125169291906133bb565b60405180910390a4505050505050565b6001600160a01b0384163b15610b76576040517ff23a6e610000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063f23a6e619061258390899089908890889088906004016133e0565b6020604051808303816000875af19250505080156125be575060408051601f3d908101601f191682019092526125bb91810190613428565b60015b612640573d8080156125ec576040519150601f19603f3d011682016040523d82523d6000602084013e6125f1565b606091505b508051600003612638576040517f57f447ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526024016108e6565b805181602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e610000000000000000000000000000000000000000000000000000000014611ff1576040517f57f447ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526024016108e6565b6001600160a01b0384163b15610b76576040517fbc197c810000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063bc197c81906127239089908990889088908890600401613445565b6020604051808303816000875af192505050801561275e575060408051601f3d908101601f1916820190925261275b91810190613428565b60015b61278c573d8080156125ec576040519150601f19603f3d011682016040523d82523d6000602084013e6125f1565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c810000000000000000000000000000000000000000000000000000000014611ff1576040517f57f447ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526024016108e6565b806001600160a01b03163b600003612861576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016108e6565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516128d791906130f7565b600060405180830381855af49150503d8060008114612912576040519150601f19603f3d011682016040523d82523d6000602084013e612917565b606091505b50915091506129278583836129d3565b95945050505050565b3415610e22576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612972611ffa565b5468010000000000000000900460ff16919050565b7f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45007f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4502610c4d83826131c1565b6060826129e8576129e382612a4b565b612a44565b81511580156129ff57506001600160a01b0384163b155b15612a41576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016108e6565b50805b9392505050565b805115612a5b5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356001600160a01b0381168114612aa457600080fd5b919050565b60008060408385031215612abc57600080fd5b612ac583612a8d565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461156d57600080fd5b600060208284031215612b1357600080fd5b8135612a4481612ad3565b600060208284031215612b3057600080fd5b5035919050565b60005b83811015612b52578181015183820152602001612b3a565b50506000910152565b60008151808452612b73816020860160208601612b37565b601f01601f19169290920160200192915050565b602081526000612a446020830184612b5b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612bf257612bf2612b9a565b604052919050565b600082601f830112612c0b57600080fd5b81356020830160008067ffffffffffffffff841115612c2c57612c2c612b9a565b50601f8301601f1916602001612c4181612bc9565b915050828152858383011115612c5657600080fd5b82826020830137600092810160200192909252509392505050565b600060208284031215612c8357600080fd5b813567ffffffffffffffff811115612c9a57600080fd5b612ca684828501612bfa565b949350505050565b600067ffffffffffffffff821115612cc857612cc8612b9a565b5060051b60200190565b600082601f830112612ce357600080fd5b8135612cf6612cf182612cae565b612bc9565b8082825260208201915060208360051b860101925085831115612d1857600080fd5b602085015b83811015612d35578035835260209283019201612d1d565b5095945050505050565b600080600080600060a08688031215612d5757600080fd5b612d6086612a8d565b9450612d6e60208701612a8d565b9350604086013567ffffffffffffffff811115612d8a57600080fd5b612d9688828901612cd2565b935050606086013567ffffffffffffffff811115612db357600080fd5b612dbf88828901612cd2565b925050608086013567ffffffffffffffff811115612ddc57600080fd5b612de888828901612bfa565b9150509295509295909350565b60008060408385031215612e0857600080fd5b82359150612e1860208401612a8d565b90509250929050565b600060208284031215612e3357600080fd5b612a4482612a8d565b60008060408385031215612e4f57600080fd5b823567ffffffffffffffff811115612e6657600080fd5b8301601f81018513612e7757600080fd5b8035612e85612cf182612cae565b8082825260208201915060208360051b850101925087831115612ea757600080fd5b6020840193505b82841015612ed057612ebf84612a8d565b825260209384019390910190612eae565b9450505050602083013567ffffffffffffffff811115612eef57600080fd5b612efb85828601612cd2565b9150509250929050565b600081518084526020840193506020830160005b82811015612f37578151865260209586019590910190600101612f19565b5093949350505050565b602081526000612a446020830184612f05565b60008060408385031215612f6757600080fd5b612f7083612a8d565b9150602083013567ffffffffffffffff811115612f8c57600080fd5b612efb85828601612bfa565b60008060408385031215612fab57600080fd5b82359150602083013567ffffffffffffffff811115612f8c57600080fd5b60008060408385031215612fdc57600080fd5b612fe583612a8d565b915060208301358015158114612ffa57600080fd5b809150509250929050565b6000806040838503121561301857600080fd5b50508035926020909101359150565b6000806040838503121561303a57600080fd5b61304383612a8d565b9150612e1860208401612a8d565b600080600080600060a0868803121561306957600080fd5b61307286612a8d565b945061308060208701612a8d565b93506040860135925060608601359150608086013567ffffffffffffffff811115612ddc57600080fd5b600181811c908216806130be57607f821691505b602082108103610a2c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60008251613109818460208701612b37565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361317357613173613113565b5060010190565b601f821115610c4d57806000526020600020601f840160051c810160208510156131a15750805b601f840160051c820191505b818110156118e157600081556001016131ad565b815167ffffffffffffffff8111156131db576131db612b9a565b6131ef816131e984546130aa565b8461317a565b6020601f821160018114613241576000831561320b5750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556118e1565b600084815260208120601f198516915b828110156132715787850151825560209485019460019092019101613251565b50848210156132ad57868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8082018082111561074557610745613113565b600080845461330c816130aa565b600182168015613323576001811461335657613386565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652811515820286019350613386565b87600052602060002060005b8381101561337e57815488820152600190910190602001613362565b505081860193505b5050508351613399818360208801612b37565b01949350505050565b6000602082840312156133b457600080fd5b5051919050565b6040815260006133ce6040830185612f05565b82810360208401526129278185612f05565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a06080820152600061341d60a0830184612b5b565b979650505050505050565b60006020828403121561343a57600080fd5b8151612a4481612ad3565b6001600160a01b03861681526001600160a01b038516602082015260a06040820152600061347660a0830186612f05565b82810360608401526134888186612f05565b9050828103608084015261349c8185612b5b565b9897505050505050505056fe68747470733a2f2f617277656176652e646576656c6f70657264616f2e636f6d2fa164736f6c634300081d000a", + "nonce": "0x3", + "chainId": "0x2105" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionType": "CREATE", + "contractName": "ERC1967Proxy", + "contractAddress": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "function": null, + "arguments": [ + "0x7c842f982A02F665ED67E3C685c507d772a1d8aa", + "0xf62d18880000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6578616d706c652e636f6d2f6d657461646174612f7b69647d2e6a736f6e0000000000000000000000000000000000000000000000000000" + ], + "transaction": { + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "gas": "0x794f3", + "value": "0x0", + "input": "0x60806040526040516103f43803806103f483398101604081905261002291610268565b61002c8282610033565b5050610358565b61003c82610092565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561008657610081828261010e565b505050565b61008e610185565b5050565b806001600160a01b03163b6000036100cd57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161012b919061033c565b600060405180830381855af49150503d8060008114610166576040519150601f19603f3d011682016040523d82523d6000602084013e61016b565b606091505b50909250905061017c8583836101a6565b95945050505050565b34156101a45760405163b398979f60e01b815260040160405180910390fd5b565b6060826101bb576101b682610205565b6101fe565b81511580156101d257506001600160a01b0384163b155b156101fb57604051639996b31560e01b81526001600160a01b03851660048201526024016100c4565b50805b9392505050565b8051156102155780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b634e487b7160e01b600052604160045260246000fd5b60005b8381101561025f578181015183820152602001610247565b50506000910152565b6000806040838503121561027b57600080fd5b82516001600160a01b038116811461029257600080fd5b60208401519092506001600160401b038111156102ae57600080fd5b8301601f810185136102bf57600080fd5b80516001600160401b038111156102d8576102d861022e565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103065761030661022e565b60405281815282820160200187101561031e57600080fd5b61032f826020830160208601610244565b8093505050509250929050565b6000825161034e818460208701610244565b9190910192915050565b608e806103666000396000f3fe6080604052600a600c565b005b60186014601a565b605e565b565b600060597f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e808015607c573d6000f35b3d6000fdfea164736f6c634300081d000a0000000000000000000000007c842f982a02f665ed67e3c685c507d772a1d8aa00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084f62d18880000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6578616d706c652e636f6d2f6d657461646174612f7b69647d2e6a736f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x4", + "chainId": "0x2105" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x24288eb", + "logs": [ + { + "address": "0x7c842f982a02f665ed67e3c685c507d772a1d8aa", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x6688ded770d780e68d27d66c9dd172fc41317a01e7fd49eccebe3422c8288c9e", + "transactionIndex": "0x7e", + "logIndex": "0xd3", + "removed": false + } + ], + "logsBloom": "0x00000000004000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6688ded770d780e68d27d66c9dd172fc41317a01e7fd49eccebe3422c8288c9e", + "transactionIndex": "0x7e", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "gasUsed": "0x2d7844", + "effectiveGasPrice": "0x2cbdab", + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "to": null, + "contractAddress": "0x7c842f982a02f665ed67e3c685c507d772a1d8aa", + "l1BaseFeeScalar": "0x8dd", + "l1BlobBaseFee": "0x4", + "l1BlobBaseFeeScalar": "0x101c12", + "l1Fee": "0x16dd2a5bf6", + "l1GasPrice": "0x1ac6c53a", + "l1GasUsed": "0x17853" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x2485e45", + "logs": [ + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000007c842f982a02f665ed67e3c685c507d772a1d8aa" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd4", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd5", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd6", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a21995984", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd7", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd8", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000001000000400000020000000000800000000000000000000000000000800000000000000000000010000000000000000000000000000000020000000000000400000002000001000000000000000000000000000000000000020000000000000000000800000000008000000000000004000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000001000000000000000000020000100000000000000000000000100000004000100000000000020000000000000000000000000000010100000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "gasUsed": "0x5d55a", + "effectiveGasPrice": "0x2cbdab", + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "to": null, + "contractAddress": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "l1BaseFeeScalar": "0x8dd", + "l1BlobBaseFee": "0x4", + "l1BlobBaseFeeScalar": "0x101c12", + "l1Fee": "0x32d3aa399", + "l1GasPrice": "0x1ac6c53a", + "l1GasUsed": "0x3449" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1742959126, + "chain": 8453, + "commit": "cd9d7e4" +} \ No newline at end of file diff --git a/memo-nft/broadcast/DeployScript.s.sol/8453/run-latest.json b/memo-nft/broadcast/DeployScript.s.sol/8453/run-latest.json new file mode 100644 index 0000000..6f8df8f --- /dev/null +++ b/memo-nft/broadcast/DeployScript.s.sol/8453/run-latest.json @@ -0,0 +1,190 @@ +{ + "transactions": [ + { + "hash": "0x6688ded770d780e68d27d66c9dd172fc41317a01e7fd49eccebe3422c8288c9e", + "transactionType": "CREATE", + "contractName": "DwarvesMemo", + "contractAddress": "0x7c842f982a02f665ed67e3c685c507d772a1d8aa", + "function": null, + "arguments": null, + "transaction": { + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "gas": "0x3b17f7", + "value": "0x0", + "input": "0x60a06040523060805234801561001457600080fd5b5061001d610022565b6100d4565b7ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00805468010000000000000000900460ff16156100725760405163f92ee8a960e01b815260040160405180910390fd5b80546001600160401b03908116146100d15780546001600160401b0319166001600160401b0390811782556040519081527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a15b50565b6080516134d66100fd60003960008181611aa401528181611acd0152611c7d01526134d66000f3fe6080604052600436106101e25760003560e01c80637545511711610102578063c48283ff11610095578063f242432a11610064578063f242432a14610682578063f2fde38b146106a2578063f62d1888146106c2578063fa2a60b7146106e257600080fd5b8063c48283ff146105ba578063d547741f146105da578063e7c539e4146105fa578063e985e9c51461061a57600080fd5b8063a217fddf116100d1578063a217fddf1461051c578063a22cb46514610531578063ad3cb1cc14610551578063c407e27a1461059a57600080fd5b8063754551171461041c5780638da5cb5b1461045057806391d14854146104975780639a41f4df146104fc57600080fd5b806333c7ad3d1161017a5780634f1ef286116101495780634f1ef286146103ca57806352d1902d146103dd57806366a07714146103f2578063715018a61461040757600080fd5b806333c7ad3d1461034857806336568abe14610368578063410729db146103885780634e1273f41461039d57600080fd5b80631e7663bc116101b65780631e7663bc14610297578063248a9ca3146102b75780632eb2c2d6146103065780632f2ff15d1461032857600080fd5b8062fdd58e146101e757806301ffc9a71461021a5780630e89341c1461024a5780631a3e69b714610277575b600080fd5b3480156101f357600080fd5b50610207610202366004612aa9565b610702565b6040519081526020015b60405180910390f35b34801561022657600080fd5b5061023a610235366004612b01565b61074b565b6040519015158152602001610211565b34801561025657600080fd5b5061026a610265366004612b1e565b610756565b6040516102119190612b87565b34801561028357600080fd5b50610207610292366004612c71565b61082d565b3480156102a357600080fd5b506102076102b2366004612c71565b610a32565b3480156102c357600080fd5b506102076102d2366004612b1e565b60009081527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015490565b34801561031257600080fd5b50610326610321366004612d3f565b610ac0565b005b34801561033457600080fd5b50610326610343366004612df5565b610b7e565b34801561035457600080fd5b50610326610363366004612e21565b610bc8565b34801561037457600080fd5b50610326610383366004612df5565b610c01565b34801561039457600080fd5b50600454610207565b3480156103a957600080fd5b506103bd6103b8366004612e3c565b610c52565b6040516102119190612f41565b6103266103d8366004612f54565b610d38565b3480156103e957600080fd5b50610207610d53565b3480156103fe57600080fd5b5061026a610d82565b34801561041357600080fd5b50610326610e10565b34801561042857600080fd5b506102077f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a2199598481565b34801561045c57600080fd5b507f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546040516001600160a01b039091168152602001610211565b3480156104a357600080fd5b5061023a6104b2366004612df5565b60009182527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408084206001600160a01b0393909316845291905290205460ff1690565b34801561050857600080fd5b50610326610517366004612f98565b610e24565b34801561052857600080fd5b50610207600081565b34801561053d57600080fd5b5061032661054c366004612fc9565b61112f565b34801561055d57600080fd5b5061026a6040518060400160405280600581526020017f352e302e3000000000000000000000000000000000000000000000000000000081525081565b3480156105a657600080fd5b506103266105b5366004612c71565b61113a565b3480156105c657600080fd5b506103266105d5366004613005565b61118d565b3480156105e657600080fd5b506103266105f5366004612df5565b6112eb565b34801561060657600080fd5b5061026a610615366004612b1e565b61132f565b34801561062657600080fd5b5061023a610635366004613027565b6001600160a01b0391821660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45016020908152604080832093909416825291909152205460ff1690565b34801561068e57600080fd5b5061032661069d366004613051565b611463565b3480156106ae57600080fd5b506103266106bd366004612e21565b611519565b3480156106ce57600080fd5b506103266106dd366004612c71565b611570565b3480156106ee57600080fd5b506102076106fd366004612b1e565b611756565b60008181527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500602090815260408083206001600160a01b03861684529091529020545b92915050565b6000610745826117ee565b7f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c450280546060917f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500916107a7906130aa565b80601f01602080910402602001604051908101604052809291908181526020018280546107d3906130aa565b80156108205780601f106107f557610100808354040283529160200191610820565b820191906000526020600020905b81548152906001019060200180831161080357829003601f168201915b5050505050915050919050565b60007f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a2199598461085981611844565b60008351116108ef576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f41727765617665207472616e73616374696f6e2049442063616e6e6f7420626560448201527f20656d707479000000000000000000000000000000000000000000000000000060648201526084015b60405180910390fd5b6001836040516108ff91906130f7565b90815260200160405180910390205460001461099d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602560248201527f41727765617665207472616e73616374696f6e20494420616c7265616479206960448201527f6e2075736500000000000000000000000000000000000000000000000000000060648201526084016108e6565b60058054600091826109ae83613142565b9091555060008181526002602052604090209091506109cd85826131c1565b50806001856040516109df91906130f7565b908152602001604051809103902081905550807f908dd6565f4c34376a0ff039f93dd3684f6adf7e9298e189190cd2a63fe6e59c85604051610a219190612b87565b60405180910390a291505b50919050565b600080600183604051610a4591906130f7565b908152602001604051809103902054905080600003610745576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b336001600160a01b0386168114801590610b1f57506001600160a01b0380871660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4501602090815260408083209385168352929052205460ff16155b15610b69576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152871660248201526044016108e6565b610b76868686868661184e565b505050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b6268006020526040902060010154610bb881611844565b610bc283836118e8565b50505050565b6000610bd381611844565b610bfd7f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a2199598483610b7e565b5050565b6001600160a01b0381163314610c43576040517f6697b23200000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b610c4d82826119d5565b505050565b60608151835114610c9c57815183516040517f5b059991000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016108e6565b6000835167ffffffffffffffff811115610cb857610cb8612b9a565b604051908082528060200260200182016040528015610ce1578160200160208202803683370190505b50905060005b8451811015610d3057602080820286010151610d0b90602080840287010151610702565b828281518110610d1d57610d1d6132bc565b6020908102919091010152600101610ce7565b509392505050565b610d40611a99565b610d4982611b69565b610bfd8282611b71565b6000610d5d611c72565b507f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc90565b60008054610d8f906130aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610dbb906130aa565b8015610e085780601f10610ddd57610100808354040283529160200191610e08565b820191906000526020600020905b815481529060010190602001808311610deb57829003601f168201915b505050505081565b610e18611cd4565b610e226000611d48565b565b7f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a21995984610e4e81611844565b6000825111610edf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602660248201527f41727765617665207472616e73616374696f6e2049442063616e6e6f7420626560448201527f20656d707479000000000000000000000000000000000000000000000000000060648201526084016108e6565b60008381526002602052604081208054610ef8906130aa565b80601f0160208091040260200160405190810160405280929190818152602001828054610f24906130aa565b8015610f715780601f10610f4657610100808354040283529160200191610f71565b820191906000526020600020905b815481529060010190602001808311610f5457829003601f168201915b505050505090506000815111610fe3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b600183604051610ff391906130f7565b908152602001604051809103902054600014611091576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602960248201527f4e65772041727765617665207472616e73616374696f6e20494420616c72656160448201527f647920696e20757365000000000000000000000000000000000000000000000060648201526084016108e6565b60006001826040516110a391906130f7565b90815260408051602092819003830190209290925560008681526002909152206110cd84826131c1565b50836001846040516110df91906130f7565b908152602001604051809103902081905550837fd5082771b8e8c48b49a0749b21fce448072a6be7d0e819387837d8138171f1ce846040516111219190612b87565b60405180910390a250505050565b610bfd338383611dd1565b600061114581611844565b600061115183826131c1565b507fa8f1b08951572f7d2ea88146630e414c5040efde11d0212ed888789182f66c67826040516111819190612b87565b60405180910390a15050565b600082815260026020526040812080546111a6906130aa565b90501161120f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b61122a33838360405180602001604052806000815250611ec3565b600082815260066020526040812080548392906112489084906132eb565b90915550503360009081526003602052604090205460ff166112b05733600090815260036020526040812080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016600117905560048054916112aa83613142565b91905055505b604051818152829033907f96234cb3d6c373a1aaa06497a540bc166d4b0359243a088eaf95e21d7253d0be9060200160405180910390a35050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602052604090206001015461132581611844565b610bc283836119d5565b60008181526002602052604081208054606092919061134d906130aa565b80601f0160208091040260200160405190810160405280929190818152602001828054611379906130aa565b80156113c65780601f1061139b576101008083540402835291602001916113c6565b820191906000526020600020905b8154815290600101906020018083116113a957829003601f168201915b505050505090506000815111611438576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b60008160405160200161144c9291906132fe565b604051602081830303815290604052915050919050565b336001600160a01b03861681148015906114c257506001600160a01b0380871660009081527f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4501602090815260408083209385168352929052205460ff16155b1561150c576040517fe237d9220000000000000000000000000000000000000000000000000000000081526001600160a01b038083166004830152871660248201526044016108e6565b610b768686868686611f39565b611521611cd4565b6001600160a01b038116611564576040517f1e4fbdf7000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b61156d81611d48565b50565b600061157a611ffa565b805490915060ff68010000000000000000820416159067ffffffffffffffff166000811580156115a75750825b905060008267ffffffffffffffff1660011480156115c45750303b155b9050811580156115d2575080155b15611609576040517ff92ee8a900000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b84547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000166001178555831561166a5784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff16680100000000000000001785555b61167386612023565b61167c33612034565b611684612045565b61168c612045565b6116976000336118e8565b506116c27f46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a21995984336118e8565b506001600555604080516060810190915260218082526134a960208301396000906116ed90826131c1565b508315610b765784547fffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffff168555604051600181527fc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d29060200160405180910390a1505050505050565b60008181526002602052604081208054829190611772906130aa565b9050116117db576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601960248201527f546f6b656e207479706520646f6573206e6f742065786973740000000000000060448201526064016108e6565b5060009081526006602052604090205490565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f7965db0b00000000000000000000000000000000000000000000000000000000148061074557506107458261204d565b61156d8133612130565b6001600160a01b038416611891576040517f57f447ce000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6001600160a01b0385166118d4576040517f01a83514000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6118e185858585856121bd565b5050505050565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff166119cb576000848152602082815260408083206001600160a01b0387168452909152902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001660011790556119813390565b6001600160a01b0316836001600160a01b0316857f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a46001915050610745565b6000915050610745565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602081815260408084206001600160a01b038616855290915282205460ff16156119cb576000848152602082815260408083206001600160a01b038716808552925280832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016905551339287917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a46001915050610745565b306001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161480611b3257507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0316611b267f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc546001600160a01b031690565b6001600160a01b031614155b15610e22576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b61156d611cd4565b816001600160a01b03166352d1902d6040518163ffffffff1660e01b8152600401602060405180830381865afa925050508015611bcb575060408051601f3d908101601f19168201909252611bc8918101906133a2565b60015b611c0c576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b03831660048201526024016108e6565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc8114611c68576040517faa1d49a4000000000000000000000000000000000000000000000000000000008152600481018290526024016108e6565b610c4d8383612210565b306001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001614610e22576040517fe07c8dba00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b33611d067f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300546001600160a01b031690565b6001600160a01b031614610e22576040517f118cdaa70000000000000000000000000000000000000000000000000000000081523360048201526024016108e6565b7f9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c19930080547fffffffffffffffffffffffff000000000000000000000000000000000000000081166001600160a01b03848116918217845560405192169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e090600090a3505050565b7f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45006001600160a01b038316611e35576040517fced3e100000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6001600160a01b03848116600081815260018401602090815260408083209488168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001687151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a350505050565b6001600160a01b038416611f06576040517f57f447ce000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b60408051600180825260208201869052818301908152606082018590526080820190925290610b766000878484876121bd565b6001600160a01b038416611f7c576040517f57f447ce000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b6001600160a01b038516611fbf576040517f01a83514000000000000000000000000000000000000000000000000000000008152600060048201526024016108e6565b60408051600180825260208201869052818301908152606082018590526080820190925290611ff187878484876121bd565b50505050505050565b6000807ff0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00610745565b61202b612266565b61156d816122a4565b61203c612266565b61156d816122b5565b610e22612266565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167fd9b67a260000000000000000000000000000000000000000000000000000000014806120e057507fffffffff0000000000000000000000000000000000000000000000000000000082167f0e89341c00000000000000000000000000000000000000000000000000000000145b8061074557507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff00000000000000000000000000000000000000000000000000000000831614610745565b60008281527f02dd7bc7dec4dceedda775e58dd541e08a116c6c53815c0bd028192f7b626800602090815260408083206001600160a01b038516845290915290205460ff16610bfd576040517fe2517d3f0000000000000000000000000000000000000000000000000000000081526001600160a01b0382166004820152602481018390526044016108e6565b6121c9858585856122bd565b6001600160a01b038416156118e1578251339060010361220257602084810151908401516121fb838989858589612526565b5050610b76565b610b768187878787876126c6565b61221982612812565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561225e57610c4d82826128ba565b610bfd612930565b61226e612968565b610e22576040517fd7e6bcf800000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6122ac612266565b61156d81612987565b611521612266565b805182517f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4500911461232757825182516040517f5b059991000000000000000000000000000000000000000000000000000000008152600481019290925260248201526044016108e6565b3360005b8451811015612446576020818102868101820151908601909101516001600160a01b038916156123f7576000828152602086815260408083206001600160a01b038d168452909152902054818110156123d0576040517f03dee4c50000000000000000000000000000000000000000000000000000000081526001600160a01b038b1660048201526024810182905260448101839052606481018490526084016108e6565b6000838152602087815260408083206001600160a01b038e16845290915290209082900390555b6001600160a01b0388161561243c576000828152602086815260408083206001600160a01b038c168452909152812080548392906124369084906132eb565b90915550505b505060010161232b565b5083516001036124c75760208401516000906020850151909150866001600160a01b0316886001600160a01b0316846001600160a01b03167fc3d58168c5ae7397731d063d5bbf3d657854427343f4c083240f7aacaa2d0f6285856040516124b8929190918252602082015260400190565b60405180910390a45050610b76565b846001600160a01b0316866001600160a01b0316826001600160a01b03167f4a39dc06d4c0dbc64b70af90fd698a233a518aa5d07e595d983b8c0526c8f7fb87876040516125169291906133bb565b60405180910390a4505050505050565b6001600160a01b0384163b15610b76576040517ff23a6e610000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063f23a6e619061258390899089908890889088906004016133e0565b6020604051808303816000875af19250505080156125be575060408051601f3d908101601f191682019092526125bb91810190613428565b60015b612640573d8080156125ec576040519150601f19603f3d011682016040523d82523d6000602084013e6125f1565b606091505b508051600003612638576040517f57f447ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526024016108e6565b805181602001fd5b7fffffffff0000000000000000000000000000000000000000000000000000000081167ff23a6e610000000000000000000000000000000000000000000000000000000014611ff1576040517f57f447ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526024016108e6565b6001600160a01b0384163b15610b76576040517fbc197c810000000000000000000000000000000000000000000000000000000081526001600160a01b0385169063bc197c81906127239089908990889088908890600401613445565b6020604051808303816000875af192505050801561275e575060408051601f3d908101601f1916820190925261275b91810190613428565b60015b61278c573d8080156125ec576040519150601f19603f3d011682016040523d82523d6000602084013e6125f1565b7fffffffff0000000000000000000000000000000000000000000000000000000081167fbc197c810000000000000000000000000000000000000000000000000000000014611ff1576040517f57f447ce0000000000000000000000000000000000000000000000000000000081526001600160a01b03861660048201526024016108e6565b806001600160a01b03163b600003612861576040517f4c9c8ce30000000000000000000000000000000000000000000000000000000081526001600160a01b03821660048201526024016108e6565b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80547fffffffffffffffffffffffff0000000000000000000000000000000000000000166001600160a01b0392909216919091179055565b6060600080846001600160a01b0316846040516128d791906130f7565b600060405180830381855af49150503d8060008114612912576040519150601f19603f3d011682016040523d82523d6000602084013e612917565b606091505b50915091506129278583836129d3565b95945050505050565b3415610e22576040517fb398979f00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b6000612972611ffa565b5468010000000000000000900460ff16919050565b7f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c45007f88be536d5240c274a3b1d3a1be54482fd9caa294f08c62a7cde569f49a3c4502610c4d83826131c1565b6060826129e8576129e382612a4b565b612a44565b81511580156129ff57506001600160a01b0384163b155b15612a41576040517f9996b3150000000000000000000000000000000000000000000000000000000081526001600160a01b03851660048201526024016108e6565b50805b9392505050565b805115612a5b5780518082602001fd5b6040517fd6bda27500000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b80356001600160a01b0381168114612aa457600080fd5b919050565b60008060408385031215612abc57600080fd5b612ac583612a8d565b946020939093013593505050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461156d57600080fd5b600060208284031215612b1357600080fd5b8135612a4481612ad3565b600060208284031215612b3057600080fd5b5035919050565b60005b83811015612b52578181015183820152602001612b3a565b50506000910152565b60008151808452612b73816020860160208601612b37565b601f01601f19169290920160200192915050565b602081526000612a446020830184612b5b565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b604051601f8201601f1916810167ffffffffffffffff81118282101715612bf257612bf2612b9a565b604052919050565b600082601f830112612c0b57600080fd5b81356020830160008067ffffffffffffffff841115612c2c57612c2c612b9a565b50601f8301601f1916602001612c4181612bc9565b915050828152858383011115612c5657600080fd5b82826020830137600092810160200192909252509392505050565b600060208284031215612c8357600080fd5b813567ffffffffffffffff811115612c9a57600080fd5b612ca684828501612bfa565b949350505050565b600067ffffffffffffffff821115612cc857612cc8612b9a565b5060051b60200190565b600082601f830112612ce357600080fd5b8135612cf6612cf182612cae565b612bc9565b8082825260208201915060208360051b860101925085831115612d1857600080fd5b602085015b83811015612d35578035835260209283019201612d1d565b5095945050505050565b600080600080600060a08688031215612d5757600080fd5b612d6086612a8d565b9450612d6e60208701612a8d565b9350604086013567ffffffffffffffff811115612d8a57600080fd5b612d9688828901612cd2565b935050606086013567ffffffffffffffff811115612db357600080fd5b612dbf88828901612cd2565b925050608086013567ffffffffffffffff811115612ddc57600080fd5b612de888828901612bfa565b9150509295509295909350565b60008060408385031215612e0857600080fd5b82359150612e1860208401612a8d565b90509250929050565b600060208284031215612e3357600080fd5b612a4482612a8d565b60008060408385031215612e4f57600080fd5b823567ffffffffffffffff811115612e6657600080fd5b8301601f81018513612e7757600080fd5b8035612e85612cf182612cae565b8082825260208201915060208360051b850101925087831115612ea757600080fd5b6020840193505b82841015612ed057612ebf84612a8d565b825260209384019390910190612eae565b9450505050602083013567ffffffffffffffff811115612eef57600080fd5b612efb85828601612cd2565b9150509250929050565b600081518084526020840193506020830160005b82811015612f37578151865260209586019590910190600101612f19565b5093949350505050565b602081526000612a446020830184612f05565b60008060408385031215612f6757600080fd5b612f7083612a8d565b9150602083013567ffffffffffffffff811115612f8c57600080fd5b612efb85828601612bfa565b60008060408385031215612fab57600080fd5b82359150602083013567ffffffffffffffff811115612f8c57600080fd5b60008060408385031215612fdc57600080fd5b612fe583612a8d565b915060208301358015158114612ffa57600080fd5b809150509250929050565b6000806040838503121561301857600080fd5b50508035926020909101359150565b6000806040838503121561303a57600080fd5b61304383612a8d565b9150612e1860208401612a8d565b600080600080600060a0868803121561306957600080fd5b61307286612a8d565b945061308060208701612a8d565b93506040860135925060608601359150608086013567ffffffffffffffff811115612ddc57600080fd5b600181811c908216806130be57607f821691505b602082108103610a2c577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60008251613109818460208701612b37565b9190910192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361317357613173613113565b5060010190565b601f821115610c4d57806000526020600020601f840160051c810160208510156131a15750805b601f840160051c820191505b818110156118e157600081556001016131ad565b815167ffffffffffffffff8111156131db576131db612b9a565b6131ef816131e984546130aa565b8461317a565b6020601f821160018114613241576000831561320b5750848201515b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600385901b1c1916600184901b1784556118e1565b600084815260208120601f198516915b828110156132715787850151825560209485019460019092019101613251565b50848210156132ad57868401517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600387901b60f8161c191681555b50505050600190811b01905550565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8082018082111561074557610745613113565b600080845461330c816130aa565b600182168015613323576001811461335657613386565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083168652811515820286019350613386565b87600052602060002060005b8381101561337e57815488820152600190910190602001613362565b505081860193505b5050508351613399818360208801612b37565b01949350505050565b6000602082840312156133b457600080fd5b5051919050565b6040815260006133ce6040830185612f05565b82810360208401526129278185612f05565b6001600160a01b03861681526001600160a01b038516602082015283604082015282606082015260a06080820152600061341d60a0830184612b5b565b979650505050505050565b60006020828403121561343a57600080fd5b8151612a4481612ad3565b6001600160a01b03861681526001600160a01b038516602082015260a06040820152600061347660a0830186612f05565b82810360608401526134888186612f05565b9050828103608084015261349c8185612b5b565b9897505050505050505056fe68747470733a2f2f617277656176652e646576656c6f70657264616f2e636f6d2fa164736f6c634300081d000a", + "nonce": "0x3", + "chainId": "0x2105" + }, + "additionalContracts": [], + "isFixedGasLimit": false + }, + { + "hash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionType": "CREATE", + "contractName": "ERC1967Proxy", + "contractAddress": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "function": null, + "arguments": [ + "0x7c842f982A02F665ED67E3C685c507d772a1d8aa", + "0xf62d18880000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6578616d706c652e636f6d2f6d657461646174612f7b69647d2e6a736f6e0000000000000000000000000000000000000000000000000000" + ], + "transaction": { + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "gas": "0x794f3", + "value": "0x0", + "input": "0x60806040526040516103f43803806103f483398101604081905261002291610268565b61002c8282610033565b5050610358565b61003c82610092565b6040516001600160a01b038316907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a280511561008657610081828261010e565b505050565b61008e610185565b5050565b806001600160a01b03163b6000036100cd57604051634c9c8ce360e01b81526001600160a01b03821660048201526024015b60405180910390fd5b7f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b0319166001600160a01b0392909216919091179055565b6060600080846001600160a01b03168460405161012b919061033c565b600060405180830381855af49150503d8060008114610166576040519150601f19603f3d011682016040523d82523d6000602084013e61016b565b606091505b50909250905061017c8583836101a6565b95945050505050565b34156101a45760405163b398979f60e01b815260040160405180910390fd5b565b6060826101bb576101b682610205565b6101fe565b81511580156101d257506001600160a01b0384163b155b156101fb57604051639996b31560e01b81526001600160a01b03851660048201526024016100c4565b50805b9392505050565b8051156102155780518082602001fd5b60405163d6bda27560e01b815260040160405180910390fd5b634e487b7160e01b600052604160045260246000fd5b60005b8381101561025f578181015183820152602001610247565b50506000910152565b6000806040838503121561027b57600080fd5b82516001600160a01b038116811461029257600080fd5b60208401519092506001600160401b038111156102ae57600080fd5b8301601f810185136102bf57600080fd5b80516001600160401b038111156102d8576102d861022e565b604051601f8201601f19908116603f011681016001600160401b03811182821017156103065761030661022e565b60405281815282820160200187101561031e57600080fd5b61032f826020830160208601610244565b8093505050509250929050565b6000825161034e818460208701610244565b9190910192915050565b608e806103666000396000f3fe6080604052600a600c565b005b60186014601a565b605e565b565b600060597f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc5473ffffffffffffffffffffffffffffffffffffffff1690565b905090565b3660008037600080366000845af43d6000803e808015607c573d6000f35b3d6000fdfea164736f6c634300081d000a0000000000000000000000007c842f982a02f665ed67e3c685c507d772a1d8aa00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000084f62d18880000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002668747470733a2f2f6578616d706c652e636f6d2f6d657461646174612f7b69647d2e6a736f6e000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "nonce": "0x4", + "chainId": "0x2105" + }, + "additionalContracts": [], + "isFixedGasLimit": false + } + ], + "receipts": [ + { + "status": "0x1", + "cumulativeGasUsed": "0x24288eb", + "logs": [ + { + "address": "0x7c842f982a02f665ed67e3c685c507d772a1d8aa", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x000000000000000000000000000000000000000000000000ffffffffffffffff", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x6688ded770d780e68d27d66c9dd172fc41317a01e7fd49eccebe3422c8288c9e", + "transactionIndex": "0x7e", + "logIndex": "0xd3", + "removed": false + } + ], + "logsBloom": "0x00000000004000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x6688ded770d780e68d27d66c9dd172fc41317a01e7fd49eccebe3422c8288c9e", + "transactionIndex": "0x7e", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "gasUsed": "0x2d7844", + "effectiveGasPrice": "0x2cbdab", + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "to": null, + "contractAddress": "0x7c842f982a02f665ed67e3c685c507d772a1d8aa", + "l1BaseFeeScalar": "0x8dd", + "l1BlobBaseFee": "0x4", + "l1BlobBaseFeeScalar": "0x101c12", + "l1Fee": "0x16dd2a5bf6", + "l1GasPrice": "0x1ac6c53a", + "l1GasUsed": "0x17853" + }, + { + "status": "0x1", + "cumulativeGasUsed": "0x2485e45", + "logs": [ + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0xbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b", + "0x0000000000000000000000007c842f982a02f665ed67e3c685c507d772a1d8aa" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd4", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd5", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x0000000000000000000000000000000000000000000000000000000000000000", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd6", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0x2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d", + "0x46bc17a0fe87d21d3032006471bcf37ce466e2647ce3c29105bf282a21995984", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698", + "0x000000000000000000000000d7d9b9e4dd263f67c777decb29456386c0cec698" + ], + "data": "0x", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd7", + "removed": false + }, + { + "address": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "topics": [ + "0xc7f505b2f371ae2175ee4913f4499e1f2633a7b5936321eed1cdaeb6115181d2" + ], + "data": "0x0000000000000000000000000000000000000000000000000000000000000001", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "blockTimestamp": "0x67e371fd", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "logIndex": "0xd8", + "removed": false + } + ], + "logsBloom": "0x00000004000000000000000001000000400000020000000000800000000000000000000000000000800000000000000000000010000000000000000000000000000000020000000000000400000002000001000000000000000000000000000000000000020000000000000000000800000000008000000000000004000000400000000000000000000800000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000001000000000000000000020000100000000000000000000000100000004000100000000000020000000000000000000000000000010100000000000000000000000000000000000", + "type": "0x2", + "transactionHash": "0x7d0b789194e71b4897b8aaf25e2caa5544d2e0a94456c70ed1c01f403d153a64", + "transactionIndex": "0x7f", + "blockHash": "0x6d77aec29f2e10bcb63393889886e1d31b6206f7f1f5836cb06992d2f9c9e476", + "blockNumber": "0x1ac8a8d", + "gasUsed": "0x5d55a", + "effectiveGasPrice": "0x2cbdab", + "from": "0xd7d9b9e4dd263f67c777decb29456386c0cec698", + "to": null, + "contractAddress": "0x07f3ed54e0b2d07cc522c4fc12eba80e6d3a8deb", + "l1BaseFeeScalar": "0x8dd", + "l1BlobBaseFee": "0x4", + "l1BlobBaseFeeScalar": "0x101c12", + "l1Fee": "0x32d3aa399", + "l1GasPrice": "0x1ac6c53a", + "l1GasUsed": "0x3449" + } + ], + "libraries": [], + "pending": [], + "returns": {}, + "timestamp": 1742959126, + "chain": 8453, + "commit": "cd9d7e4" +} \ No newline at end of file diff --git a/memo-nft/bun.lockb b/memo-nft/bun.lockb new file mode 100755 index 0000000..e0513f3 Binary files /dev/null and b/memo-nft/bun.lockb differ diff --git a/memo-nft/foundry.toml b/memo-nft/foundry.toml new file mode 100644 index 0000000..737ce95 --- /dev/null +++ b/memo-nft/foundry.toml @@ -0,0 +1,37 @@ +# Full reference https://github.com/foundry-rs/foundry/tree/master/crates/config + +[profile.default] + auto_detect_solc = false + block_timestamp = 1_738_368_000 # Feb 1, 2025 at 00:00 GMT + bytecode_hash = "none" + fuzz = { runs = 1_000 } + gas_reports = ["*"] + optimizer = true + optimizer_runs = 10_000 + out = "out" + script = "script" + solc = "0.8.29" + src = "src" + test = "tests" + +[profile.ci] + fuzz = { runs = 10_000 } + verbosity = 4 + +[rpc_endpoints] + base = "${BASE_RPC}" + base_sepolia = "${BASE_SEPOLIA_RPC}" + +[etherscan] + base = { key = "${BASESCAN_API_KEY}" } + base_sepolia = { key = "${BASESCAN_API_KEY}" } + +[fmt] + bracket_spacing = true + int_types = "long" + line_length = 120 + multiline_func_header = "all" + number_underscore = "thousands" + quote_style = "double" + tab_width = 4 + wrap_comments = true diff --git a/memo-nft/package.json b/memo-nft/package.json new file mode 100644 index 0000000..bdac7bc --- /dev/null +++ b/memo-nft/package.json @@ -0,0 +1,31 @@ +{ + "name": "@df/memo-nft", + "description": "Memo NFT", + "version": "1.0.0", + "dependencies": { + "@openzeppelin/contracts": "^5.2.0", + "@openzeppelin/foundry-upgrades": "OpenZeppelin/openzeppelin-foundry-upgrades", + "openzeppelin-solidity": "OpenZeppelin/openzeppelin-contracts-upgradeable" + }, + "devDependencies": { + "forge-std": "github:foundry-rs/forge-std#v1.8.1", + "prettier": "^3.0.0", + "solhint": "^3.6.2" + }, + "private": true, + "scripts": { + "clean": "rm -rf cache out", + "build": "forge build", + "lint": "bun run lint:sol && bun run prettier:check", + "lint:sol": "forge fmt --check && bun solhint \"{script,src,tests}/**/*.sol\"", + "prettier:check": "prettier --check \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"", + "prettier:write": "prettier --write \"**/*.{json,md,yml}\" --ignore-path \".prettierignore\"", + "test": "forge test -vvv", + "test:coverage": "forge coverage", + "test:coverage:report": "forge coverage --report lcov && genhtml lcov.info --branch-coverage --output-dir coverage", + "deploy:testnet": "forge script script/DeployScript.s.sol:DeployScript --rpc-url base_sepolia --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv", + "upgrade:testnet": "forge script script/UpgradeScript.s.sol:UpgradeScript --rpc-url base_sepolia --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv", + "deploy:mainnet": "forge script script/DeployScript.s.sol:DeployScript --rpc-url base --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv", + "upgrade:mainnet": "forge script script/UpgradeScript.s.sol:UpgradeScript --rpc-url base --private-key $(grep WALLET_PRIVATE_KEY .env | cut -d '=' -f2) --broadcast --verify -vvvv" + } +} diff --git a/memo-nft/remappings.txt b/memo-nft/remappings.txt new file mode 100644 index 0000000..32e88dd --- /dev/null +++ b/memo-nft/remappings.txt @@ -0,0 +1,3 @@ +@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/ +forge-std/=node_modules/forge-std/ +@openzeppelin/contracts-upgradeable/=node_modules/openzeppelin-solidity/contracts \ No newline at end of file diff --git a/memo-nft/script/DeployScript.s.sol b/memo-nft/script/DeployScript.s.sol new file mode 100644 index 0000000..b813dca --- /dev/null +++ b/memo-nft/script/DeployScript.s.sol @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.29; + +import "forge-std/src/Script.sol"; +import "../src/DwarvesMemo.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +// Notes: +// Replace `INITIAL_URI` with the initial URI for the NFT metadata +contract DeployScript is Script { + function run() external { + vm.startBroadcast(); + + string memory INITIAL_URI = "https://example.com/metadata/{id}.json"; + + // Deploy implementation contract + DwarvesMemo implementation = new DwarvesMemo(); + + // Deploy proxy contract + new ERC1967Proxy( + address(implementation), + abi.encodeWithSelector(DwarvesMemo.initialize.selector, INITIAL_URI) + ); + + vm.stopBroadcast(); + } +} \ No newline at end of file diff --git a/memo-nft/script/UpgradeScript.s.sol b/memo-nft/script/UpgradeScript.s.sol new file mode 100644 index 0000000..9d9996d --- /dev/null +++ b/memo-nft/script/UpgradeScript.s.sol @@ -0,0 +1,29 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.29; + +import "forge-std/src/Script.sol"; +import "../src/DwarvesMemo.sol"; + +// Notes: +// 1. Replace `PROXY_ADDRESS` with the address of the proxy contract you want to upgrade before running the script +// 2. Replace `INITIAL_URI` with the initial URI for the NFT metadata +contract UpgradeScript is Script { + function run() external { + vm.startBroadcast(); + + // TODO: Replace with the address of the latest proxy contract you want to upgrade + address PROXY_ADDRESS = 0x07f3ed54e0b2D07cC522c4FC12EbA80E6D3A8DeB; + + // Deploy the new implementation contract + DwarvesMemo newImplementation = new DwarvesMemo(); + + DwarvesMemo proxy = DwarvesMemo(address(PROXY_ADDRESS)); + bytes memory data = ""; + proxy.upgradeToAndCall( + address(newImplementation), + data + ); + + vm.stopBroadcast(); + } +} diff --git a/memo-nft/src/DwarvesMemo.sol b/memo-nft/src/DwarvesMemo.sol new file mode 100644 index 0000000..a2bf845 --- /dev/null +++ b/memo-nft/src/DwarvesMemo.sol @@ -0,0 +1,209 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.29; + +import "@openzeppelin/contracts-upgradeable/token/ERC1155/ERC1155Upgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; +import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol"; +import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol"; + +contract DwarvesMemo is + Initializable, + ERC1155Upgradeable, + OwnableUpgradeable, + UUPSUpgradeable, + AccessControlUpgradeable +{ + /*////////////////////////////////////////////////////////////// + EVENTS + //////////////////////////////////////////////////////////////*/ + + event TokenTypeCreated(uint256 indexed tokenId, string arweaveTxId); + event TokenTypeUpdated(uint256 indexed tokenId, string newArweaveTxId); + event TokenMinted(address indexed to, uint256 indexed tokenId, uint256 amount); + event ArweaveGatewayUrlUpdated(string newArweaveGatewayUrl); + + /*////////////////////////////////////////////////////////////// + STATE VARIABLES + //////////////////////////////////////////////////////////////*/ + + string public _arweaveGatewayUrl; // The Arweave gateway URL + mapping(string => uint256) private _arweaveTxIdToTokenId; // Maps Arweave transaction ID to tokenId + mapping(uint256 => string) private _tokenIdToArweaveTxId; // Maps tokenId to Arweave transaction ID + mapping(address => bool) private _uniqueMinters; // Tracks unique minters + uint256 private _uniqueMinterCount; // Counts unique minters + uint256 private _nextTokenId; // Auto-incrementing token ID counter + mapping(uint256 => uint256) private _tokenMintCount; // Tracks total mints per tokenId + + /*////////////////////////////////////////////////////////////// + CONSTANTS + //////////////////////////////////////////////////////////////*/ + bytes32 public constant NFT_CREATOR_ROLE = keccak256("NFT_CREATOR_ROLE"); + + /*////////////////////////////////////////////////////////////// + CONSTRUCTOR + //////////////////////////////////////////////////////////////*/ + + /// @custom:oz-upgrades-unsafe-allow constructor + constructor() { + _disableInitializers(); // Disables initializer on implementation contract + } + + /** + * @dev Initializes the contract (replaces constructor for upgradeable contracts). + * @param uri The base URI for the ERC1155 token. + */ + function initialize(string memory uri) public initializer { + __ERC1155_init(uri); + __Ownable_init(msg.sender); + __UUPSUpgradeable_init(); + __AccessControl_init(); + + // Grant the contract deployer the default admin role and minter role + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); + _grantRole(NFT_CREATOR_ROLE, msg.sender); + + // Initialize state variables + _nextTokenId = 1; + _arweaveGatewayUrl = "https://arweave.developerdao.com/"; + } + + /*////////////////////////////////////////////////////////////// + ADMIN FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + function grantCreateNftRole(address account) external onlyRole(DEFAULT_ADMIN_ROLE) { + grantRole(NFT_CREATOR_ROLE, account); + } + + function setArweaveGatewayUrl(string memory newArweaveGatewayUrl) external onlyRole(DEFAULT_ADMIN_ROLE) { + _arweaveGatewayUrl = newArweaveGatewayUrl; + emit ArweaveGatewayUrlUpdated(newArweaveGatewayUrl); + } + + /** + * @dev Creates a new NFT type based on an Arweave transaction ID. + * @param arweaveTxId The Arweave transaction ID for the NFT metadata. + * @return The automatically assigned token ID. + */ + function createTokenType(string memory arweaveTxId) external onlyRole(NFT_CREATOR_ROLE) returns (uint256) { + require(bytes(arweaveTxId).length > 0, "Arweave transaction ID cannot be empty"); + require(_arweaveTxIdToTokenId[arweaveTxId] == 0, "Arweave transaction ID already in use"); + + uint256 tokenId = _nextTokenId++; + _tokenIdToArweaveTxId[tokenId] = arweaveTxId; + _arweaveTxIdToTokenId[arweaveTxId] = tokenId; + + emit TokenTypeCreated(tokenId, arweaveTxId); + return tokenId; + } + + /** + * @dev Updates the Arweave transaction ID for an existing token ID. + * @param tokenId The token ID to update. + * @param newArweaveTxId The new Arweave transaction ID. + */ + function updateTokenType(uint256 tokenId, string memory newArweaveTxId) external onlyRole(NFT_CREATOR_ROLE) { + require(bytes(newArweaveTxId).length > 0, "Arweave transaction ID cannot be empty"); + string memory oldArweaveTxId = _tokenIdToArweaveTxId[tokenId]; + require(bytes(oldArweaveTxId).length > 0, "Token type does not exist"); + require(_arweaveTxIdToTokenId[newArweaveTxId] == 0, "New Arweave transaction ID already in use"); + + // Update mappings + _arweaveTxIdToTokenId[oldArweaveTxId] = 0; + _tokenIdToArweaveTxId[tokenId] = newArweaveTxId; + _arweaveTxIdToTokenId[newArweaveTxId] = tokenId; + + emit TokenTypeUpdated(tokenId, newArweaveTxId); + } + + /*////////////////////////////////////////////////////////////// + PUBLIC FUNCTIONS + //////////////////////////////////////////////////////////////*/ + + /** + * @dev Returns the Arweave gateway URL for the token's metadata. + * @param tokenId The token ID. + * @return The Arweave gateway URL. + */ + function readNFT(uint256 tokenId) external view returns (string memory) { + string memory arweaveTxId = _tokenIdToArweaveTxId[tokenId]; + require(bytes(arweaveTxId).length > 0, "Token type does not exist"); + return string(abi.encodePacked(_arweaveGatewayUrl, arweaveTxId)); + } + + /** + * @dev Returns the token ID for a given Arweave transaction ID. + * @param arweaveTxId The Arweave transaction ID. + * @return The corresponding token ID. + */ + function getTokenId(string memory arweaveTxId) external view returns (uint256) { + uint256 tokenId = _arweaveTxIdToTokenId[arweaveTxId]; + require(tokenId != 0, "Token type does not exist"); + return tokenId; + } + + /** + * @dev Mints tokens of an existing NFT type. + * @param tokenId The token ID of the NFT type to mint. + * @param amount The number of tokens to mint. + */ + function mintNFT(uint256 tokenId, uint256 amount) external { + require( + bytes(_tokenIdToArweaveTxId[tokenId]).length > 0, + "Token type does not exist" + ); + _mint(msg.sender, tokenId, amount, ""); + + // Update mint count for this tokenId + _tokenMintCount[tokenId] += amount; + + // Track unique minters + if (!_uniqueMinters[msg.sender]) { + _uniqueMinters[msg.sender] = true; + _uniqueMinterCount++; + } + + emit TokenMinted(msg.sender, tokenId, amount); + } + + /** + * @dev Returns the total number of tokens minted for a specific tokenId. + * @param tokenId The token ID to query. + * @return The total number of tokens minted for the given tokenId. + */ + function getMintCountByTokenId(uint256 tokenId) external view returns (uint256) { + require(bytes(_tokenIdToArweaveTxId[tokenId]).length > 0, "Token type does not exist"); + return _tokenMintCount[tokenId]; + } + + /** + * @dev Returns the total number of unique addresses that have minted at least one NFT. + * @return The count of unique minters. + */ + function getUniqueMinterCount() external view returns (uint256) { + return _uniqueMinterCount; + } + + /*////////////////////////////////////////////////////////////// + UUPS UPGRADE AUTHORIZATION + //////////////////////////////////////////////////////////////*/ + + /** + * @dev Override to restrict upgrades to the owner. + */ + function _authorizeUpgrade(address newImplementation) internal override onlyOwner {} + + /** + * @dev See {IERC165-supportsInterface}. + */ + function supportsInterface(bytes4 interfaceId) + public + view + virtual + override(ERC1155Upgradeable, AccessControlUpgradeable) + returns (bool) + { + return super.supportsInterface(interfaceId); + } +} diff --git a/memo-nft/tests/DwarvesMemo.t.sol b/memo-nft/tests/DwarvesMemo.t.sol new file mode 100644 index 0000000..23ff13f --- /dev/null +++ b/memo-nft/tests/DwarvesMemo.t.sol @@ -0,0 +1,185 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.29; + +import "forge-std/src/Test.sol"; +import "../src/DwarvesMemo.sol"; +import "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol"; + +contract DwarvesMemoTest is Test { + DwarvesMemo public implementation; + DwarvesMemo public proxy; + address owner = address(0x123); + address user = address(0x456); + + function setUp() public { + // Deploy implementation contract + implementation = new DwarvesMemo(); + + // Deploy proxy contract and initialize it + vm.prank(owner); + proxy = DwarvesMemo( + address( + new ERC1967Proxy( + address(implementation), + abi.encodeWithSelector(DwarvesMemo.initialize.selector, "https://example.com/metadata/{id}.json") + ) + ) + ); + } + + // Test Admin Functions + + function test_CreateTokenType() public { + vm.prank(owner); + uint256 tokenId = proxy.createTokenType("arweave-tx-id-123"); + assertEq(tokenId, 1, "First token ID should be 1"); + } + + function test_CreateTokenType_RevertIfNotOwner() public { + vm.prank(user); + vm.expectRevert(); + proxy.createTokenType("arweave-tx-id-123"); + } + + function test_UpdateTokenType() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(owner); + proxy.updateTokenType(tokenId, "new-arweave-tx-id"); + + string memory arweaveUrl = proxy.readNFT(tokenId); + assertEq(arweaveUrl, "https://arweave.developerdao.com/new-arweave-tx-id", "Arweave URL should be updated"); + } + + function test_UpdateTokenType_RevertIfNotOwner() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(user); + vm.expectRevert(); + proxy.updateTokenType(tokenId, "new-arweave-tx-id"); + } + + function test_UpdateTokenType_RevertIfTokenDoesNotExist() public { + vm.prank(owner); + vm.expectRevert(); + proxy.updateTokenType(1, "new-arweave-tx-id"); + } + + // Test Public Functions + + function test_ReadNFT() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + string memory arweaveUrl = proxy.readNFT(tokenId); + assertEq(arweaveUrl, "https://arweave.developerdao.com/arweave-tx-id-123", "Arweave URL should match"); + } + + function test_ReadNFT_RevertIfTokenDoesNotExist() public { + vm.expectRevert("Token type does not exist"); + proxy.readNFT(1); + } + + function test_GetTokenId() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + assertEq(tokenId, 1, "Token ID should be 1"); + } + + function test_MintNFT() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(user); + proxy.mintNFT(tokenId, 1); + + assertEq(proxy.balanceOf(user, tokenId), 1, "User should have 1 token"); + assertEq(proxy.getUniqueMinterCount(), 1, "Unique minters count should be 1"); + } + + function test_MintNFT_RevertIfTokenDoesNotExist() public { + vm.prank(user); + vm.expectRevert("Token type does not exist"); + proxy.mintNFT(1, 10); + } + + function test_GetUniqueMinterCount() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(user); + proxy.mintNFT(tokenId, 1); + + vm.prank(address(0x789)); + proxy.mintNFT(tokenId, 1); + + assertEq(proxy.getUniqueMinterCount(), 2, "Unique minters count should be 2"); + } + + function test_SetArweaveGatewayUrl() public { + vm.prank(owner); + proxy.setArweaveGatewayUrl("https://new-gateway.com/"); + + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + string memory arweaveUrl = proxy.readNFT(tokenId); + assertEq(arweaveUrl, "https://new-gateway.com/arweave-tx-id-123", "Arweave URL should use new gateway"); + } + + // Test minting multiple times from the same address + function test_MintNFT_MultipleMints() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(user); + proxy.mintNFT(tokenId, 5); + + vm.prank(user); + proxy.mintNFT(tokenId, 10); + + assertEq(proxy.balanceOf(user, tokenId), 15, "User should have 15 tokens total"); + assertEq(proxy.getUniqueMinterCount(), 1, "Unique minters count should still be 1"); + } + + // Test minting with zero amount + function test_MintNFT_ZeroAmount() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(user); + proxy.mintNFT(tokenId, 0); + + assertEq(proxy.balanceOf(user, tokenId), 0, "User should have 0 tokens"); + assertEq(proxy.getUniqueMinterCount(), 1, "Unique minters count should be 1"); + } + + // Test updating token type to empty Arweave transaction ID + function test_UpdateTokenType_ToEmptyArweaveTxId() public { + vm.prank(owner); + proxy.createTokenType("arweave-tx-id-123"); + + uint256 tokenId = proxy.getTokenId("arweave-tx-id-123"); + + vm.prank(owner); + vm.expectRevert("Arweave transaction ID cannot be empty"); + proxy.updateTokenType(tokenId, ""); + } +} \ No newline at end of file