@paimaexample/evm-contracts 0.3.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/README.md +7 -0
- package/deno.json +28 -0
- package/docs/templates/contract.hbs +144 -0
- package/docs/templates/helpers.js +61 -0
- package/docs/templates/page.hbs +7 -0
- package/docs/templates/properties.js +76 -0
- package/hardhat.config.ts +11 -0
- package/index.js +1 -0
- package/mod.ts +0 -0
- package/package.json +13 -0
- package/remappings.txt +1 -0
- package/src/companions/ERC165Contract.json +21 -0
- package/src/companions/ERC165Contract.ts +21 -0
- package/src/companions/ERC20Contract.json +222 -0
- package/src/companions/ERC20Contract.ts +222 -0
- package/src/companions/ERC6551RegistryContract.json +128 -0
- package/src/companions/ERC6551RegistryContract.ts +128 -0
- package/src/companions/ERC721Contract.json +248 -0
- package/src/companions/ERC721Contract.ts +222 -0
- package/src/companions/IERC1155Contract.json +295 -0
- package/src/companions/IERC1155Contract.ts +295 -0
- package/src/companions/OldERC6551RegistryContract.json +133 -0
- package/src/companions/OldERC6551RegistryContract.ts +133 -0
- package/src/companions/PaimaERC721Contract.json +787 -0
- package/src/companions/PaimaERC721Contract.ts +787 -0
- package/src/companions/PaimaL2Contract.json +134 -0
- package/src/companions/PaimaL2Contract.ts +134 -0
- package/src/companions/README.md +5 -0
- package/src/contracts/AnnotatedMintNft.sol +171 -0
- package/src/contracts/BaseState.sol +16 -0
- package/src/contracts/ERC1967.sol +43 -0
- package/src/contracts/Erc20NftSale.sol +186 -0
- package/src/contracts/GenericPayment.sol +60 -0
- package/src/contracts/NativeNftSale.sol +97 -0
- package/src/contracts/PaimaL2Contract.sol +54 -0
- package/src/contracts/Proxy/Erc20NftSaleProxy.sol +79 -0
- package/src/contracts/Proxy/GenericPaymentProxy.sol +64 -0
- package/src/contracts/Proxy/NativeNftSaleProxy.sol +72 -0
- package/src/contracts/Proxy/OrderbookDexProxy.sol +27 -0
- package/src/contracts/README.md +72 -0
- package/src/contracts/State.sol +25 -0
- package/src/contracts/dev/ERC721Dev.sol +13 -0
- package/src/contracts/dev/Erc20Dev.sol +13 -0
- package/src/contracts/dev/NativeNftSaleUpgradeDev.sol +9 -0
- package/src/contracts/dev/NftSaleUpgradeDev.sol +12 -0
- package/src/contracts/dev/NftTypeMapper.sol +38 -0
- package/src/contracts/dev/Token.sol +15 -0
- package/src/contracts/dev/UpgradeDev.sol +10 -0
- package/src/contracts/orderbook/IOrderbookDex.sol +215 -0
- package/src/contracts/orderbook/OrderbookDex.sol +435 -0
- package/src/contracts/token/IERC4906Agnostic.sol +17 -0
- package/src/contracts/token/IInverseAppProjected1155.sol +40 -0
- package/src/contracts/token/IInverseAppProjectedNft.sol +38 -0
- package/src/contracts/token/IInverseBaseProjected1155.sol +25 -0
- package/src/contracts/token/IInverseBaseProjectedNft.sol +29 -0
- package/src/contracts/token/IInverseProjected1155.sol +38 -0
- package/src/contracts/token/IInverseProjectedNft.sol +41 -0
- package/src/contracts/token/ITokenUri.sol +10 -0
- package/src/contracts/token/IUri.sol +13 -0
- package/src/contracts/token/InverseAppProjected1155.sol +218 -0
- package/src/contracts/token/InverseAppProjectedNft.sol +192 -0
- package/src/contracts/token/InverseBaseProjected1155.sol +170 -0
- package/src/contracts/token/InverseBaseProjectedNft.sol +158 -0
- package/src/plugin/common.ts +35 -0
- package/src/plugin/deployment.ts +161 -0
- package/src/plugin/mod.ts +6 -0
- package/src/plugin/paimaL2.ts +202 -0
- package/src/recommendedHardhat.ts +86 -0
- package/test/lib/StdInvariant.sol +96 -0
- package/test/lib/cheatcodes.sol +89 -0
- package/test/lib/console.sol +1884 -0
- package/test/lib/ctest.sol +678 -0
- package/test/src/InverseAppProjected1155.t.sol +207 -0
- package/test/src/InverseAppProjectedNft.t.sol +164 -0
- package/test/src/InverseBaseProjected1155.t.sol +171 -0
- package/test/src/InverseBaseProjectedNft.t.sol +141 -0
- package/test/src/OrderbookDex.t.sol +710 -0
- package/test/src/OrderbookDexInvariant.t.sol +426 -0
- package/test/src/PaimaL2ContractTest.sol +115 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.13;
|
|
3
|
+
|
|
4
|
+
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
|
5
|
+
import {ERC1155} from "@openzeppelin/contracts/token/ERC1155/ERC1155.sol";
|
|
6
|
+
import {IERC1155MetadataURI} from "@openzeppelin/contracts/token/ERC1155/extensions/IERC1155MetadataURI.sol";
|
|
7
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
8
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
9
|
+
import {IInverseProjected1155} from "./IInverseProjected1155.sol";
|
|
10
|
+
import {IInverseBaseProjected1155} from "./IInverseBaseProjected1155.sol";
|
|
11
|
+
import {IUri} from "./IUri.sol";
|
|
12
|
+
|
|
13
|
+
/// @dev A Paima Inverse Projection ERC1155 token where initialization is handled by the base-layer.
|
|
14
|
+
/// A standard ERC1155 that accepts calldata in the mint function for any initialization data needed in a Paima dApp.
|
|
15
|
+
contract InverseBaseProjected1155 is IInverseBaseProjected1155, ERC1155, Ownable {
|
|
16
|
+
using Strings for uint256;
|
|
17
|
+
|
|
18
|
+
string public name;
|
|
19
|
+
string public symbol;
|
|
20
|
+
|
|
21
|
+
/// @dev The token ID that will be minted when calling the `mint` function.
|
|
22
|
+
uint256 public currentTokenId;
|
|
23
|
+
/// @dev Base URI that is used in the `uri` function to form the start of the token URI.
|
|
24
|
+
string public baseURI;
|
|
25
|
+
/// @dev Base extension that is used in the `uri` function to form the end of the token URI.
|
|
26
|
+
string public baseExtension;
|
|
27
|
+
|
|
28
|
+
mapping(uint256 id => uint256) private _totalSupply;
|
|
29
|
+
|
|
30
|
+
/// @dev Sets the NFT's `name`, `symbol`, and transfers ownership to `owner`.
|
|
31
|
+
/// Also sets `currentTokenId` to 1.
|
|
32
|
+
constructor(
|
|
33
|
+
string memory _name,
|
|
34
|
+
string memory _symbol,
|
|
35
|
+
address _owner
|
|
36
|
+
) ERC1155("") Ownable(_owner) {
|
|
37
|
+
name = _name;
|
|
38
|
+
symbol = _symbol;
|
|
39
|
+
currentTokenId = 1;
|
|
40
|
+
baseExtension = ".json";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/// @dev Returns true if this contract implements the interface defined by `interfaceId`. See EIP165.
|
|
44
|
+
function supportsInterface(
|
|
45
|
+
bytes4 interfaceId
|
|
46
|
+
) public view virtual override(IERC165, ERC1155) returns (bool) {
|
|
47
|
+
return
|
|
48
|
+
interfaceId == type(IInverseProjected1155).interfaceId ||
|
|
49
|
+
interfaceId == type(IInverseBaseProjected1155).interfaceId ||
|
|
50
|
+
super.supportsInterface(interfaceId);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/// @dev Returns the total amount of tokens with ID `id` that currently exists.
|
|
54
|
+
function totalSupply(uint256 id) public view virtual returns (uint256) {
|
|
55
|
+
return _totalSupply[id];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/// @dev Mints `value` of a new token to transaction sender, passing `initialData` to be emitted in the event.
|
|
59
|
+
/// Increases the `currentTokenId`.
|
|
60
|
+
/// Reverts if transaction sender is a smart contract that does not implement IERC1155Receiver-onERC1155Received.
|
|
61
|
+
/// Emits the `Minted` event.
|
|
62
|
+
/// @param value the amount of tokens to mint.
|
|
63
|
+
/// @param data additional data to pass to the receiver contract.
|
|
64
|
+
/// @param initialData data that is emitted in the `Minted` event.
|
|
65
|
+
/// @return id of the minted token.
|
|
66
|
+
function mint(
|
|
67
|
+
uint256 value,
|
|
68
|
+
bytes memory data,
|
|
69
|
+
string calldata initialData
|
|
70
|
+
) public virtual returns (uint256) {
|
|
71
|
+
uint256 tokenId = currentTokenId;
|
|
72
|
+
_mint(msg.sender, tokenId, value, data);
|
|
73
|
+
|
|
74
|
+
currentTokenId++;
|
|
75
|
+
|
|
76
|
+
emit Minted(tokenId, value, initialData);
|
|
77
|
+
return tokenId;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// @dev Burns `value` amount of token of ID `id` from transaction sender.
|
|
81
|
+
/// Reverts if transaction sender's balance of `id` is less than `value`.
|
|
82
|
+
function burn(uint256 id, uint256 value) public virtual {
|
|
83
|
+
_burn(msg.sender, id, value);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/// @dev Burns batch of `values` amounts of tokens of IDs `ids` from transaction sender.
|
|
87
|
+
/// Reverts if transaction sender's balance of any `id` is less than `value`.
|
|
88
|
+
function burnBatch(uint256[] memory ids, uint256[] memory values) public virtual {
|
|
89
|
+
_burnBatch(msg.sender, ids, values);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// @dev Returns the token URI of specified `id` using the default set base URI.
|
|
93
|
+
function uri(
|
|
94
|
+
uint256 id
|
|
95
|
+
) public view virtual override(ERC1155, IERC1155MetadataURI) returns (string memory) {
|
|
96
|
+
return uri(id, baseURI);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
/// @dev Returns the token URI of specified `id` using a custom base URI.
|
|
100
|
+
function uri(
|
|
101
|
+
uint256 id,
|
|
102
|
+
string memory customBaseUri
|
|
103
|
+
) public view virtual returns (string memory) {
|
|
104
|
+
require(_totalSupply[id] > 0, "InverseBaseProjected1155: URI query for nonexistent token");
|
|
105
|
+
string memory URI = bytes(customBaseUri).length > 0
|
|
106
|
+
? string.concat(customBaseUri, "eip155:", block.chainid.toString(), "/", id.toString())
|
|
107
|
+
: "";
|
|
108
|
+
return string(abi.encodePacked(URI, baseExtension));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/// @dev Returns the token URI of specified `id` using a call to contract implementing `IUri`.
|
|
112
|
+
function uri(uint256 id, IUri customUriInterface) public view virtual returns (string memory) {
|
|
113
|
+
return customUriInterface.uri(id);
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/// @dev Sets `_URI` as the `baseURI` of the NFT.
|
|
117
|
+
/// Callable only by the contract owner.
|
|
118
|
+
/// Emits the `SetBaseURI` event.
|
|
119
|
+
function setBaseURI(string memory _URI) public virtual onlyOwner {
|
|
120
|
+
string memory oldURI = baseURI;
|
|
121
|
+
baseURI = _URI;
|
|
122
|
+
emit SetBaseURI(oldURI, _URI);
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/// @dev Sets `_newBaseExtension` as the `baseExtension` of the NFT.
|
|
126
|
+
/// Callable only by the contract owner.
|
|
127
|
+
function setBaseExtension(string memory _newBaseExtension) public virtual onlyOwner {
|
|
128
|
+
string memory oldBaseExtension = baseExtension;
|
|
129
|
+
baseExtension = _newBaseExtension;
|
|
130
|
+
emit SetBaseURI(oldBaseExtension, _newBaseExtension);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/// @dev Function that emits an event to notify third-parties (e.g. NFT marketplaces) about
|
|
134
|
+
/// an update to consecutive range of tokens. Can be overridden in inheriting contract.
|
|
135
|
+
function updateMetadataBatch(uint256 _fromTokenId, uint256 _toTokenId) public virtual {
|
|
136
|
+
emit BatchMetadataUpdate(_fromTokenId, _toTokenId);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/// @dev Function that emits an event to notify third-parties (e.g. NFT marketplaces) about
|
|
140
|
+
/// an update to a single token. Can be overridden in inheriting contract.
|
|
141
|
+
function updateMetadata(uint256 _tokenId) public virtual {
|
|
142
|
+
emit MetadataUpdate(_tokenId);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/// @dev See {ERC1155-_update}.
|
|
146
|
+
function _update(
|
|
147
|
+
address from,
|
|
148
|
+
address to,
|
|
149
|
+
uint256[] memory ids,
|
|
150
|
+
uint256[] memory values
|
|
151
|
+
) internal virtual override {
|
|
152
|
+
super._update(from, to, ids, values);
|
|
153
|
+
|
|
154
|
+
if (from == address(0)) {
|
|
155
|
+
for (uint256 i = 0; i < ids.length; ++i) {
|
|
156
|
+
// Overflow check required: The rest of the code assumes that totalSupply never overflows
|
|
157
|
+
_totalSupply[ids[i]] += values[i];
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (to == address(0)) {
|
|
162
|
+
for (uint256 i = 0; i < ids.length; ++i) {
|
|
163
|
+
unchecked {
|
|
164
|
+
// Overflow not possible: values[i] <= balanceOf(from, ids[i]) <= totalSupply(ids[i])
|
|
165
|
+
_totalSupply[ids[i]] -= values[i];
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.13;
|
|
3
|
+
|
|
4
|
+
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
|
|
5
|
+
import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
|
|
6
|
+
import {IERC721Metadata} from "@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
|
|
7
|
+
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
|
|
8
|
+
import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
|
9
|
+
import {IInverseProjectedNft} from "./IInverseProjectedNft.sol";
|
|
10
|
+
import {IInverseBaseProjectedNft} from "./IInverseBaseProjectedNft.sol";
|
|
11
|
+
import {ITokenUri} from "./ITokenUri.sol";
|
|
12
|
+
|
|
13
|
+
/// @dev A standard ERC721 that accepts calldata in the mint function for any initialization data needed in a Paima dApp.
|
|
14
|
+
/// See PRC3 for more.
|
|
15
|
+
contract InverseBaseProjectedNft is IInverseBaseProjectedNft, ERC721, Ownable {
|
|
16
|
+
using Strings for uint256;
|
|
17
|
+
|
|
18
|
+
/// @dev The token ID that will be minted when calling the `mint` function.
|
|
19
|
+
uint256 public currentTokenId;
|
|
20
|
+
/// @dev Base URI that is used in the `tokenURI` function to form the start of the token URI.
|
|
21
|
+
string public baseURI;
|
|
22
|
+
/// @dev Total token supply, increased by minting and decreased by burning.
|
|
23
|
+
uint256 public totalSupply;
|
|
24
|
+
/// @dev Base extension that is used in the `tokenURI` function to form the end of the token URI.
|
|
25
|
+
string public baseExtension;
|
|
26
|
+
|
|
27
|
+
/// @dev Reverts if `msg.sender` is not the specified token's owner.
|
|
28
|
+
modifier onlyTokenOwner(uint256 tokenId) {
|
|
29
|
+
require(msg.sender == ownerOf(tokenId), "InverseBaseProjectedNft: not owner");
|
|
30
|
+
_;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/// @dev Sets the NFT's `name`, `symbol`, and transfers ownership to `owner`.
|
|
34
|
+
/// Also sets `currentTokenId` to 1 and `baseExtension` to `".json"`.
|
|
35
|
+
constructor(
|
|
36
|
+
string memory name,
|
|
37
|
+
string memory symbol,
|
|
38
|
+
address owner
|
|
39
|
+
) ERC721(name, symbol) Ownable(owner) {
|
|
40
|
+
currentTokenId = 1;
|
|
41
|
+
baseExtension = ".json";
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/// @dev Returns true if this contract implements the interface defined by `interfaceId`. See EIP165.
|
|
45
|
+
function supportsInterface(
|
|
46
|
+
bytes4 interfaceId
|
|
47
|
+
) public view virtual override(IERC165, ERC721) returns (bool) {
|
|
48
|
+
return
|
|
49
|
+
interfaceId == type(IInverseProjectedNft).interfaceId ||
|
|
50
|
+
interfaceId == type(IInverseBaseProjectedNft).interfaceId ||
|
|
51
|
+
interfaceId == bytes4(0x49064906) ||
|
|
52
|
+
super.supportsInterface(interfaceId);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/// @dev Mints a new token to address `_to`, passing `initialData` to be emitted in the event.
|
|
56
|
+
/// Increases the `totalSupply` and `currentTokenId`.
|
|
57
|
+
/// Reverts if `_to` is a zero address or if it refers to smart contract but does not implement IERC721Receiver-onERC721Received.
|
|
58
|
+
/// Emits the `Minted` event.
|
|
59
|
+
/// @param _to where to send the NFT to
|
|
60
|
+
/// @param initialData data that is emitted in the `Minted` event
|
|
61
|
+
/// @param data any additional data to pass to the receiver contract
|
|
62
|
+
/// @return id of the minted token
|
|
63
|
+
function mint(
|
|
64
|
+
address _to,
|
|
65
|
+
string calldata initialData,
|
|
66
|
+
bytes memory data
|
|
67
|
+
) public virtual returns (uint256) {
|
|
68
|
+
require(_to != address(0), "InverseBaseProjectedNft: zero receiver address");
|
|
69
|
+
|
|
70
|
+
uint256 tokenId = currentTokenId;
|
|
71
|
+
_safeMint(_to, tokenId, data);
|
|
72
|
+
|
|
73
|
+
totalSupply++;
|
|
74
|
+
currentTokenId++;
|
|
75
|
+
|
|
76
|
+
emit Minted(tokenId, initialData);
|
|
77
|
+
return tokenId;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/// @dev Shorthand function that calls the `mint` function with empty `data`.
|
|
81
|
+
function mint(address _to, string calldata initialData) public virtual returns (uint256) {
|
|
82
|
+
return mint(_to, initialData, bytes(""));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/// @dev Burns token of ID `_tokenId`. Callable only by the owner of the specified token.
|
|
86
|
+
/// Reverts if `_tokenId` does not exist.
|
|
87
|
+
function burn(uint256 _tokenId) public virtual onlyTokenOwner(_tokenId) {
|
|
88
|
+
totalSupply--;
|
|
89
|
+
_burn(_tokenId);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/// @dev Returns the `baseURI` of this NFT.
|
|
93
|
+
function _baseURI() internal view virtual override returns (string memory) {
|
|
94
|
+
return baseURI;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/// @dev Returns the token URI of specified `tokenId` using the default set base URI.
|
|
98
|
+
function tokenURI(
|
|
99
|
+
uint256 tokenId
|
|
100
|
+
) public view virtual override(ERC721, IERC721Metadata) returns (string memory) {
|
|
101
|
+
return tokenURI(tokenId, _baseURI());
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/// @dev Returns the token URI of specified `tokenId` using a custom base URI.
|
|
105
|
+
function tokenURI(
|
|
106
|
+
uint256 tokenId,
|
|
107
|
+
string memory customBaseUri
|
|
108
|
+
) public view virtual returns (string memory) {
|
|
109
|
+
_requireOwned(tokenId);
|
|
110
|
+
string memory URI = bytes(customBaseUri).length > 0
|
|
111
|
+
? string.concat(
|
|
112
|
+
customBaseUri,
|
|
113
|
+
"eip155:",
|
|
114
|
+
block.chainid.toString(),
|
|
115
|
+
"/",
|
|
116
|
+
tokenId.toString()
|
|
117
|
+
)
|
|
118
|
+
: "";
|
|
119
|
+
return string(abi.encodePacked(URI, baseExtension));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/// @dev Returns the token URI of specified `tokenId` using a call to contract implementing `ITokenUri`.
|
|
123
|
+
function tokenURI(
|
|
124
|
+
uint256 tokenId,
|
|
125
|
+
ITokenUri customUriInterface
|
|
126
|
+
) public view returns (string memory) {
|
|
127
|
+
return customUriInterface.tokenURI(tokenId);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/// @dev Sets `_URI` as the `baseURI` of the NFT.
|
|
131
|
+
/// Callable only by the contract owner.
|
|
132
|
+
/// Emits the `SetBaseURI` event.
|
|
133
|
+
function setBaseURI(string memory _URI) public virtual onlyOwner {
|
|
134
|
+
string memory oldURI = baseURI;
|
|
135
|
+
baseURI = _URI;
|
|
136
|
+
emit SetBaseURI(oldURI, _URI);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/// @dev Sets `_newBaseExtension` as the `baseExtension` of the NFT.
|
|
140
|
+
/// Callable only by the contract owner.
|
|
141
|
+
function setBaseExtension(string memory _newBaseExtension) public virtual onlyOwner {
|
|
142
|
+
string memory oldBaseExtension = baseExtension;
|
|
143
|
+
baseExtension = _newBaseExtension;
|
|
144
|
+
emit SetBaseURI(oldBaseExtension, _newBaseExtension);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/// @dev Function that emits an event to notify third-parties (e.g. NFT marketplaces) about
|
|
148
|
+
/// an update to consecutive range of tokens. Can be overridden in inheriting contract.
|
|
149
|
+
function updateMetadataBatch(uint256 _fromTokenId, uint256 _toTokenId) public virtual {
|
|
150
|
+
emit BatchMetadataUpdate(_fromTokenId, _toTokenId);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/// @dev Function that emits an event to notify third-parties (e.g. NFT marketplaces) about
|
|
154
|
+
/// an update to a single token. Can be overridden in inheriting contract.
|
|
155
|
+
function updateMetadata(uint256 _tokenId) public virtual {
|
|
156
|
+
emit MetadataUpdate(_tokenId);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// import type { HardhatRuntimeEnvironment } from 'hardhat/types';
|
|
2
|
+
// import { isAddress } from 'viem';
|
|
3
|
+
// import type { WalletClient } from 'viem';
|
|
4
|
+
// import { scope } from 'hardhat/config';
|
|
5
|
+
// import { createInterface } from 'node:readline/promises';
|
|
6
|
+
// import { stdin, stdout } from 'process';
|
|
7
|
+
|
|
8
|
+
// export const paimaScope = scope('paima', 'Paima Engine tasks');
|
|
9
|
+
|
|
10
|
+
// const rl = createInterface({ input: stdin, output: stdout });
|
|
11
|
+
|
|
12
|
+
// export async function getOrAskString(cmdLineValue: unknown, question: string): Promise<string> {
|
|
13
|
+
// if (cmdLineValue != null && typeof cmdLineValue !== 'string') {
|
|
14
|
+
// throw new Error(`Invalid type passed. Expected string: ${JSON.stringify(cmdLineValue)}`);
|
|
15
|
+
// }
|
|
16
|
+
// return cmdLineValue != null ? cmdLineValue : await rl.question(question);
|
|
17
|
+
// }
|
|
18
|
+
// export async function getContract(
|
|
19
|
+
// hre: HardhatRuntimeEnvironment,
|
|
20
|
+
// cmdLineAccount: unknown
|
|
21
|
+
// ): Promise<{ signer: WalletClient; account: `0x${string}` }> {
|
|
22
|
+
// const account = await getOrAskString(cmdLineAccount, 'Contract address? ');
|
|
23
|
+
// if (!isAddress(account)) {
|
|
24
|
+
// throw new Error(`Invalid contract address passed ${account}`);
|
|
25
|
+
// }
|
|
26
|
+
|
|
27
|
+
// const wallets = await hre.viem.getWalletClients();
|
|
28
|
+
|
|
29
|
+
// return { signer: wallets[0], account };
|
|
30
|
+
// }
|
|
31
|
+
// export function ownerCheck(expectedOwner: string, caller: string): void {
|
|
32
|
+
// if (expectedOwner !== caller) {
|
|
33
|
+
// throw new Error(`Owner mismatch. Expected ${expectedOwner}, but signer was ${caller}`);
|
|
34
|
+
// }
|
|
35
|
+
// }
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
// import { types } from "hardhat/config";
|
|
2
|
+
// import { listDeployments } from "@nomicfoundation/ignition-core";
|
|
3
|
+
// import * as path from "path";
|
|
4
|
+
// import * as fs from "fs";
|
|
5
|
+
// import { paimaScope } from "./common.js";
|
|
6
|
+
// import * as ts from "typescript";
|
|
7
|
+
// import * as dom from "dts-dom";
|
|
8
|
+
|
|
9
|
+
// paimaScope
|
|
10
|
+
// .task(
|
|
11
|
+
// "copy-ignition-deployment",
|
|
12
|
+
// `Copy the hardhat-ignition deployed addresses information to a target folder`,
|
|
13
|
+
// )
|
|
14
|
+
// .addParam(
|
|
15
|
+
// "rootDir",
|
|
16
|
+
// `Root directory of your hardhat-ignition project`,
|
|
17
|
+
// undefined,
|
|
18
|
+
// types.string,
|
|
19
|
+
// )
|
|
20
|
+
// .addParam(
|
|
21
|
+
// "outDir",
|
|
22
|
+
// `Build output directory to place deployment info`,
|
|
23
|
+
// undefined,
|
|
24
|
+
// types.string,
|
|
25
|
+
// )
|
|
26
|
+
// .setAction(async (taskArgs, hre) => {
|
|
27
|
+
// await copyDeployments(taskArgs.rootDir, taskArgs.outDir);
|
|
28
|
+
// });
|
|
29
|
+
// export async function copyDeployments(
|
|
30
|
+
// rootDir: string,
|
|
31
|
+
// outDir: string,
|
|
32
|
+
// ): Promise<void> {
|
|
33
|
+
// const deploymentDir = path.resolve(rootDir, "src", "ignition", "deployments");
|
|
34
|
+
// const deployments = await listDeployments(deploymentDir);
|
|
35
|
+
|
|
36
|
+
// const allDeployments: Record<string, Record<string, string>> = {};
|
|
37
|
+
// for (const deployment of deployments) {
|
|
38
|
+
// const deployedAddressesPath = path.join(
|
|
39
|
+
// deploymentDir,
|
|
40
|
+
// deployment,
|
|
41
|
+
// "deployed_addresses.json",
|
|
42
|
+
// );
|
|
43
|
+
// allDeployments[deployment] = JSON.parse(
|
|
44
|
+
// fs.readFileSync(deployedAddressesPath, "utf8"),
|
|
45
|
+
// );
|
|
46
|
+
// }
|
|
47
|
+
// const outputTs = `export default ${
|
|
48
|
+
// JSON.stringify(allDeployments, null, 2)
|
|
49
|
+
// } as const;`;
|
|
50
|
+
|
|
51
|
+
// const deploymentsOutput = path.join(outDir, "deployments");
|
|
52
|
+
// if (!fs.existsSync(deploymentsOutput)) {
|
|
53
|
+
// fs.mkdirSync(deploymentsOutput, { recursive: true });
|
|
54
|
+
// }
|
|
55
|
+
|
|
56
|
+
// // ESM file
|
|
57
|
+
// {
|
|
58
|
+
// const result = ts.transpileModule(outputTs, {
|
|
59
|
+
// compilerOptions: {
|
|
60
|
+
// module: ts.ModuleKind.ESNext, // ESM
|
|
61
|
+
// target: ts.ScriptTarget.ESNext,
|
|
62
|
+
// },
|
|
63
|
+
// });
|
|
64
|
+
// fs.writeFileSync(
|
|
65
|
+
// path.join(deploymentsOutput, `index.mjs`),
|
|
66
|
+
// result.outputText,
|
|
67
|
+
// { flag: "w" },
|
|
68
|
+
// );
|
|
69
|
+
// }
|
|
70
|
+
// // CJS file
|
|
71
|
+
// {
|
|
72
|
+
// const result = ts.transpileModule(outputTs, {
|
|
73
|
+
// compilerOptions: {
|
|
74
|
+
// module: ts.ModuleKind.NodeNext, // CJS
|
|
75
|
+
// target: ts.ScriptTarget.ESNext,
|
|
76
|
+
// },
|
|
77
|
+
// });
|
|
78
|
+
// fs.writeFileSync(
|
|
79
|
+
// path.join(deploymentsOutput, `index.cjs`),
|
|
80
|
+
// result.outputText,
|
|
81
|
+
// { flag: "w" },
|
|
82
|
+
// );
|
|
83
|
+
// }
|
|
84
|
+
// // DTS file
|
|
85
|
+
// {
|
|
86
|
+
// /**
|
|
87
|
+
// * I couldn't find a nice way to convert a TS file to a d.ts file in-memory using the official typescript compiler API
|
|
88
|
+
// * since all the standard ways require a bunch of ugly file system operations.
|
|
89
|
+
// *
|
|
90
|
+
// * I found two ways to get this to work properly:
|
|
91
|
+
// * 1. Use `ts-morph` which is a typescript compiler wrapper that does support in-memory operations
|
|
92
|
+
// * The problem is that it can block upgrading typescript since the ts-morph version needs to match your ts version
|
|
93
|
+
// * 2. Use `dts-dom` to manually construct the d.ts file as it's fairly simple
|
|
94
|
+
// *
|
|
95
|
+
// * I went with option 2
|
|
96
|
+
// */
|
|
97
|
+
|
|
98
|
+
// /**
|
|
99
|
+
// * This is the unused option (1) in case we ever end up needing it (ex: we need to do imports or other things not easily supported in dts-dom
|
|
100
|
+
// */
|
|
101
|
+
// // import tsMorph from 'ts-morph';
|
|
102
|
+
// //
|
|
103
|
+
// // const project = new tsMorph.Project({
|
|
104
|
+
// // useInMemoryFileSystem: true,
|
|
105
|
+
// // compilerOptions: {
|
|
106
|
+
// // module: tsMorph.ModuleKind.ESNext,
|
|
107
|
+
// // target: tsMorph.ScriptTarget.ESNext,
|
|
108
|
+
// // declaration: true,
|
|
109
|
+
// // },
|
|
110
|
+
// // });
|
|
111
|
+
// // const myClassFile = project.createSourceFile('deployment.ts', outputTs);
|
|
112
|
+
// // const emitResult = project.emitToMemory({ emitOnlyDtsFiles: true });
|
|
113
|
+
// // const declaration = emitResult.getFiles()[0].text;
|
|
114
|
+
// // fs.writeFileSync(path.join(deploymentsOutput, `index.d.ts`), declaration, { flag: 'w' });
|
|
115
|
+
|
|
116
|
+
// const changeCase = await import("change-case"); // async import since it's an ESM module, and Hardhat only supports CJS
|
|
117
|
+
// const file: string[] = [];
|
|
118
|
+
|
|
119
|
+
// const genType = (name: string, properties: dom.PropertyDeclaration[]) => {
|
|
120
|
+
// const type = dom.create.objectType(properties);
|
|
121
|
+
// const alias = dom.create.alias(changeCase.pascalCase(name), type);
|
|
122
|
+
|
|
123
|
+
// return alias;
|
|
124
|
+
// };
|
|
125
|
+
// const topLevelProperties: dom.PropertyDeclaration[] = [];
|
|
126
|
+
// for (const [deploymentName, contracts] of Object.entries(allDeployments)) {
|
|
127
|
+
// const type = genType(
|
|
128
|
+
// changeCase.pascalCase(deploymentName),
|
|
129
|
+
// Object.entries(contracts).map(
|
|
130
|
+
// ([contractName, contractAddress]) =>
|
|
131
|
+
// dom.create.property(
|
|
132
|
+
// contractName,
|
|
133
|
+
// dom.type.stringLiteral(contractAddress),
|
|
134
|
+
// ),
|
|
135
|
+
// ),
|
|
136
|
+
// );
|
|
137
|
+
// file.push(dom.emit(type));
|
|
138
|
+
// topLevelProperties.push(dom.create.property(deploymentName, type));
|
|
139
|
+
// }
|
|
140
|
+
// const topLevelType = genType(
|
|
141
|
+
// "DeployedContracts",
|
|
142
|
+
// topLevelProperties,
|
|
143
|
+
// );
|
|
144
|
+
// file.push(dom.emit(topLevelType));
|
|
145
|
+
|
|
146
|
+
// const topLevelConst = dom.create.const("_default", topLevelType);
|
|
147
|
+
// file.push(dom.emit(topLevelConst));
|
|
148
|
+
// const defaultExport = dom.create.exportDefault(topLevelConst.name);
|
|
149
|
+
// file.push(dom.emit(defaultExport));
|
|
150
|
+
// const dtsContent = file.join("\n");
|
|
151
|
+
|
|
152
|
+
// fs.writeFileSync(path.join(deploymentsOutput, `index.d.ts`), dtsContent, {
|
|
153
|
+
// flag: "w",
|
|
154
|
+
// });
|
|
155
|
+
// }
|
|
156
|
+
// }
|
|
157
|
+
|
|
158
|
+
// let name = dom.create.property("name", dom.type.string);
|
|
159
|
+
// let age = dom.create.property("age", dom.type.number);
|
|
160
|
+
// let type = dom.create.objectType([name, age]);
|
|
161
|
+
// let typeBase = dom.create.alias("typeBase", type);
|