@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.
Files changed (79) hide show
  1. package/README.md +7 -0
  2. package/deno.json +28 -0
  3. package/docs/templates/contract.hbs +144 -0
  4. package/docs/templates/helpers.js +61 -0
  5. package/docs/templates/page.hbs +7 -0
  6. package/docs/templates/properties.js +76 -0
  7. package/hardhat.config.ts +11 -0
  8. package/index.js +1 -0
  9. package/mod.ts +0 -0
  10. package/package.json +13 -0
  11. package/remappings.txt +1 -0
  12. package/src/companions/ERC165Contract.json +21 -0
  13. package/src/companions/ERC165Contract.ts +21 -0
  14. package/src/companions/ERC20Contract.json +222 -0
  15. package/src/companions/ERC20Contract.ts +222 -0
  16. package/src/companions/ERC6551RegistryContract.json +128 -0
  17. package/src/companions/ERC6551RegistryContract.ts +128 -0
  18. package/src/companions/ERC721Contract.json +248 -0
  19. package/src/companions/ERC721Contract.ts +222 -0
  20. package/src/companions/IERC1155Contract.json +295 -0
  21. package/src/companions/IERC1155Contract.ts +295 -0
  22. package/src/companions/OldERC6551RegistryContract.json +133 -0
  23. package/src/companions/OldERC6551RegistryContract.ts +133 -0
  24. package/src/companions/PaimaERC721Contract.json +787 -0
  25. package/src/companions/PaimaERC721Contract.ts +787 -0
  26. package/src/companions/PaimaL2Contract.json +134 -0
  27. package/src/companions/PaimaL2Contract.ts +134 -0
  28. package/src/companions/README.md +5 -0
  29. package/src/contracts/AnnotatedMintNft.sol +171 -0
  30. package/src/contracts/BaseState.sol +16 -0
  31. package/src/contracts/ERC1967.sol +43 -0
  32. package/src/contracts/Erc20NftSale.sol +186 -0
  33. package/src/contracts/GenericPayment.sol +60 -0
  34. package/src/contracts/NativeNftSale.sol +97 -0
  35. package/src/contracts/PaimaL2Contract.sol +54 -0
  36. package/src/contracts/Proxy/Erc20NftSaleProxy.sol +79 -0
  37. package/src/contracts/Proxy/GenericPaymentProxy.sol +64 -0
  38. package/src/contracts/Proxy/NativeNftSaleProxy.sol +72 -0
  39. package/src/contracts/Proxy/OrderbookDexProxy.sol +27 -0
  40. package/src/contracts/README.md +72 -0
  41. package/src/contracts/State.sol +25 -0
  42. package/src/contracts/dev/ERC721Dev.sol +13 -0
  43. package/src/contracts/dev/Erc20Dev.sol +13 -0
  44. package/src/contracts/dev/NativeNftSaleUpgradeDev.sol +9 -0
  45. package/src/contracts/dev/NftSaleUpgradeDev.sol +12 -0
  46. package/src/contracts/dev/NftTypeMapper.sol +38 -0
  47. package/src/contracts/dev/Token.sol +15 -0
  48. package/src/contracts/dev/UpgradeDev.sol +10 -0
  49. package/src/contracts/orderbook/IOrderbookDex.sol +215 -0
  50. package/src/contracts/orderbook/OrderbookDex.sol +435 -0
  51. package/src/contracts/token/IERC4906Agnostic.sol +17 -0
  52. package/src/contracts/token/IInverseAppProjected1155.sol +40 -0
  53. package/src/contracts/token/IInverseAppProjectedNft.sol +38 -0
  54. package/src/contracts/token/IInverseBaseProjected1155.sol +25 -0
  55. package/src/contracts/token/IInverseBaseProjectedNft.sol +29 -0
  56. package/src/contracts/token/IInverseProjected1155.sol +38 -0
  57. package/src/contracts/token/IInverseProjectedNft.sol +41 -0
  58. package/src/contracts/token/ITokenUri.sol +10 -0
  59. package/src/contracts/token/IUri.sol +13 -0
  60. package/src/contracts/token/InverseAppProjected1155.sol +218 -0
  61. package/src/contracts/token/InverseAppProjectedNft.sol +192 -0
  62. package/src/contracts/token/InverseBaseProjected1155.sol +170 -0
  63. package/src/contracts/token/InverseBaseProjectedNft.sol +158 -0
  64. package/src/plugin/common.ts +35 -0
  65. package/src/plugin/deployment.ts +161 -0
  66. package/src/plugin/mod.ts +6 -0
  67. package/src/plugin/paimaL2.ts +202 -0
  68. package/src/recommendedHardhat.ts +86 -0
  69. package/test/lib/StdInvariant.sol +96 -0
  70. package/test/lib/cheatcodes.sol +89 -0
  71. package/test/lib/console.sol +1884 -0
  72. package/test/lib/ctest.sol +678 -0
  73. package/test/src/InverseAppProjected1155.t.sol +207 -0
  74. package/test/src/InverseAppProjectedNft.t.sol +164 -0
  75. package/test/src/InverseBaseProjected1155.t.sol +171 -0
  76. package/test/src/InverseBaseProjectedNft.t.sol +141 -0
  77. package/test/src/OrderbookDex.t.sol +710 -0
  78. package/test/src/OrderbookDexInvariant.t.sol +426 -0
  79. package/test/src/PaimaL2ContractTest.sol +115 -0
