Skip to content

Commit 0666559

Browse files
authored
Merge pull request #156 from thirdweb-dev/byoc
BYOC: initial work
2 parents e68775c + 600303b commit 0666559

File tree

86 files changed

+8120
-3383
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+8120
-3383
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ typechain/
1515
.parcel-cache/
1616

1717
abi/
18+
contracts/abi/
1819
artifacts/
1920
artifacts_forge/
2021

README.md

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,38 @@
44
55
## Quick start
66

7-
The [`@thirdweb-dev/contracts`](https://www.npmjs.com/package/@thirdweb-dev/contracts) package gives you access to all contracts and interfaces available in the `/contracts` directory of this repository.
7+
### BYOC Deployments - (new)
88

9-
**Installation:**
10-
```bash
11-
yarn add @thirdweb-dev/contracts
12-
```
9+
### ByocRegistry - Mumbai
10+
- `TWRegistry`: [0x3F17972CB27506eb4a6a3D59659e0B57a43fd16C](https://blockscan.com/address/0x3F17972CB27506eb4a6a3D59659e0B57a43fd16C#code)
11+
12+
- `ByocRegistry`: [0x61Bb02795b4fF5248169A54D9f149C4557B0B7de](https://mumbai.polygonscan.com/address/0x61Bb02795b4fF5248169A54D9f149C4557B0B7de#code)
1313

14-
**Usage:**
14+
- `ByocFactory`: [0x3c3D901Acb5f7746dCf06B26fCe881d21970d2B6](https://mumbai.polygonscan.com/address/0x3c3D901Acb5f7746dCf06B26fCe881d21970d2B6#code)
15+
16+
### BYOC Deployments - (previous)
1517

1618
`@thirdweb-dev/contracts` can be used in your Solidity project just like other popular libraries e.g. `@openzeppelin/contracts`. Once you've installed the package, import the relevant resources from the package as follows:
1719

1820
```solidity
1921
// Example usage
2022
21-
import "@thirdweb-dev/contracts/contracts/interfaces/token/TokenERC721.sol";
23+
import "@thirdweb-dev/contracts/interfaces/token/TokenERC721.sol";
2224
2325
contract MyNFT is TokenERC721 { ... }
2426
```
2527

2628
## Run locally
2729

28-
Clone the repository:
29-
```bash
30-
git clone https://github.com/thirdweb-dev/contracts.git
31-
```
30+
### Deployments (prod)
31+
- `TWRegistry`: [0x7c487845f98938Bb955B1D5AD069d9a30e4131fd](https://blockscan.com/address/0x7c487845f98938Bb955B1D5AD069d9a30e4131fd)
32+
33+
- `TWFactory`: [0x11c34F062Cb10a20B9F463E12Ff9dA62D76FDf65](https://blockscan.com/address/0x11c34F062Cb10a20B9F463E12Ff9dA62D76FDf65)
34+
35+
## Running Tests
36+
1. `yarn`: install contracts dependencies
37+
2. `forge install`: install tests dependencies
38+
3. `forge test`: run the tests
3239

3340
This repository is a hybrid [hardhat](https://hardhat.org/) and [forge](https://github.com/foundry-rs/foundry/tree/master/forge) project.
3441

contracts/ByocFactory.sol

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
pragma solidity ^0.8.11;
3+
4+
// ========== External imports ==========
5+
import "@openzeppelin/contracts/utils/Create2.sol";
6+
import "@openzeppelin/contracts/proxy/Clones.sol";
7+
import "@openzeppelin/contracts/utils/Address.sol";
8+
import "@openzeppelin/contracts/access/AccessControlEnumerable.sol";
9+
import "@openzeppelin/contracts/metatx/ERC2771Context.sol";
10+
11+
// ========== Internal imports ==========
12+
import { IByocFactory } from "./interfaces/IByocFactory.sol";
13+
import { TWRegistry } from "./TWRegistry.sol";
14+
import { ThirdwebContract } from "./ThirdwebContract.sol";
15+
16+
contract ByocFactory is IByocFactory, ERC2771Context, AccessControlEnumerable {
17+
/*///////////////////////////////////////////////////////////////
18+
State variables
19+
//////////////////////////////////////////////////////////////*/
20+
21+
/// @dev The main thirdweb registry.
22+
TWRegistry private immutable registry;
23+
24+
/// @dev Whether the registry is paused.
25+
bool public isPaused;
26+
27+
/*///////////////////////////////////////////////////////////////
28+
Constructor + modifiers
29+
//////////////////////////////////////////////////////////////*/
30+
31+
/// @dev Checks whether contract is unpaused or the caller is a contract admin.
32+
modifier onlyUnpausedOrAdmin() {
33+
require(!isPaused || hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "registry paused");
34+
35+
_;
36+
}
37+
38+
constructor(address _twRegistry, address _trustedForwarder) ERC2771Context(_trustedForwarder) {
39+
registry = TWRegistry(_twRegistry);
40+
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
41+
}
42+
43+
/*///////////////////////////////////////////////////////////////
44+
Deploy logic
45+
//////////////////////////////////////////////////////////////*/
46+
47+
/// @notice Deploys an instance of a published contract directly.
48+
function deployInstance(
49+
address _publisher,
50+
bytes memory _contractBytecode,
51+
bytes memory _constructorArgs,
52+
bytes32 _salt,
53+
uint256 _value,
54+
ThirdwebContract.ThirdwebInfo memory _thirdwebInfo
55+
) external onlyUnpausedOrAdmin returns (address deployedAddress) {
56+
require(bytes(_thirdwebInfo.publishMetadataUri).length > 0, "No publish metadata");
57+
58+
bytes memory contractBytecode = abi.encodePacked(_contractBytecode, _constructorArgs);
59+
bytes32 salt = _salt == "" ? keccak256(abi.encodePacked(_msgSender(), block.number)) : _salt;
60+
61+
deployedAddress = Create2.deploy(_value, salt, contractBytecode);
62+
63+
ThirdwebContract(deployedAddress).setThirdwebInfo(_thirdwebInfo);
64+
require(
65+
keccak256(bytes(ThirdwebContract(deployedAddress).getPublishMetadataUri())) ==
66+
keccak256(bytes(_thirdwebInfo.publishMetadataUri)),
67+
"Not a thirdweb contract"
68+
);
69+
70+
registry.add(_publisher, deployedAddress);
71+
72+
emit ContractDeployed(_msgSender(), _publisher, deployedAddress);
73+
}
74+
75+
/// @notice Deploys a clone pointing to an implementation of a published contract.
76+
function deployInstanceProxy(
77+
address _publisher,
78+
address _implementation,
79+
bytes memory _initializeData,
80+
bytes32 _salt,
81+
uint256 _value,
82+
ThirdwebContract.ThirdwebInfo memory _thirdwebInfo
83+
) external onlyUnpausedOrAdmin returns (address deployedAddress) {
84+
bytes32 salt = _salt == "" ? keccak256(abi.encodePacked(_msgSender(), block.number)) : _salt;
85+
deployedAddress = Clones.cloneDeterministic(_implementation, salt);
86+
87+
ThirdwebContract(deployedAddress).setThirdwebInfo(_thirdwebInfo);
88+
require(
89+
keccak256(bytes(ThirdwebContract(deployedAddress).getPublishMetadataUri())) ==
90+
keccak256(bytes(_thirdwebInfo.publishMetadataUri)),
91+
"Not a thirdweb contract"
92+
);
93+
94+
registry.add(_publisher, deployedAddress);
95+
96+
if (_initializeData.length > 0) {
97+
// slither-disable-next-line unused-return
98+
Address.functionCallWithValue(deployedAddress, _initializeData, _value);
99+
}
100+
101+
emit ContractDeployed(_msgSender(), _publisher, deployedAddress);
102+
}
103+
104+
/*///////////////////////////////////////////////////////////////
105+
Miscellaneous
106+
//////////////////////////////////////////////////////////////*/
107+
108+
/// @dev Lets a contract admin pause the registry.
109+
function setPause(bool _pause) external {
110+
require(hasRole(DEFAULT_ADMIN_ROLE, _msgSender()), "unapproved caller");
111+
isPaused = _pause;
112+
emit Paused(_pause);
113+
}
114+
115+
function _msgSender() internal view virtual override(Context, ERC2771Context) returns (address sender) {
116+
return ERC2771Context._msgSender();
117+
}
118+
119+
function _msgData() internal view virtual override(Context, ERC2771Context) returns (bytes calldata) {
120+
return ERC2771Context._msgData();
121+
}
122+
}

0 commit comments

Comments
 (0)