@zoralabs/coins 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +7 -0
- package/.turbo/turbo-build.log +49 -37
- package/CHANGELOG.md +6 -0
- package/README.md +29 -0
- package/abis/CoinTest.json +28 -0
- package/abis/Create2.json +28 -0
- package/abis/DeployScript.json +9 -0
- package/abis/DeterministicDeployerAndCaller.json +315 -0
- package/abis/DeterministicUUPSProxyDeployer.json +167 -0
- package/abis/FactoryTest.json +20 -0
- package/abis/GenerateDeterministicParams.json +9 -0
- package/abis/IERC165.json +1 -1
- package/abis/IERC20.json +42 -39
- package/abis/IImmutableCreate2Factory.json +93 -0
- package/abis/ISafe.json +15 -0
- package/abis/ISymbol.json +15 -0
- package/abis/ImmutableCreate2FactoryUtils.json +15 -0
- package/abis/LibString.json +7 -0
- package/abis/ProxyShim.json +112 -0
- package/abis/UUPSUpgradeable.json +15 -14
- package/abis/ZoraFactory.json +0 -5
- package/addresses/8453.json +5 -8
- package/addresses/84532.json +5 -8
- package/deterministicConfig/deployerAndCaller.json +5 -0
- package/deterministicConfig/zoraFactory.json +8 -0
- package/foundry.toml +14 -0
- package/package.json +3 -2
- package/remappings.txt +2 -1
- package/script/CoinsDeployerBase.sol +98 -0
- package/script/Deploy.s.sol +14 -5
- package/script/GenerateDeterministicParams.s.sol +43 -0
- package/src/Coin.sol +1 -1
- package/src/proxy/ZoraFactory.sol +7 -1
- package/src/utils/CoinConstants.sol +2 -2
- package/src/version/ContractVersionBase.sol +1 -1
- package/test/Coin.t.sol +119 -6
- package/test/Factory.t.sol +34 -11
- package/test/utils/BaseTest.sol +4 -4
- package/abis/Deploy.json +0 -29
- package/addresses/1.json +0 -4
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
{
|
|
2
|
+
"creationCode": "0x610180604052346101a1576040516100186040826101a5565b601e815260208101907f44657465726d696e69737469634465706c6f796572416e6443616c6c657200008252604051916100536040846101a5565b600183526020830191603160f81b835261006c816101c8565b610120526100798461035e565b61014052519020918260e05251902080610100524660a0526040519060208201927f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f8452604083015260608201524660808201523060a082015260a081526100e260c0826101a5565b5190206080523060c05260405161046b80820191906001600160401b0383118284101761018d575f928291610fbd8339039082f580156101825761016052604051610b269081610497823960805181610980015260a05181610a3d015260c0518161094a015260e051816109cf015261010051816109f50152610120518161025e0152610140518161028701526101605181818161035301526104bf0152f35b6040513d5f823e3d90fd5b634e487b7160e01b5f52604160045260245ffd5b5f80fd5b601f909101601f19168101906001600160401b0382119082101761018d57604052565b908151602081105f14610242575090601f8151116102025760208151910151602082106101f3571790565b5f198260200360031b1b161790565b604460209160405192839163305a27a960e01b83528160048401528051918291826024860152018484015e5f828201840152601f01601f19168101030190fd5b6001600160401b03811161018d575f54600181811c91168015610354575b602082101461034057601f811161030e575b50602092601f82116001146102af57928192935f926102a4575b50508160011b915f199060031b1c1916175f5560ff90565b015190505f8061028c565b601f198216935f8052805f20915f5b8681106102f657508360019596106102de575b505050811b015f5560ff90565b01515f1960f88460031b161c191690555f80806102d1565b919260206001819286850151815501940192016102be565b5f8052601f60205f20910160051c810190601f830160051c015b8181106103355750610272565b5f8155600101610328565b634e487b7160e01b5f52602260045260245ffd5b90607f1690610260565b908151602081105f14610389575090601f8151116102025760208151910151602082106101f3571790565b6001600160401b03811161018d57600154600181811c9116801561048c575b602082101461034057601f8111610459575b50602092601f82116001146103f857928192935f926103ed575b50508160011b915f199060031b1c19161760015560ff90565b015190505f806103d4565b601f1982169360015f52805f20915f5b8681106104415750836001959610610429575b505050811b0160015560ff90565b01515f1960f88460031b161c191690555f808061041b565b91926020600181928685015181550194019201610408565b60015f52601f60205f20910160051c810190601f830160051c015b81811061048157506103ba565b5f8155600101610474565b90607f16906103a856fe60806040526004361015610011575f80fd5b5f3560e01c806325746d39146103825780637db68ec41461033e57806384b0196e1461024657806386881034146101cf578063e3867c2914610105578063eae49c87146100d25763f9baed1814610066575f80fd5b346100ce5760603660031901126100ce5760243567ffffffffffffffff81116100ce57610097903690600401610449565b60443567ffffffffffffffff81116100ce576020916100bd6100c6923690600401610449565b906004356104f6565b604051908152f35b5f80fd5b346100ce575f3660031901126100ce576101016100ed6104b3565b60405191829160208352602083019061048f565b0390f35b60a03660031901126100ce5760043567ffffffffffffffff81116100ce57610131903690600401610449565b6024359060443567ffffffffffffffff81116100ce57610155903690600401610449565b60643567ffffffffffffffff81116100ce57610175903690600401610449565b608435916001600160a01b03831683036100ce57846101b8816101b36101aa6101bd986101a5888860209d6104f6565b610899565b909291926108d3565b61057a565b6105a8565b6040516001600160a01b039091168152f35b346100ce5760203660031901126100ce5760043567ffffffffffffffff81116100ce5760206100ed610208610101933690600401610449565b82806102126104b3565b6040519584879551918291018487015e8401908282015f8152815193849201905e01015f815203601f1981018352826103f7565b346100ce575f3660031901126100ce576102e26102827f00000000000000000000000000000000000000000000000000000000000000006106a6565b6102ab7f00000000000000000000000000000000000000000000000000000000000000006107c9565b60206102f0604051926102be83856103f7565b5f84525f368137604051958695600f60f81b875260e08588015260e087019061048f565b90858203604087015261048f565b4660608501523060808501525f60a085015283810360c08501528180845192838152019301915f5b82811061032757505050500390f35b835185528695509381019392810192600101610318565b346100ce575f3660031901126100ce576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b60803660031901126100ce5760043560243567ffffffffffffffff81116100ce576103b1903690600401610449565b9060443567ffffffffffffffff81116100ce576103d2903690600401610449565b606435906001600160a01b03821682036100ce57602093836101b86101bd953361057a565b90601f8019910116810190811067ffffffffffffffff82111761041957604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff811161041957601f01601f191660200190565b81601f820112156100ce578035906104608261042d565b9261046e60405194856103f7565b828452602083830101116100ce57815f926020809301838601378301015290565b805180835260209291819084018484015e5f828201840152601f01601f1916010190565b60405160018060a01b037f0000000000000000000000000000000000000000000000000000000000000000166020820152602081526104f36040826103f7565b90565b90916042926020815191012090602081519101206040519160208301937fdc039731015eea17e316614c8f3af7dca5fc4664683c8e8f2adc4e0ff71a7c9285526040840152606083015260808201526080815261055460a0826103f7565b51902061055f610947565b906040519161190160f01b8352600283015260228201522090565b6001600160a01b0316606082901c819003610593575050565b632696d3f160e11b5f5260045260245260445ffd5b919290805191600b602083019384206040519060408201528560208201523081520160ff8153605590206001600160a01b0390811691168181036106915750508051156106825751905ff5906001600160a01b03821615610673575f816020829351910182855af13d1561066b573d906106218261042d565b9161062f60405193846103f7565b82523d5f602084013e5b15610642575090565b60405163a5fa8d2b60e01b81526020600482015290819061066790602483019061048f565b0390fd5b606090610639565b633a0ba96160e11b5f5260045ffd5b631328927760e21b5f5260045ffd5b6312ae30e560e01b5f5260045260245260445ffd5b60ff81146106ec5760ff811690601f82116106dd57604051916106ca6040846103f7565b6020808452838101919036833783525290565b632cd44ac360e21b5f5260045ffd5b506040515f5f548060011c91600182169182156107bf575b6020841083146107ab57838552849290811561078c575060011461072f575b6104f3925003826103f7565b505f80805290917f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e5635b8183106107705750509060206104f392820101610723565b6020919350806001915483858801015201910190918392610758565b602092506104f394915060ff191682840152151560051b820101610723565b634e487b7160e01b5f52602260045260245ffd5b92607f1692610704565b60ff81146107ed5760ff811690601f82116106dd57604051916106ca6040846103f7565b506040515f6001548060011c916001821691821561088f575b6020841083146107ab57838552849290811561078c5750600114610830576104f3925003826103f7565b5060015f90815290917fb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf65b8183106108735750509060206104f392820101610723565b602091935080600191548385880101520191019091839261085b565b92607f1692610806565b81519190604183036108c9576108c29250602082015190606060408401519301515f1a90610a63565b9192909190565b50505f9160029190565b600481101561093357806108e5575050565b600181036108fc5763f645eedf60e01b5f5260045ffd5b60028103610917575063fce698f760e01b5f5260045260245ffd5b6003146109215750565b6335e2f38360e21b5f5260045260245ffd5b634e487b7160e01b5f52602160045260245ffd5b307f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03161480610a3a575b156109a2577f000000000000000000000000000000000000000000000000000000000000000090565b60405160208101907f8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f82527f000000000000000000000000000000000000000000000000000000000000000060408201527f000000000000000000000000000000000000000000000000000000000000000060608201524660808201523060a082015260a08152610a3460c0826103f7565b51902090565b507f00000000000000000000000000000000000000000000000000000000000000004614610979565b91907f7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a08411610ae5579160209360809260ff5f9560405194855216868401526040830152606082015282805260015afa15610ada575f516001600160a01b03811615610ad057905f905f90565b505f906001905f90565b6040513d5f823e3d90fd5b5050505f916003919056fea264697066735822122020d4cc29643fbc137d039c78a8d78f52fd9a09b7daa1a5943440ff9a3e8ea56f64736f6c634300081c003360c08060405234603257306080523360a0526104349081610037823960805181818160ae015261018b015260a051815050f35b5f80fdfe60806040526004361015610011575f80fd5b5f3560e01c80634f1ef2861461010257806352d1902d1461009c5763ad3cb1cc1461003a575f80fd5b34610098575f366003190112610098576040805190610059818361032e565b600582526020820191640352e302e360dc1b83528151928391602083525180918160208501528484015e5f828201840152601f01601f19168101030190f35b5f80fd5b34610098575f366003190112610098577f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031630036100f35760206040515f5160206103df5f395f51905f528152f35b63703e46dd60e11b5f5260045ffd5b6040366003190112610098576004356001600160a01b03811690818103610098576024359067ffffffffffffffff821161009857366023830112156100985781600401359161015083610364565b9261015e604051948561032e565b8084526020840191366024838301011161009857815f926024602093018537850101526001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001630811490811561030c575b506100f3576040516352d1902d60e01b8152602081600481885afa5f91816102d8575b506101f15784634c9c8ce360e01b5f5260045260245ffd5b805f5160206103df5f395f51905f528692036102c65750823b156102b4575f5160206103df5f395f51905f5280546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a282511561029b575f8091610291945190845af43d15610293573d9161027583610364565b92610283604051948561032e565b83523d5f602085013e610380565b005b606091610380565b505050346102a557005b63b398979f60e01b5f5260045ffd5b634c9c8ce360e01b5f5260045260245ffd5b632a87526960e21b5f5260045260245ffd5b9091506020813d602011610304575b816102f46020938361032e565b81010312610098575190866101d9565b3d91506102e7565b5f5160206103df5f395f51905f52546001600160a01b031614159050856101b6565b90601f8019910116810190811067ffffffffffffffff82111761035057604052565b634e487b7160e01b5f52604160045260245ffd5b67ffffffffffffffff811161035057601f01601f191660200190565b906103a4575080511561039557805190602001fd5b630a12f52160e11b5f5260045ffd5b815115806103d5575b6103b5575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156103ad56fe360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbca264697066735822122005f8ca25544854f7fe07eac3cac751ac5b35b9a8529e80352f19449570409c3364736f6c634300081c0033",
|
|
3
|
+
"deployedAddress": "0xCB571Eaa13A8276B1Ed44348291dD80b5BC360dA",
|
|
4
|
+
"salt": "0x0000000000000000000000000000000000000000000000000000000000000000"
|
|
5
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
{
|
|
2
|
+
"constructorArgs": "0x00000000000000000000000015b56e81f8a628aab8a5a8b9414f05cf5728d1ff",
|
|
3
|
+
"contractName": "Zora",
|
|
4
|
+
"creationCode": "0x60a06040523461016c575f61028a6020813803918261001d81610170565b93849283398101031261016c5751906001600160a01b03821680830361016c576100476020610170565b905f8252833b1561015a577f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc80546001600160a01b031916821790557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b5f80a280511561015257818160208293519101855af43d15610145573d926001600160401b038411610131576100f7936100e7601f8201601f1916602001610170565b908152809360203d92013e6101a9565b505b7fffd9efbec42a225861234c46dd9ad199e6b6c0e9dc65ff463e6987cedc26d6a1608052604051608290816102088239608051815050f35b634e487b7160e01b83526041600452602483fd5b6100f792606092506101a9565b5050506100f9565b634c9c8ce360e01b5f5260045260245ffd5b5f80fd5b6040519190601f01601f191682016001600160401b0381118382101761019557604052565b634e487b7160e01b5f52604160045260245ffd5b906101cd57508051156101be57805190602001fd5b630a12f52160e11b5f5260045ffd5b815115806101fe575b6101de575090565b639996b31560e01b5f9081526001600160a01b0391909116600452602490fd5b50803b156101d656fe60806040527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc545f9081906001600160a01b0316368280378136915af43d5f803e156048573d5ff35b3d5ffdfea2646970667358221220d17864a0488eaaba33173ba368bd2448917739c58ea27a5b985e8b13c01d346664736f6c634300081c003300000000000000000000000015b56e81f8a628aab8a5a8b9414f05cf5728d1ff",
|
|
5
|
+
"deployedAddress": "0x777777751622c0d3258f214F9DF38E35BF45baF3",
|
|
6
|
+
"deploymentCaller": "0x680E26B472d8cae8148ee21FCAd6A69D73766436",
|
|
7
|
+
"salt": "0x680e26b472d8cae8148ee21fcad6a69d73766436f27a901327372bd2be5d38f6"
|
|
8
|
+
}
|
package/foundry.toml
CHANGED
|
@@ -4,6 +4,20 @@ test = "test"
|
|
|
4
4
|
libs = ["node_modules"]
|
|
5
5
|
via_ir = true
|
|
6
6
|
optimizer = true
|
|
7
|
+
solc_version = '0.8.28'
|
|
8
|
+
optimizer_runs = 200
|
|
9
|
+
fs_permissions = [
|
|
10
|
+
{ access = "readwrite", path = "./addresses" },
|
|
11
|
+
{ access = "read", path = "./package.json" },
|
|
12
|
+
{ access = "readwrite", path = "./deterministicConfig" },
|
|
13
|
+
{ access = "read", path = "../shared-contracts/chainConfigs" },
|
|
14
|
+
{ access = "read", path = "../shared-contracts/deterministicConfig" }
|
|
15
|
+
]
|
|
7
16
|
|
|
8
17
|
[profile.ci.fuzz]
|
|
9
18
|
runs = 1000
|
|
19
|
+
|
|
20
|
+
[rpc_endpoints]
|
|
21
|
+
base = "https://base-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}"
|
|
22
|
+
mainnet = "https://eth-mainnet.g.alchemy.com/v2/${ALCHEMY_KEY}"
|
|
23
|
+
zora = "https://rpc.zora.energy"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zoralabs/coins",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -25,12 +25,13 @@
|
|
|
25
25
|
"forge-std": "https://github.com/foundry-rs/forge-std#v1.9.1",
|
|
26
26
|
"prettier": "^3.0.3",
|
|
27
27
|
"prettier-plugin-solidity": "^1.4.1",
|
|
28
|
+
"solady": "0.0.132",
|
|
28
29
|
"tsup": "^7.2.0",
|
|
29
30
|
"tsx": "^3.13.0",
|
|
30
31
|
"typescript": "^5.2.2",
|
|
31
32
|
"viem": "^2.21.18",
|
|
32
|
-
"@zoralabs/shared-scripts": "^0.0.0",
|
|
33
33
|
"@zoralabs/shared-contracts": "^0.0.1",
|
|
34
|
+
"@zoralabs/shared-scripts": "^0.0.0",
|
|
34
35
|
"@zoralabs/tsconfig": "^0.0.1"
|
|
35
36
|
},
|
|
36
37
|
"scripts": {
|
package/remappings.txt
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
ds-test/=node_modules/ds-test/src/
|
|
2
2
|
forge-std/=node_modules/forge-std/src/
|
|
3
3
|
@openzeppelin/=node_modules/@openzeppelin/
|
|
4
|
-
@zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/
|
|
4
|
+
@zoralabs/shared-contracts/=node_modules/@zoralabs/shared-contracts/src/
|
|
5
|
+
solady/=node_modules/solady/src/
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Script.sol";
|
|
5
|
+
|
|
6
|
+
import {ProxyDeployerScript, DeterministicContractConfig, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
|
|
7
|
+
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
8
|
+
import {ZoraFactoryImpl} from "../src/ZoraFactoryImpl.sol";
|
|
9
|
+
import {Coin} from "../src/Coin.sol";
|
|
10
|
+
import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersionedContract.sol";
|
|
11
|
+
|
|
12
|
+
contract CoinsDeployerBase is ProxyDeployerScript {
|
|
13
|
+
address internal constant PROTOCOL_REWARDS = 0x7777777F279eba3d3Ad8F4E708545291A6fDBA8B;
|
|
14
|
+
|
|
15
|
+
using stdJson for string;
|
|
16
|
+
|
|
17
|
+
struct CoinsDeployment {
|
|
18
|
+
// Factory
|
|
19
|
+
address zoraFactory;
|
|
20
|
+
address zoraFactoryImpl;
|
|
21
|
+
// Implementation
|
|
22
|
+
address coinImpl;
|
|
23
|
+
string coinVersion;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
function addressesFile() internal view returns (string memory) {
|
|
27
|
+
return string.concat("./addresses/", vm.toString(block.chainid), ".json");
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function saveDeployment(CoinsDeployment memory deployment) internal {
|
|
31
|
+
string memory objectKey = "config";
|
|
32
|
+
|
|
33
|
+
vm.serializeAddress(objectKey, "ZORA_FACTORY", deployment.zoraFactory);
|
|
34
|
+
vm.serializeAddress(objectKey, "ZORA_FACTORY_IMPL", deployment.zoraFactoryImpl);
|
|
35
|
+
vm.serializeString(objectKey, "COIN_VERSION", deployment.coinVersion);
|
|
36
|
+
string memory result = vm.serializeAddress(objectKey, "COIN_IMPL", deployment.coinImpl);
|
|
37
|
+
|
|
38
|
+
vm.writeJson(result, addressesFile());
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function readDeployment() internal returns (CoinsDeployment memory deployment) {
|
|
42
|
+
string memory file = addressesFile();
|
|
43
|
+
if (!vm.exists(file)) {
|
|
44
|
+
return deployment;
|
|
45
|
+
}
|
|
46
|
+
string memory json = vm.readFile(file);
|
|
47
|
+
|
|
48
|
+
deployment.zoraFactory = readAddressOrDefaultToZero(json, "ZORA_FACTORY");
|
|
49
|
+
deployment.zoraFactoryImpl = readAddressOrDefaultToZero(json, "ZORA_FACTORY_IMPL");
|
|
50
|
+
deployment.coinImpl = readAddressOrDefaultToZero(json, "COIN_IMPL");
|
|
51
|
+
deployment.coinVersion = readStringOrDefaultToEmpty(json, "COIN_VERSION");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function deployCoinImpl() internal returns (Coin) {
|
|
55
|
+
return new Coin(getZoraRecipient(), PROTOCOL_REWARDS, getWeth(), getNonFungiblePositionManager(), getUniswapSwapRouter());
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function deployZoraFactoryImpl(address coinImpl) internal returns (ZoraFactoryImpl) {
|
|
59
|
+
return new ZoraFactoryImpl(coinImpl);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function deployZoraDeterministic(CoinsDeployment memory deployment, DeterministicDeployerAndCaller deployer) internal {
|
|
63
|
+
// read previously saved deterministic config
|
|
64
|
+
DeterministicContractConfig memory zoraConfig = readDeterministicContractConfig("zoraFactory");
|
|
65
|
+
|
|
66
|
+
// Deploy implementation contracts
|
|
67
|
+
deployment.coinImpl = address(deployCoinImpl());
|
|
68
|
+
deployment.zoraFactoryImpl = address(deployZoraFactoryImpl(deployment.coinImpl));
|
|
69
|
+
deployment.coinVersion = IVersionedContract(deployment.coinImpl).contractVersion();
|
|
70
|
+
|
|
71
|
+
if (deployment.zoraFactoryImpl.code.length == 0) {
|
|
72
|
+
revert("Factory Impl not yet deployed. Make sure to deploy it with DeployImpl.s.sol");
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// build upgrade to and call for factory, with init call
|
|
76
|
+
bytes memory upgradeToAndCall = abi.encodeWithSelector(
|
|
77
|
+
UUPSUpgradeable.upgradeToAndCall.selector,
|
|
78
|
+
deployment.zoraFactoryImpl,
|
|
79
|
+
abi.encodeWithSelector(ZoraFactoryImpl.initialize.selector, getProxyAdmin())
|
|
80
|
+
);
|
|
81
|
+
|
|
82
|
+
// sign deployment with turnkey account
|
|
83
|
+
bytes memory signature = signDeploymentWithTurnkey(zoraConfig, upgradeToAndCall, deployer);
|
|
84
|
+
|
|
85
|
+
printVerificationCommand(zoraConfig);
|
|
86
|
+
|
|
87
|
+
deployment.zoraFactory = deployer.permitSafeCreate2AndCall(
|
|
88
|
+
signature,
|
|
89
|
+
zoraConfig.salt,
|
|
90
|
+
zoraConfig.creationCode,
|
|
91
|
+
upgradeToAndCall,
|
|
92
|
+
zoraConfig.deployedAddress
|
|
93
|
+
);
|
|
94
|
+
|
|
95
|
+
// validate that the zora factory owner is the proxy admin
|
|
96
|
+
require(ZoraFactoryImpl(deployment.zoraFactory).owner() == getProxyAdmin(), "Zora factory owner is not the proxy admin");
|
|
97
|
+
}
|
|
98
|
+
}
|
package/script/Deploy.s.sol
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
1
|
// SPDX-License-Identifier: MIT
|
|
2
|
-
pragma solidity ^0.8.
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
6
|
-
contract Deploy is Script {
|
|
7
|
-
function setUp() public {}
|
|
4
|
+
import {ProxyDeployerScript, DeterministicDeployerAndCaller} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
|
|
5
|
+
import {CoinsDeployerBase} from "./CoinsDeployerBase.sol";
|
|
8
6
|
|
|
7
|
+
contract DeployScript is CoinsDeployerBase {
|
|
9
8
|
function run() public {
|
|
9
|
+
CoinsDeployment memory deployment = readDeployment();
|
|
10
|
+
|
|
10
11
|
vm.startBroadcast();
|
|
11
12
|
|
|
13
|
+
// get deployer contract
|
|
14
|
+
DeterministicDeployerAndCaller deployer = createOrGetDeployerAndCaller();
|
|
15
|
+
|
|
16
|
+
deployZoraDeterministic(deployment, deployer);
|
|
17
|
+
|
|
12
18
|
vm.stopBroadcast();
|
|
19
|
+
|
|
20
|
+
// save the deployment json
|
|
21
|
+
saveDeployment(deployment);
|
|
13
22
|
}
|
|
14
23
|
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.28;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Script.sol";
|
|
5
|
+
|
|
6
|
+
import {ImmutableCreate2FactoryUtils} from "@zoralabs/shared-contracts/utils/ImmutableCreate2FactoryUtils.sol";
|
|
7
|
+
import {ProxyDeployerScript, DeterministicDeployerAndCaller, DeterministicContractConfig} from "@zoralabs/shared-contracts/deployment/ProxyDeployerScript.sol";
|
|
8
|
+
import {ZoraFactory} from "../src/proxy/ZoraFactory.sol";
|
|
9
|
+
|
|
10
|
+
contract GenerateDeterministicParams is ProxyDeployerScript {
|
|
11
|
+
function mineForZoraAddress(DeterministicDeployerAndCaller deployer, address caller) private returns (DeterministicContractConfig memory config) {
|
|
12
|
+
// get proxy creation code
|
|
13
|
+
bytes memory initCode = deployer.proxyCreationCode(type(ZoraFactory).creationCode);
|
|
14
|
+
bytes32 initCodeHash = keccak256(initCode);
|
|
15
|
+
|
|
16
|
+
// uupsProxyDeployer is deployer
|
|
17
|
+
(bytes32 salt, address expectedAddress) = mineSalt(address(deployer), initCodeHash, "7777777", caller);
|
|
18
|
+
|
|
19
|
+
console2.log("salt");
|
|
20
|
+
console2.log(vm.toString(salt));
|
|
21
|
+
|
|
22
|
+
config.salt = salt;
|
|
23
|
+
config.deployedAddress = expectedAddress;
|
|
24
|
+
config.creationCode = initCode;
|
|
25
|
+
config.constructorArgs = deployer.proxyConstructorArgs();
|
|
26
|
+
config.contractName = "Zora";
|
|
27
|
+
config.deploymentCaller = caller;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function run() public {
|
|
31
|
+
address caller = vm.envAddress("DEPLOYER");
|
|
32
|
+
|
|
33
|
+
vm.startBroadcast();
|
|
34
|
+
|
|
35
|
+
// create a proxy deployer, which we can use to generate deterministic addresses and corresponding params
|
|
36
|
+
DeterministicDeployerAndCaller deployer = createOrGetDeployerAndCaller();
|
|
37
|
+
|
|
38
|
+
vm.stopBroadcast();
|
|
39
|
+
|
|
40
|
+
DeterministicContractConfig memory zoraConfig = mineForZoraAddress(deployer, caller);
|
|
41
|
+
saveDeterministicContractConfig(zoraConfig, "zoraFactory");
|
|
42
|
+
}
|
|
43
|
+
}
|
package/src/Coin.sol
CHANGED
|
@@ -350,7 +350,7 @@ contract Coin is ICoin, CoinConstants, ContractVersionBase, ERC20PermitUpgradeab
|
|
|
350
350
|
/// @dev Deploy the pool
|
|
351
351
|
function _deployPool(int24 tickLower_) internal {
|
|
352
352
|
// If WETH is the pool's currency, validate the lower tick
|
|
353
|
-
if (currency == WETH && tickLower_
|
|
353
|
+
if (currency == WETH && tickLower_ < LP_TICK_LOWER_WETH) {
|
|
354
354
|
revert InvalidWethLowerTick();
|
|
355
355
|
}
|
|
356
356
|
|
|
@@ -22,5 +22,11 @@ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.s
|
|
|
22
22
|
OURS TRULY,
|
|
23
23
|
*/
|
|
24
24
|
contract ZoraFactory is ERC1967Proxy {
|
|
25
|
-
|
|
25
|
+
bytes32 internal immutable name;
|
|
26
|
+
|
|
27
|
+
constructor(address _logic) ERC1967Proxy(_logic, "") {
|
|
28
|
+
// added to create unique bytecode for this contract
|
|
29
|
+
// so that it can be properly verified as its own contract.
|
|
30
|
+
name = keccak256("ZoraFactory");
|
|
31
|
+
}
|
|
26
32
|
}
|
|
@@ -50,9 +50,9 @@ abstract contract CoinConstants {
|
|
|
50
50
|
/// @dev 10000 basis points = 1%
|
|
51
51
|
uint24 internal constant LP_FEE = 10000;
|
|
52
52
|
|
|
53
|
-
/// @notice The LP's lower tick
|
|
53
|
+
/// @notice The LP's minimum lower tick
|
|
54
54
|
/// @dev This is only used if the currency is WETH
|
|
55
|
-
int24 internal constant LP_TICK_LOWER_WETH = -
|
|
55
|
+
int24 internal constant LP_TICK_LOWER_WETH = -208200;
|
|
56
56
|
|
|
57
57
|
/// @notice The LP's upper tick
|
|
58
58
|
int24 internal constant LP_TICK_UPPER = 887200;
|
|
@@ -9,6 +9,6 @@ import {IVersionedContract} from "@zoralabs/shared-contracts/interfaces/IVersion
|
|
|
9
9
|
contract ContractVersionBase is IVersionedContract {
|
|
10
10
|
/// @notice The version of the contract
|
|
11
11
|
function contractVersion() external pure override returns (string memory) {
|
|
12
|
-
return "0.
|
|
12
|
+
return "0.6.0";
|
|
13
13
|
}
|
|
14
14
|
}
|
package/test/Coin.t.sol
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
pragma solidity ^0.8.13;
|
|
3
3
|
|
|
4
4
|
import "./utils/BaseTest.sol";
|
|
5
|
+
import {ISwapRouter} from "../src/interfaces/ISwapRouter.sol";
|
|
5
6
|
|
|
6
7
|
contract CoinTest is BaseTest {
|
|
7
8
|
function setUp() public override {
|
|
@@ -11,7 +12,7 @@ contract CoinTest is BaseTest {
|
|
|
11
12
|
}
|
|
12
13
|
|
|
13
14
|
function test_contract_version() public view {
|
|
14
|
-
assertEq(coin.contractVersion(), "0.
|
|
15
|
+
assertEq(coin.contractVersion(), "0.6.0");
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
function test_supply_constants() public view {
|
|
@@ -199,6 +200,82 @@ contract CoinTest is BaseTest {
|
|
|
199
200
|
assertGe(coin.balanceOf(users.coinRecipient), amountOut, "coinRecipient coin balance");
|
|
200
201
|
}
|
|
201
202
|
|
|
203
|
+
function test_sell_for_eth_direct_and_claim_secondary() public {
|
|
204
|
+
vm.deal(users.buyer, 1 ether);
|
|
205
|
+
|
|
206
|
+
vm.prank(users.buyer);
|
|
207
|
+
weth.deposit{value: 100_000}();
|
|
208
|
+
|
|
209
|
+
vm.prank(users.buyer);
|
|
210
|
+
weth.approve(address(swapRouter), 100_000);
|
|
211
|
+
|
|
212
|
+
// Set up the swap parameters
|
|
213
|
+
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
|
|
214
|
+
tokenIn: WETH_ADDRESS,
|
|
215
|
+
tokenOut: address(coin),
|
|
216
|
+
fee: LP_FEE,
|
|
217
|
+
recipient: address(users.buyer),
|
|
218
|
+
amountIn: 100_000,
|
|
219
|
+
amountOutMinimum: 0,
|
|
220
|
+
sqrtPriceLimitX96: 0
|
|
221
|
+
});
|
|
222
|
+
|
|
223
|
+
// Execute the swap
|
|
224
|
+
vm.prank(users.buyer);
|
|
225
|
+
uint256 amountOut = ISwapRouter(swapRouter).exactInputSingle(params);
|
|
226
|
+
|
|
227
|
+
assertEq(coin.balanceOf(users.buyer), 108941722423358, "buyer coin balance");
|
|
228
|
+
assertEq(amountOut, 108941722423358);
|
|
229
|
+
assertGt(users.buyer.balance, 0, "seller eth balance");
|
|
230
|
+
|
|
231
|
+
// now we have unclaimed secondary rewards to claim
|
|
232
|
+
vm.prank(users.buyer);
|
|
233
|
+
|
|
234
|
+
// don't push ETH
|
|
235
|
+
coin.claimSecondaryRewards(false);
|
|
236
|
+
assertEq(protocolRewards.balanceOf(users.creator), 499);
|
|
237
|
+
assertEq(protocolRewards.balanceOf(users.platformReferrer), 249);
|
|
238
|
+
assertEq(protocolRewards.balanceOf(users.feeRecipient), 251);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
function test_sell_for_eth_direct_and_claim_secondary_push_eth() public {
|
|
242
|
+
vm.deal(users.buyer, 1 ether);
|
|
243
|
+
|
|
244
|
+
vm.prank(users.buyer);
|
|
245
|
+
weth.deposit{value: 100_000}();
|
|
246
|
+
|
|
247
|
+
vm.prank(users.buyer);
|
|
248
|
+
weth.approve(address(swapRouter), 100_000);
|
|
249
|
+
|
|
250
|
+
// Set up the swap parameters
|
|
251
|
+
ISwapRouter.ExactInputSingleParams memory params = ISwapRouter.ExactInputSingleParams({
|
|
252
|
+
tokenIn: WETH_ADDRESS,
|
|
253
|
+
tokenOut: address(coin),
|
|
254
|
+
fee: LP_FEE,
|
|
255
|
+
recipient: address(users.buyer),
|
|
256
|
+
amountIn: 100_000,
|
|
257
|
+
amountOutMinimum: 0,
|
|
258
|
+
sqrtPriceLimitX96: 0
|
|
259
|
+
});
|
|
260
|
+
|
|
261
|
+
// Execute the swap
|
|
262
|
+
vm.prank(users.buyer);
|
|
263
|
+
uint256 amountOut = ISwapRouter(swapRouter).exactInputSingle(params);
|
|
264
|
+
|
|
265
|
+
assertEq(coin.balanceOf(users.buyer), 108941722423358, "buyer coin balance");
|
|
266
|
+
assertEq(amountOut, 108941722423358);
|
|
267
|
+
assertGt(users.buyer.balance, 0, "seller eth balance");
|
|
268
|
+
|
|
269
|
+
// Now we have unclaimed secondary rewards to claim
|
|
270
|
+
vm.prank(users.buyer);
|
|
271
|
+
|
|
272
|
+
uint256 initialBalance = users.creator.balance;
|
|
273
|
+
|
|
274
|
+
// Push ETH
|
|
275
|
+
coin.claimSecondaryRewards(true);
|
|
276
|
+
assertEq(users.creator.balance - initialBalance, 499);
|
|
277
|
+
}
|
|
278
|
+
|
|
202
279
|
function test_sell_for_eth() public {
|
|
203
280
|
vm.deal(users.buyer, 1 ether);
|
|
204
281
|
vm.prank(users.buyer);
|
|
@@ -284,18 +361,18 @@ contract CoinTest is BaseTest {
|
|
|
284
361
|
coin.buy{value: 0.001 ether}(users.creator, 0.001 ether, 0, 0, users.tradeReferrer);
|
|
285
362
|
|
|
286
363
|
uint256 beforeBalance = coin.balanceOf(users.creator);
|
|
287
|
-
assertEq(beforeBalance,
|
|
364
|
+
assertEq(beforeBalance, 11077349369032224007213331); // 11,077,349 coins
|
|
288
365
|
|
|
289
366
|
vm.prank(users.creator);
|
|
290
367
|
(uint256 amountSold, ) = coin.sell(users.creator, beforeBalance, 0, 0, users.tradeReferrer);
|
|
291
|
-
assertEq(amountSold,
|
|
368
|
+
assertEq(amountSold, 1088231685891135360821548); // 1,088,232 coins (max that could be sold)
|
|
292
369
|
|
|
293
370
|
uint256 afterBalance = coin.balanceOf(users.creator);
|
|
294
|
-
assertEq(afterBalance,
|
|
371
|
+
assertEq(afterBalance, 9994558841570544323195890); // 9,994,559 coins
|
|
295
372
|
|
|
296
|
-
uint256 expectedMarketReward =
|
|
373
|
+
uint256 expectedMarketReward = 5441158429455676804107; // 5,441 coins
|
|
297
374
|
|
|
298
|
-
// 9,
|
|
375
|
+
// 9,994,559 = 11,077,349 order size - 1,088,232 true order size + 5,441 creator market reward
|
|
299
376
|
assertEq(afterBalance, ((beforeBalance - amountSold) + expectedMarketReward), "amountSold");
|
|
300
377
|
}
|
|
301
378
|
|
|
@@ -361,6 +438,42 @@ contract CoinTest is BaseTest {
|
|
|
361
438
|
assertGt(protocolRewards.balanceOf(users.feeRecipient), expectedFees.platformReferrer, "feeRecipient eth balance");
|
|
362
439
|
}
|
|
363
440
|
|
|
441
|
+
function test_invalid_weth_tick() public {
|
|
442
|
+
address[] memory owners = new address[](1);
|
|
443
|
+
owners[0] = users.creator;
|
|
444
|
+
|
|
445
|
+
vm.expectRevert(ICoin.InvalidWethLowerTick.selector);
|
|
446
|
+
(address newCoinAddr, ) = factory.deploy(
|
|
447
|
+
users.creator,
|
|
448
|
+
owners,
|
|
449
|
+
"https://test.com",
|
|
450
|
+
"Test Token",
|
|
451
|
+
"TEST",
|
|
452
|
+
users.platformReferrer,
|
|
453
|
+
address(weth),
|
|
454
|
+
LP_TICK_LOWER_WETH - 1,
|
|
455
|
+
0
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
function test_invalid_currency_tick() public {
|
|
460
|
+
address[] memory owners = new address[](1);
|
|
461
|
+
owners[0] = users.creator;
|
|
462
|
+
|
|
463
|
+
vm.expectRevert(ICoin.InvalidCurrencyLowerTick.selector);
|
|
464
|
+
(address newCoinAddr, ) = factory.deploy(
|
|
465
|
+
users.creator,
|
|
466
|
+
owners,
|
|
467
|
+
"https://test.com",
|
|
468
|
+
"Test Token",
|
|
469
|
+
"TEST",
|
|
470
|
+
users.platformReferrer,
|
|
471
|
+
address(0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913),
|
|
472
|
+
20,
|
|
473
|
+
0
|
|
474
|
+
);
|
|
475
|
+
}
|
|
476
|
+
|
|
364
477
|
function test_default_order_referrer() public {
|
|
365
478
|
vm.deal(users.buyer, 1 ether);
|
|
366
479
|
vm.prank(users.buyer);
|
package/test/Factory.t.sol
CHANGED
|
@@ -96,6 +96,35 @@ contract FactoryTest is BaseTest {
|
|
|
96
96
|
console.log("BUYER_COIN_BALANCE ", coin.balanceOf(users.creator) - 10_000_000e18);
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
+
function test_deploy_with_weth(uint256 initialOrderSize) public {
|
|
100
|
+
vm.assume(initialOrderSize > MIN_ORDER_SIZE);
|
|
101
|
+
vm.assume(initialOrderSize < 10 ether);
|
|
102
|
+
|
|
103
|
+
address[] memory owners = new address[](1);
|
|
104
|
+
owners[0] = users.creator;
|
|
105
|
+
|
|
106
|
+
vm.deal(users.creator, initialOrderSize);
|
|
107
|
+
|
|
108
|
+
vm.startPrank(users.creator);
|
|
109
|
+
weth.deposit{value: initialOrderSize}();
|
|
110
|
+
|
|
111
|
+
weth.approve(address(factory), type(uint256).max);
|
|
112
|
+
|
|
113
|
+
// Expect this to revert because WETH needs to be sent with msg.value.
|
|
114
|
+
vm.expectRevert();
|
|
115
|
+
factory.deploy(
|
|
116
|
+
users.creator,
|
|
117
|
+
owners,
|
|
118
|
+
"https://test2.com",
|
|
119
|
+
"Test2 Token",
|
|
120
|
+
"TEST2",
|
|
121
|
+
users.platformReferrer,
|
|
122
|
+
address(weth),
|
|
123
|
+
LP_TICK_LOWER_WETH,
|
|
124
|
+
initialOrderSize
|
|
125
|
+
);
|
|
126
|
+
}
|
|
127
|
+
|
|
99
128
|
function test_deploy_with_one_eth() public {
|
|
100
129
|
address[] memory owners = new address[](1);
|
|
101
130
|
owners[0] = users.creator;
|
|
@@ -206,17 +235,7 @@ contract FactoryTest is BaseTest {
|
|
|
206
235
|
|
|
207
236
|
vm.expectRevert(abi.encodeWithSelector(ICoin.InvalidWethLowerTick.selector));
|
|
208
237
|
|
|
209
|
-
factory.deploy(
|
|
210
|
-
users.creator,
|
|
211
|
-
owners,
|
|
212
|
-
"https://testcoinusdcpair.com",
|
|
213
|
-
"Testcoinusdcpair",
|
|
214
|
-
"TESTCOINUSDCPAIR",
|
|
215
|
-
users.platformReferrer,
|
|
216
|
-
address(0),
|
|
217
|
-
USDC_TICK_LOWER,
|
|
218
|
-
0
|
|
219
|
-
);
|
|
238
|
+
factory.deploy(users.creator, owners, "https://testcoin.com", "Testcoin", "TESTCOIN", users.platformReferrer, address(0), LP_TICK_LOWER_WETH - 1, 0);
|
|
220
239
|
}
|
|
221
240
|
|
|
222
241
|
function test_deploy_with_usdc_revert_invalid_eth_transfer() public {
|
|
@@ -272,6 +291,10 @@ contract FactoryTest is BaseTest {
|
|
|
272
291
|
assertEq(factory.implementation(), address(newImpl), "implementation");
|
|
273
292
|
}
|
|
274
293
|
|
|
294
|
+
function test_implementation_address() public view {
|
|
295
|
+
assertEq(factory.implementation(), address(factoryImpl));
|
|
296
|
+
}
|
|
297
|
+
|
|
275
298
|
function test_revert_invalid_upgrade_impl() public {
|
|
276
299
|
address newImpl = address(this);
|
|
277
300
|
|
package/test/utils/BaseTest.sol
CHANGED
|
@@ -59,7 +59,7 @@ contract BaseTest is Test, CoinConstants {
|
|
|
59
59
|
IUniswapV3Pool internal pool;
|
|
60
60
|
|
|
61
61
|
function setUp() public virtual {
|
|
62
|
-
forkId = vm.createSelectFork("
|
|
62
|
+
forkId = vm.createSelectFork("base", 21179722);
|
|
63
63
|
|
|
64
64
|
weth = IWETH(WETH_ADDRESS);
|
|
65
65
|
usdc = IERC20Metadata(USDC_ADDRESS);
|
|
@@ -80,9 +80,9 @@ contract BaseTest is Test, CoinConstants {
|
|
|
80
80
|
|
|
81
81
|
coinImpl = new Coin(users.feeRecipient, address(protocolRewards), WETH_ADDRESS, NONFUNGIBLE_POSITION_MANAGER, SWAP_ROUTER);
|
|
82
82
|
factoryImpl = new ZoraFactoryImpl(address(coinImpl));
|
|
83
|
-
factory = ZoraFactoryImpl(
|
|
84
|
-
|
|
85
|
-
);
|
|
83
|
+
factory = ZoraFactoryImpl(address(new ZoraFactory(address(factoryImpl))));
|
|
84
|
+
|
|
85
|
+
ZoraFactoryImpl(factory).initialize(users.factoryOwner);
|
|
86
86
|
|
|
87
87
|
vm.label(address(factory), "ZORA_FACTORY");
|
|
88
88
|
vm.label(address(protocolRewards), "PROTOCOL_REWARDS");
|
package/abis/Deploy.json
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
[
|
|
2
|
-
{
|
|
3
|
-
"type": "function",
|
|
4
|
-
"name": "IS_SCRIPT",
|
|
5
|
-
"inputs": [],
|
|
6
|
-
"outputs": [
|
|
7
|
-
{
|
|
8
|
-
"name": "",
|
|
9
|
-
"type": "bool",
|
|
10
|
-
"internalType": "bool"
|
|
11
|
-
}
|
|
12
|
-
],
|
|
13
|
-
"stateMutability": "view"
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
"type": "function",
|
|
17
|
-
"name": "run",
|
|
18
|
-
"inputs": [],
|
|
19
|
-
"outputs": [],
|
|
20
|
-
"stateMutability": "nonpayable"
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"type": "function",
|
|
24
|
-
"name": "setUp",
|
|
25
|
-
"inputs": [],
|
|
26
|
-
"outputs": [],
|
|
27
|
-
"stateMutability": "nonpayable"
|
|
28
|
-
}
|
|
29
|
-
]
|
package/addresses/1.json
DELETED