@@ -0,0 +1,60 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "./ERC1967.sol";
6
+
7
+ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
8
+ import "@openzeppelin/contracts/utils/Address.sol";
9
+
10
+ /// @dev Facilitates accepting payment that accepts extra data to know what the payment was for inside a Paima dApp.
11
+ contract GenericPayment is ERC1967, OwnableUpgradeable {
12
+ /// @dev True if contract has been initialized via the `initialize` function.
13
+ bool public initialized;
14
+
15
+ using Address for address payable;
16
+
17
+ /// @dev Emitted when the contract is initialized.
18
+ event Initialized(address indexed owner);
19
+
20
+ /// @dev Emitted when payment of `amount` if made by `payer` with `message`.
21
+ event Pay(uint256 amount, address payer, string message);
22
+
23
+ /// @custom:oz-upgrades-unsafe-allow constructor
24
+ constructor() {
25
+ _disableInitializers();
26
+ }
27
+
28
+ /// @dev Initializes the contracts, transferring ownership to the specified `owner`.
29
+ /// Callable only once.
30
+ /// Emits the `Initialized` event.
31
+ function initialize(address owner) public initializer {
32
+ require(!initialized, "Contract already initialized");
33
+ initialized = true;
34
+
35
+ __Ownable_init(owner);
36
+
37
+ emit Initialized(owner);
38
+ }
39
+
40
+ /// @dev Transfers native tokens to the contract, providing `message`.
41
+ /// Emits the `Pay` event.
42
+ function pay(string calldata message) external payable {
43
+ emit Pay(msg.value, msg.sender, message);
44
+ }
45
+
46
+ /// @dev Withdraws the contract balance to `_account`.
47
+ /// Callable only by the contract owner.
48
+ function withdraw(address payable _account) external onlyOwner {
49
+ uint256 balance = address(this).balance;
50
+
51
+ require(balance > 0, "GenericPayment: 0 balance");
52
+ _account.sendValue(balance);
53
+ }
54
+
55
+ /// @dev Upgrades the contract implementation to `_newContract`.
56
+ /// Callable only by the contract owner.
57
+ function upgradeContract(address _newContract) external onlyOwner {
58
+ _setImplementation(_newContract);
59
+ }
60
+ }
@@ -0,0 +1,97 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "./AnnotatedMintNft.sol";
6
+ import "./BaseState.sol";
7
+ import "./ERC1967.sol";
8
+
9
+ import {OwnableUpgradeable} from "@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol";
10
+ import "@openzeppelin/contracts/utils/Address.sol";
11
+
12
+ /// @dev Facilitates selling NFTs that accepts extra data when buying for any initialization data needed in a Paima dApp.
13
+ contract NativeNftSale is BaseState, ERC1967, OwnableUpgradeable {
14
+ using Address for address payable;
15
+
16
+ /// @dev Emitted when the contract is initialized.
17
+ event Initialized(address indexed owner, address indexed nft);
18
+
19
+ /// @dev Emitted when the NFT price is updated from `oldPrice` to `newPrice`.
20
+ event UpdatePrice(uint256 indexed oldPrice, uint256 indexed newPrice);
21
+
22
+ /// @dev Emitted when an NFT of `tokenId` is minted to `receiver` by `buyer` paying `PRICE` in native tokens.
23
+ event BuyNFT(
24
+ uint256 indexed tokenId,
25
+ uint256 indexed PRICE,
26
+ address indexed receiver,
27
+ address buyer
28
+ );
29
+
30
+ /// @custom:oz-upgrades-unsafe-allow constructor
31
+ constructor() {
32
+ _disableInitializers();
33
+ }
34
+
35
+ /// @dev Initializes the contract with the requested price `_price` in native tokens for specified NFT `_nft`,
36
+ /// transferring ownership to the specified `owner`.
37
+ /// Callable only once.
38
+ /// Emits the `Initialized` event.
39
+ function initialize(address owner, address _nft, uint256 _price) public virtual initializer {
40
+ require(!initialized, "Contract already initialized");
41
+ initialized = true;
42
+
43
+ nftPrice = _price;
44
+ nftAddress = _nft;
45
+ __Ownable_init(owner);
46
+
47
+ emit Initialized(owner, _nft);
48
+ }
49
+
50
+ /// @dev Purchases NFT for address `receiverAddress`, paying required price in native token.
51
+ /// This function calls the `mint` function on the `AnnotatedMintNft` contract, passing provided `initialData`.
52
+ /// Emits the `BuyNFT` event.
53
+ function buyNft(
54
+ address receiverAddress,
55
+ // not calldata to allow other contracts to wrap this and change what is bought with their own logic
56
+ string memory initialData
57
+ ) public payable returns (uint256) {
58
+ require(msg.value == nftPrice, "NativeNftSale: incorrect value");
59
+ require(receiverAddress != address(0), "NativeNftSale: zero receiver address");
60
+
61
+ uint256 price = nftPrice;
62
+
63
+ uint256 tokenId = AnnotatedMintNft(nftAddress).mint(receiverAddress, initialData);
64
+
65
+ emit BuyNFT(tokenId, price, receiverAddress, msg.sender);
66
+
67
+ return tokenId;
68
+ }
69
+
70
+ /// @dev Changes the sale price to `_nftPrice`.
71
+ /// Callable only by the contract owner.
72
+ /// Emits the `UpdatePrice` event.
73
+ function updatePrice(uint256 _nftPrice) external onlyOwner {
74
+ uint256 oldPrice = nftPrice;
75
+ nftPrice = _nftPrice;
76
+
77
+ emit UpdatePrice(oldPrice, _nftPrice);
78
+ }
79
+
80
+ /// @dev Withdraws the contract balance to `_account`.
81
+ /// Callable only by the contract owner.
82
+ function withdraw(address payable _account) external onlyOwner {
83
+ uint256 balance = address(this).balance;
84
+
85
+ require(balance > 0, "NativeNftSale: 0 balance");
86
+ _account.sendValue(balance);
87
+ }
88
+
89
+ /// @dev Upgrades the contract implementation to `_newContract`.
90
+ /// Callable only by the contract owner.
91
+ function upgradeContract(address _newContract) external onlyOwner {
92
+ _setImplementation(_newContract);
93
+ }
94
+
95
+ /// @dev Function allowing the contract to receive native tokens.
96
+ receive() external payable {}
97
+ }
@@ -0,0 +1,54 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import "@openzeppelin/contracts/utils/Address.sol";
5
+
6
+ /// @dev The main L2 contract for a Paima L2.
7
+ contract PaimaL2Contract {
8
+ using Address for address payable;
9
+
10
+ /// @dev Emitted when `paimaSubmitGameInput` function is called with `data`.
11
+ /// `userAddress` is the transaction sender and `value` is the transaction value.
12
+ event PaimaGameInteraction(address indexed userAddress, bytes data, uint256 value);
13
+
14
+ /// @dev Contract owner.
15
+ address public owner;
16
+ /// @dev Amount in wei that is required to be paid when calling `paimaSubmitGameInput`.
17
+ uint256 public fee; // in wei
18
+
19
+ /// @dev Sets the contract owner to `_owner` and payment fee to `_fee`.
20
+ constructor(address _owner, uint256 _fee) {
21
+ owner = _owner;
22
+ fee = _fee;
23
+ }
24
+
25
+ /// @dev Emits the `PaimaGameInteraction` event, logging the `msg.sender`, `data`, and `msg.value`.
26
+ /// Revert if `msg.value` is less than set `fee`.
27
+ function paimaSubmitGameInput(bytes calldata data) public payable {
28
+ require(msg.value >= fee, "Sufficient funds required to submit game input");
29
+ emit PaimaGameInteraction(msg.sender, data, msg.value);
30
+ }
31
+
32
+ /// @dev Withdraws the contract balance to the `owner`.
33
+ /// Callable only by the contract owner.
34
+ function withdrawFunds() public {
35
+ require(msg.sender == owner, "Only owner can withdraw funds");
36
+ address payable to = payable(owner);
37
+ uint256 balance = address(this).balance;
38
+ to.sendValue(balance);
39
+ }
40
+
41
+ /// @dev Sets the `newOwner` as the contract owner.
42
+ /// Callable only by the contract owner.
43
+ function setOwner(address newOwner) public {
44
+ require(msg.sender == owner, "Only owner can change owner");
45
+ owner = newOwner;
46
+ }
47
+
48
+ /// @dev Sets the `newFee` as the required payment fee.
49
+ /// Callable only by the contract owner.
50
+ function setFee(uint256 newFee) public {
51
+ require(msg.sender == owner, "Only owner can change fee");
52
+ fee = newFee;
53
+ }
54
+ }
@@ -0,0 +1,79 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "../ERC1967.sol";
6
+
7
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
8
+ import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
9
+
10
+ /// @title Proxy
11
+ /// @dev Proxy contract mostly based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Proxy.sol
12
+ contract Erc20NftSaleProxy is ERC1967 {
13
+ /// @dev Sets `implementation` address and calls the `Erc20NftSale.initialize` function with the parameters
14
+ /// `currencies`, `owner`, `nftAddress`, `nftPrice`.
15
+ constructor(
16
+ address implementation,
17
+ ERC20[] memory currencies,
18
+ address owner,
19
+ address nftAddress,
20
+ uint256 nftPrice
21
+ ) {
22
+ _assertCorrectImplementationSlot();
23
+ _setImplementation(implementation);
24
+
25
+ bytes memory data = abi.encodeWithSignature(
26
+ "initialize(address[],address,address,uint256)",
27
+ currencies,
28
+ owner,
29
+ nftAddress,
30
+ nftPrice
31
+ );
32
+ (bool success, ) = implementation.delegatecall(data);
33
+ require(success, "Initialization unsuccessful");
34
+ }
35
+
36
+ /// @dev Delegates the current call to `implementation`.
37
+ /// This function does not return to its internal call site, it will return
38
+ /// directly to the external caller.
39
+ function _delegate(address target) internal {
40
+ assembly {
41
+ // Copy msg.data. We take full control of memory in this inline assembly
42
+ // block because it will not return to Solidity code. We overwrite the
43
+ // Solidity scratch pad at memory position 0.
44
+ calldatacopy(0, 0, calldatasize())
45
+
46
+ // Call the implementation.
47
+ // out and outsize are 0 because we don't know the size yet.
48
+ let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)
49
+
50
+ // Copy the returned data.
51
+ returndatacopy(0, 0, returndatasize())
52
+
53
+ switch result
54
+ // delegatecall returns 0 on error.
55
+ case 0 {
56
+ revert(0, returndatasize())
57
+ }
58
+ default {
59
+ return(0, returndatasize())
60
+ }
61
+ }
62
+ }
63
+
64
+ /// @dev Delegates the current call to the address returned by `_implementation()`.
65
+ /// This function does not return to its internal call site, it will return
66
+ /// directly to the external caller.
67
+ function _fallback() internal {
68
+ _delegate(_getImplementation());
69
+ }
70
+
71
+ /// @dev Fallback function that delegates calls to the address returned by `_implementation()`.
72
+ /// Will run if no other function in the contract matches the call data.
73
+ fallback() external payable {
74
+ _fallback();
75
+ }
76
+
77
+ /// @dev Called if this contract is receiving native tokens and `msg.data` is empty
78
+ receive() external payable {}
79
+ }
@@ -0,0 +1,64 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "../ERC1967.sol";
6
+
7
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
8
+ import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
9
+
10
+ /// @title Proxy
11
+ /// @dev Proxy contract mostly based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Proxy.sol
12
+ contract GenericPaymentProxy is ERC1967 {
13
+ /// @dev Sets `implementation` address and calls the `GenericPayment.initialize` function with the parameter
14
+ /// `owner`.
15
+ constructor(address implementation, address owner) {
16
+ _assertCorrectImplementationSlot();
17
+ _setImplementation(implementation);
18
+
19
+ bytes memory data = abi.encodeWithSignature("initialize(address)", owner);
20
+ (bool success, ) = implementation.delegatecall(data);
21
+ require(success, "Initialization unsuccessful");
22
+ }
23
+
24
+ /// @dev Delegates the current call to `implementation`.
25
+ /// This function does not return to its internal call site, it will return
26
+ /// directly to the external caller.
27
+ function _delegate(address target) internal {
28
+ assembly {
29
+ // Copy msg.data. We take full control of memory in this inline assembly
30
+ // block because it will not return to Solidity code. We overwrite the
31
+ // Solidity scratch pad at memory position 0.
32
+ calldatacopy(0, 0, calldatasize())
33
+
34
+ // Call the implementation.
35
+ // out and outsize are 0 because we don't know the size yet.
36
+ let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)
37
+
38
+ // Copy the returned data.
39
+ returndatacopy(0, 0, returndatasize())
40
+
41
+ switch result
42
+ // delegatecall returns 0 on error.
43
+ case 0 {
44
+ revert(0, returndatasize())
45
+ }
46
+ default {
47
+ return(0, returndatasize())
48
+ }
49
+ }
50
+ }
51
+
52
+ /// @dev Delegates the current call to the address returned by `_implementation()`.
53
+ /// This function does not return to its internal call site, it will return
54
+ /// directly to the external caller.
55
+ function _fallback() internal {
56
+ _delegate(_getImplementation());
57
+ }
58
+
59
+ /// @dev Fallback function that delegates calls to the address returned by `_implementation()`.
60
+ /// Will run if no other function in the contract matches the call data.
61
+ fallback() external payable {
62
+ _fallback();
63
+ }
64
+ }
@@ -0,0 +1,72 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "../ERC1967.sol";
6
+
7
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
8
+ import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
9
+
10
+ /// @title Proxy
11
+ /// @dev Proxy contract mostly based on https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Proxy.sol
12
+ contract NativeNftSaleProxy is ERC1967 {
13
+ /// @dev Sets `implementation` address and calls the `NativeNftSale.initialize` function with the parameters
14
+ /// `owner`, `nftAddress`, `nftPrice`.
15
+ constructor(address implementation, address owner, address nftAddress, uint256 nftPrice) {
16
+ _assertCorrectImplementationSlot();
17
+ _setImplementation(implementation);
18
+
19
+ bytes memory data = abi.encodeWithSignature(
20
+ "initialize(address,address,uint256)",
21
+ owner,
22
+ nftAddress,
23
+ nftPrice
24
+ );
25
+ (bool success, ) = implementation.delegatecall(data);
26
+ require(success, "Initialization unsuccessful");
27
+ }
28
+
29
+ /// @dev Delegates the current call to `implementation`.
30
+ /// This function does not return to its internal call site, it will return
31
+ /// directly to the external caller.
32
+ function _delegate(address target) internal {
33
+ assembly {
34
+ // Copy msg.data. We take full control of memory in this inline assembly
35
+ // block because it will not return to Solidity code. We overwrite the
36
+ // Solidity scratch pad at memory position 0.
37
+ calldatacopy(0, 0, calldatasize())
38
+
39
+ // Call the implementation.
40
+ // out and outsize are 0 because we don't know the size yet.
41
+ let result := delegatecall(gas(), target, 0, calldatasize(), 0, 0)
42
+
43
+ // Copy the returned data.
44
+ returndatacopy(0, 0, returndatasize())
45
+
46
+ switch result
47
+ // delegatecall returns 0 on error.
48
+ case 0 {
49
+ revert(0, returndatasize())
50
+ }
51
+ default {
52
+ return(0, returndatasize())
53
+ }
54
+ }
55
+ }
56
+
57
+ /// @dev Delegates the current call to the address returned by `_implementation()`.
58
+ /// This function does not return to its internal call site, it will return
59
+ /// directly to the external caller.
60
+ function _fallback() internal {
61
+ _delegate(_getImplementation());
62
+ }
63
+
64
+ /// @dev Fallback function that delegates calls to the address returned by `_implementation()`.
65
+ /// Will run if no other function in the contract matches the call data.
66
+ fallback() external payable {
67
+ _fallback();
68
+ }
69
+
70
+ /// @dev Called if this contract is receiving native tokens and `msg.data` is empty
71
+ receive() external payable {}
72
+ }
@@ -0,0 +1,27 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
6
+
7
+ /// @title Proxy contract for OrderbookDex
8
+ contract OrderbookDexProxy is ERC1967Proxy {
9
+ constructor(
10
+ address _implementation,
11
+ address _owner,
12
+ uint256 _defaultMakerFee,
13
+ uint256 _defaultTakerFee,
14
+ uint256 _orderCreationFee
15
+ )
16
+ ERC1967Proxy(
17
+ _implementation,
18
+ abi.encodeWithSignature(
19
+ "initialize(address,uint256,uint256,uint256)",
20
+ _owner,
21
+ _defaultMakerFee,
22
+ _defaultTakerFee,
23
+ _orderCreationFee
24
+ )
25
+ )
26
+ {}
27
+ }
@@ -0,0 +1,72 @@
1
+ # Solidity Contracts
2
+
3
+ Solidity contracts provided as part of Paima Engine.
4
+
5
+ Core contracts
6
+
7
+ <ul>
8
+ <li>[PaimaL2Contract](#PaimaL2Contract): The main L2 contract for a Paima L2.</li>
9
+ </ul>
10
+ State-annotated contracts
11
+ <ul>
12
+ <li>[AnnotatedMintNft](#AnnotatedMintNft): A standard ERC721 that accepts calldata in the mint function for any initialization data needed in a Paima dApp.</li>
13
+ <li>[InverseBaseProjectedNft](#InverseBaseProjectedNft): Project game state into a ERC721 NFT on an EVM layer initiated on said base layer.</li>
14
+ <li>[InverseAppProjectedNft](#InverseAppProjectedNft): Project game state into a ERC721 NFT on an EVM layer initiated on the app layer.</li>
15
+ <li>[InverseBaseProjected1155](#InverseBaseProjected1155): Project game state into a ERC1155 on an EVM layer initiated on said base layer.</li>
16
+ <li>[InverseAppProjected1155](#InverseAppProjected1155): Project game state into a ERC1155 on an EVM layer initiated on the app layer.</li>
17
+ </ul>
18
+ Facilitating monetization
19
+ <ul>
20
+ <li>[NativeNftSale](#NativeNftSale): Facilitates selling NFTs that accepts extra data when buying for any initialization data needed in a Paima dApp.</li>
21
+ <li>[GenericPayment](#GenericPayment): Facilitates accepting payment that accepts extra data to know what the payment was for inside a Paima dApp.</li>
22
+ <li>[Erc20NftSale](#Erc20NftSale): Facilitates selling NFTs for specific ERC20s that accepts extra data when buying for any initialization data needed in a Paima dApp.</li>
23
+ <li>[OrderbookDexProxy](#OrderbookDexProxy): Proxy for the orderbook DEX contract.</li>
24
+ <li>[IOrderbookDex](#IOrderbookDex): Interface to facilitate trading inverse projected ERC1155 tokens.</li>
25
+ <li>[OrderbookDex](#OrderbookDex): Facilitates trading inverse projected ERC1155 tokens.</li>
26
+ </ul>
27
+
28
+ ## Core contracts
29
+
30
+ {{PaimaL2Contract}}
31
+
32
+ ## State-annotated contracts
33
+
34
+ {{AnnotatedMintNft}}
35
+
36
+ {{IInverseProjectedNft}} {{IInverseBaseProjectedNft}}
37
+ {{InverseBaseProjectedNft}} {{IInverseAppProjectedNft}}
38
+ {{InverseAppProjectedNft}}
39
+
40
+ {{IInverseProjected1155}} {{IInverseBaseProjected1155}}
41
+ {{InverseBaseProjected1155}} {{IInverseAppProjected1155}}
42
+ {{InverseAppProjected1155}}
43
+
44
+ ## Facilitating monetization
45
+
46
+ {{NativeNftSale}}
47
+
48
+ {{GenericPayment}}
49
+
50
+ {{Erc20NftSale}}
51
+
52
+ {{OrderbookDexProxy}}
53
+
54
+ {{IOrderbookDex}}
55
+
56
+ {{OrderbookDex}}
57
+
58
+ ## Utilities
59
+
60
+ {{BaseState}}
61
+
62
+ {{State}}
63
+
64
+ {{IERC4906Agnostic}} {{ERC1967}}
65
+
66
+ {{IUri}} {{ITokenUri}}
67
+
68
+ {{NativeNftSaleProxy}}
69
+
70
+ {{GenericPaymentProxy}}
71
+
72
+ {{Erc20NftSaleProxy}}
@@ -0,0 +1,25 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6
+
7
+ contract State {
8
+ /// @dev Required payment for the NFT in sale.
9
+ uint256 public nftPrice;
10
+
11
+ /// @dev True if contract has been initialized via `initialize` function.
12
+ bool public initialized;
13
+
14
+ /// @dev Address of the NFT for sale.
15
+ address public nftAddress;
16
+
17
+ /// @dev Array of addresses of tokens that have been deposited to the contract via NFT sales.
18
+ ERC20[] public depositedCurrencies;
19
+
20
+ /// @dev Mapping that returns true for address of token that has been deposited to the contract via NFT sale.
21
+ mapping(ERC20 => bool) public depositedCurrenciesMap;
22
+
23
+ /// @dev Array of addresses of tokens that are accepted as payment for the NFT sale.
24
+ ERC20[] public supportedCurrencies;
25
+ }
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol";
6
+
7
+ contract Erc721Dev is ERC721 {
8
+ constructor() ERC721("Mock ERC721", "MERC") {}
9
+
10
+ function mint(address _to, uint256 _tokenId) external {
11
+ _mint(_to, _tokenId);
12
+ }
13
+ }
@@ -0,0 +1,13 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6
+
7
+ contract Erc20Dev is ERC20 {
8
+ constructor() ERC20("Mock ERC20", "MERC") {}
9
+
10
+ function mint(address _to, uint256 _amount) external {
11
+ _mint(_to, _amount);
12
+ }
13
+ }
@@ -0,0 +1,9 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "../NativeNftSale.sol";
6
+ import "./UpgradeDev.sol";
7
+
8
+ /// @dev For testing upgradeability.
9
+ contract NativeNftSaleUpgradeDev is UpgradeDev, NativeNftSale {}
@@ -0,0 +1,12 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "../Erc20NftSale.sol";
6
+
7
+ /// @dev For testing upgradeability.
8
+ contract NftSaleUpgradeDev is Erc20NftSale {
9
+ function version() public pure returns (uint8) {
10
+ return 2;
11
+ }
12
+ }
@@ -0,0 +1,38 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import "../NativeNftSale.sol";
6
+
7
+ enum NftType {
8
+ FIRE,
9
+ WATER
10
+ }
11
+
12
+ contract NftTypeMapper {
13
+ mapping(NftType => string) internal nftTypeToString;
14
+
15
+ constructor() {
16
+ nftTypeToString[NftType.FIRE] = "fire";
17
+ nftTypeToString[NftType.WATER] = "water";
18
+ }
19
+
20
+ function getNftTypeString(NftType nftType) external view returns (string memory) {
21
+ return nftTypeToString[nftType];
22
+ }
23
+ }
24
+
25
+ contract TypedNativeNftSale is NativeNftSale {
26
+ NftTypeMapper public typeMapper;
27
+
28
+ function initialize(address owner, address _nft, uint256 _price) public override {
29
+ require(!initialized, "Contract already initialized");
30
+ // initialize state here first since parent constructor emits event
31
+ typeMapper = new NftTypeMapper();
32
+ super.initialize(owner, _nft, _price);
33
+ }
34
+
35
+ function buyNftType(address receiverAddress, NftType nftType) public payable returns (uint256) {
36
+ return super.buyNft(receiverAddress, typeMapper.getNftTypeString(nftType));
37
+ }
38
+ }
@@ -0,0 +1,15 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
6
+
7
+ contract Token is ERC20 {
8
+ constructor(string memory name, string memory symbol) ERC20(name, symbol) {
9
+ _mint(msg.sender, 10000000e18);
10
+ }
11
+
12
+ function mint(address _to, uint256 _amount) external {
13
+ _mint(_to, _amount);
14
+ }
15
+ }
@@ -0,0 +1,10 @@
1
+ // SPDX-License-Identifier: MIT
2
+
3
+ pragma solidity ^0.8.20;
4
+
5
+ /// @dev For testing upgradeability.
6
+ contract UpgradeDev {
7
+ function version() public pure returns (uint8) {
8
+ return 2;
9
+ }
10
+ }