polkamarkets-js 3.4.3 → 3.4.4
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/abis/AccessControlUpgradeable.json +1 -0
- package/abis/ERC165Upgradeable.json +1 -0
- package/abis/Hashes.json +1 -0
- package/abis/Math.json +1 -1
- package/abis/MerkleProof.json +1 -0
- package/abis/MerkleRewardsDistributor.json +1 -0
- package/abis/MerkleRewardsDistributorTest.json +1 -0
- package/abis/Panic.json +1 -0
- package/abis/SafeCast.json +1 -0
- package/abis/SignedMath.json +1 -0
- package/abis/Strings.json +1 -1
- package/contracts/MerkleRewardsDistributor.sol +194 -0
- package/package.json +1 -1
- package/scripts/UpdateMarket.s.sol +55 -0
- package/src/Application.js +16 -0
- package/src/interfaces/index.js +1 -0
- package/src/models/IContract.js +14 -0
- package/src/models/MerkleRewardsDistributorContract.js +107 -0
- package/src/models/index.js +3 -1
- package/test/MerkleRewardsDistributor.t.sol +316 -0
- package/script/UpdateMarket.s.sol +0 -55
- /package/abis/{test.json → Test.json} +0 -0
- /package/{script → scripts}/AddAdminToLand.s.sol +0 -0
- /package/{script → scripts}/ClaimMerkleRoot.s.sol +0 -0
- /package/{script → scripts}/CreateLand.s.sol +0 -0
- /package/{script → scripts}/CreateMarkets.s.sol +0 -0
- /package/{script → scripts}/DeployContracts.s.sol +0 -0
- /package/{script → scripts}/DeployMerkleRewardsDistributor.s.sol +0 -0
- /package/{script → scripts}/DeployToken.s.sol +0 -0
- /package/{script → scripts}/DeployUSDT.s.sol +0 -0
- /package/{script → scripts}/MintTokens.s.sol +0 -0
- /package/{script → scripts}/PublishMerkleRoot.s.sol +0 -0
- /package/{script → scripts}/ResolveMarket.s.sol +0 -0
- /package/{script → scripts}/TradeMarket.s.sol +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]}]}
|
package/abis/Hashes.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[]}
|
package/abis/Math.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"abi":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[{"type":"error","name":"MerkleProofInvalidMultiproof","inputs":[]}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"UPGRADE_INTERFACE_VERSION","inputs":[],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addAdmin","inputs":[{"name":"user","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claim","inputs":[{"name":"contestId","type":"string","internalType":"string"},{"name":"token","type":"address","internalType":"contract IERC20"},{"name":"index","type":"uint256","internalType":"uint256"},{"name":"user","type":"address","internalType":"address"},{"name":"amount","type":"uint256","internalType":"uint256"},{"name":"merkleProof","type":"bytes32[]","internalType":"bytes32[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"claimMany","inputs":[{"name":"contestIds","type":"string[]","internalType":"string[]"},{"name":"tokens","type":"address[]","internalType":"contract IERC20[]"},{"name":"indices","type":"uint256[]","internalType":"uint256[]"},{"name":"users","type":"address[]","internalType":"address[]"},{"name":"amounts","type":"uint256[]","internalType":"uint256[]"},{"name":"merkleProofs","type":"bytes32[][]","internalType":"bytes32[][]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoot","inputs":[{"name":"contestId","type":"string","internalType":"string"},{"name":"token","type":"address","internalType":"contract IERC20"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"initialize","inputs":[{"name":"initialOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"isAdmin","inputs":[{"name":"user","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isClaimed","inputs":[{"name":"contestId","type":"string","internalType":"string"},{"name":"token","type":"address","internalType":"contract IERC20"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isClaimedMany","inputs":[{"name":"contestIds","type":"string[]","internalType":"string[]"},{"name":"tokens","type":"address[]","internalType":"contract IERC20[]"},{"name":"indices","type":"uint256[]","internalType":"uint256[]"}],"outputs":[{"name":"","type":"bool[]","internalType":"bool[]"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"proxiableUUID","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"publishRoot","inputs":[{"name":"contestId","type":"string","internalType":"string"},{"name":"token","type":"address","internalType":"contract IERC20"},{"name":"root","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"removeAdmin","inputs":[{"name":"user","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"upgradeToAndCall","inputs":[{"name":"newImplementation","type":"address","internalType":"address"},{"name":"data","type":"bytes","internalType":"bytes"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"withdraw","inputs":[{"name":"token","type":"address","internalType":"contract IERC20"},{"name":"amount","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"Claim","inputs":[{"name":"contestId","type":"string","indexed":false,"internalType":"string"},{"name":"token","type":"address","indexed":true,"internalType":"contract IERC20"},{"name":"index","type":"uint256","indexed":true,"internalType":"uint256"},{"name":"user","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Initialized","inputs":[{"name":"version","type":"uint64","indexed":false,"internalType":"uint64"}],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RootPublished","inputs":[{"name":"contestId","type":"string","indexed":false,"internalType":"string"},{"name":"token","type":"address","indexed":true,"internalType":"contract IERC20"},{"name":"root","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"rootKey","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"TokensWithdrawn","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"to","type":"address","indexed":true,"internalType":"address"},{"name":"amount","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"name":"implementation","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"AddressEmptyCode","inputs":[{"name":"target","type":"address","internalType":"address"}]},{"type":"error","name":"ERC1967InvalidImplementation","inputs":[{"name":"implementation","type":"address","internalType":"address"}]},{"type":"error","name":"ERC1967NonPayable","inputs":[]},{"type":"error","name":"FailedCall","inputs":[]},{"type":"error","name":"InvalidInitialization","inputs":[]},{"type":"error","name":"NotInitializing","inputs":[]},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"ReentrancyGuardReentrantCall","inputs":[]},{"type":"error","name":"SafeERC20FailedOperation","inputs":[{"name":"token","type":"address","internalType":"address"}]},{"type":"error","name":"UUPSUnauthorizedCallContext","inputs":[]},{"type":"error","name":"UUPSUnsupportedProxiableUUID","inputs":[{"name":"slot","type":"bytes32","internalType":"bytes32"}]}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[{"type":"function","name":"IS_TEST","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"excludeArtifacts","inputs":[],"outputs":[{"name":"excludedArtifacts_","type":"string[]","internalType":"string[]"}],"stateMutability":"view"},{"type":"function","name":"excludeContracts","inputs":[],"outputs":[{"name":"excludedContracts_","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"excludeSelectors","inputs":[],"outputs":[{"name":"excludedSelectors_","type":"tuple[]","internalType":"struct StdInvariant.FuzzSelector[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"selectors","type":"bytes4[]","internalType":"bytes4[]"}]}],"stateMutability":"view"},{"type":"function","name":"excludeSenders","inputs":[],"outputs":[{"name":"excludedSenders_","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"failed","inputs":[],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"setUp","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"targetArtifactSelectors","inputs":[],"outputs":[{"name":"targetedArtifactSelectors_","type":"tuple[]","internalType":"struct StdInvariant.FuzzArtifactSelector[]","components":[{"name":"artifact","type":"string","internalType":"string"},{"name":"selectors","type":"bytes4[]","internalType":"bytes4[]"}]}],"stateMutability":"view"},{"type":"function","name":"targetArtifacts","inputs":[],"outputs":[{"name":"targetedArtifacts_","type":"string[]","internalType":"string[]"}],"stateMutability":"view"},{"type":"function","name":"targetContracts","inputs":[],"outputs":[{"name":"targetedContracts_","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"targetInterfaces","inputs":[],"outputs":[{"name":"targetedInterfaces_","type":"tuple[]","internalType":"struct StdInvariant.FuzzInterface[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"artifacts","type":"string[]","internalType":"string[]"}]}],"stateMutability":"view"},{"type":"function","name":"targetSelectors","inputs":[],"outputs":[{"name":"targetedSelectors_","type":"tuple[]","internalType":"struct StdInvariant.FuzzSelector[]","components":[{"name":"addr","type":"address","internalType":"address"},{"name":"selectors","type":"bytes4[]","internalType":"bytes4[]"}]}],"stateMutability":"view"},{"type":"function","name":"targetSenders","inputs":[],"outputs":[{"name":"targetedSenders_","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"test_AdminRoleCanPublishRoot","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_AdminWithdraw","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_ClaimMany","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_ClaimMany_DuplicateIndexReverts","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_ClaimMany_LengthMismatchReverts","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_ClaimWithWrongTokenOrContest","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_IsClaimedReflectsState","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_OnlyOwnerGuards","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_PublishRootAndSingleClaim","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_RevertOnDoubleClaim","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_RevertOnInvalidProof","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_RootNotSet_RevertOnClaim","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"test_RootUpdateInvalidatesOldProof","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"event","name":"log","inputs":[{"name":"","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"log_address","inputs":[{"name":"","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"log_array","inputs":[{"name":"val","type":"uint256[]","indexed":false,"internalType":"uint256[]"}],"anonymous":false},{"type":"event","name":"log_array","inputs":[{"name":"val","type":"int256[]","indexed":false,"internalType":"int256[]"}],"anonymous":false},{"type":"event","name":"log_array","inputs":[{"name":"val","type":"address[]","indexed":false,"internalType":"address[]"}],"anonymous":false},{"type":"event","name":"log_bytes","inputs":[{"name":"","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"log_bytes32","inputs":[{"name":"","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"log_int","inputs":[{"name":"","type":"int256","indexed":false,"internalType":"int256"}],"anonymous":false},{"type":"event","name":"log_named_address","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"log_named_array","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"uint256[]","indexed":false,"internalType":"uint256[]"}],"anonymous":false},{"type":"event","name":"log_named_array","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"int256[]","indexed":false,"internalType":"int256[]"}],"anonymous":false},{"type":"event","name":"log_named_array","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"address[]","indexed":false,"internalType":"address[]"}],"anonymous":false},{"type":"event","name":"log_named_bytes","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false},{"type":"event","name":"log_named_bytes32","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"bytes32","indexed":false,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"log_named_decimal_int","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"int256","indexed":false,"internalType":"int256"},{"name":"decimals","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"log_named_decimal_uint","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"uint256","indexed":false,"internalType":"uint256"},{"name":"decimals","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"log_named_int","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"int256","indexed":false,"internalType":"int256"}],"anonymous":false},{"type":"event","name":"log_named_string","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"log_named_uint","inputs":[{"name":"key","type":"string","indexed":false,"internalType":"string"},{"name":"val","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"log_string","inputs":[{"name":"","type":"string","indexed":false,"internalType":"string"}],"anonymous":false},{"type":"event","name":"log_uint","inputs":[{"name":"","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"logs","inputs":[{"name":"","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false}]}
|
package/abis/Panic.json
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[{"type":"error","name":"SafeCastOverflowedIntDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"int256","internalType":"int256"}]},{"type":"error","name":"SafeCastOverflowedIntToUint","inputs":[{"name":"value","type":"int256","internalType":"int256"}]},{"type":"error","name":"SafeCastOverflowedUintDowncast","inputs":[{"name":"bits","type":"uint8","internalType":"uint8"},{"name":"value","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"SafeCastOverflowedUintToInt","inputs":[{"name":"value","type":"uint256","internalType":"uint256"}]}]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"abi":[]}
|
package/abis/Strings.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"
|
|
1
|
+
{"abi":[{"type":"error","name":"StringsInsufficientHexLength","inputs":[{"name":"value","type":"uint256","internalType":"uint256"},{"name":"length","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"StringsInvalidAddressFormat","inputs":[]},{"type":"error","name":"StringsInvalidChar","inputs":[]}]}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.26;
|
|
3
|
+
|
|
4
|
+
// OpenZeppelin upgradeable
|
|
5
|
+
import "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
|
|
6
|
+
import "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
|
|
7
|
+
import "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
|
|
8
|
+
import "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
|
|
9
|
+
import "@openzeppelin/contracts-upgradeable/utils/ReentrancyGuardUpgradeable.sol";
|
|
10
|
+
|
|
11
|
+
// OpenZeppelin non-upgradeable utils
|
|
12
|
+
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
13
|
+
import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
|
|
14
|
+
import "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
|
|
15
|
+
|
|
16
|
+
/// @title Merkle-based rewards distributor for contests
|
|
17
|
+
/// @notice Owner publishes one Merkle root per (contestId, token). Users claim with proof.
|
|
18
|
+
contract MerkleRewardsDistributor is Initializable, UUPSUpgradeable, Ownable2StepUpgradeable, AccessControlUpgradeable, ReentrancyGuardUpgradeable {
|
|
19
|
+
using SafeERC20 for IERC20;
|
|
20
|
+
|
|
21
|
+
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
|
|
22
|
+
|
|
23
|
+
// rootKey => merkleRoot
|
|
24
|
+
mapping(bytes32 => bytes32) private _roots;
|
|
25
|
+
// rootKey => claimed bitmap wordIndex => word
|
|
26
|
+
mapping(bytes32 => mapping(uint256 => uint256)) private _claimedBitMap;
|
|
27
|
+
|
|
28
|
+
event RootPublished(string contestId, IERC20 indexed token, bytes32 indexed root, bytes32 indexed rootKey);
|
|
29
|
+
event Claim(
|
|
30
|
+
string contestId,
|
|
31
|
+
IERC20 indexed token,
|
|
32
|
+
uint256 indexed index,
|
|
33
|
+
address indexed user,
|
|
34
|
+
uint256 amount
|
|
35
|
+
);
|
|
36
|
+
event TokensWithdrawn(address indexed token, address indexed to, uint256 amount);
|
|
37
|
+
|
|
38
|
+
/// @custom:oz-upgrades-unsafe-allow constructor
|
|
39
|
+
constructor() {
|
|
40
|
+
_disableInitializers();
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function initialize(address initialOwner) public initializer {
|
|
44
|
+
__ReentrancyGuard_init();
|
|
45
|
+
__Ownable_init(initialOwner);
|
|
46
|
+
__UUPSUpgradeable_init();
|
|
47
|
+
__AccessControl_init();
|
|
48
|
+
|
|
49
|
+
_grantRole(ADMIN_ROLE, initialOwner);
|
|
50
|
+
_setRoleAdmin(ADMIN_ROLE, ADMIN_ROLE);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function _authorizeUpgrade(address newImplementation) internal override onlyOwner {}
|
|
54
|
+
|
|
55
|
+
// ------ Admin ------
|
|
56
|
+
|
|
57
|
+
/// @notice Publishes/updates the root for a given (contestId, token)
|
|
58
|
+
function publishRoot(string calldata contestId, IERC20 token, bytes32 root) external onlyAdmin {
|
|
59
|
+
bytes32 key = _rootKey(contestId, token);
|
|
60
|
+
_roots[key] = root;
|
|
61
|
+
emit RootPublished(contestId, token, root, key);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function withdraw(IERC20 token, uint256 amount) external onlyOwner nonReentrant {
|
|
65
|
+
token.safeTransfer(msg.sender, amount);
|
|
66
|
+
emit TokensWithdrawn(address(token), msg.sender, amount);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// role management
|
|
70
|
+
modifier onlyAdmin() {
|
|
71
|
+
require(hasRole(ADMIN_ROLE, msg.sender), "MerkleRewards: must have admin role");
|
|
72
|
+
_;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function addAdmin(address user) external onlyAdmin {
|
|
76
|
+
grantRole(ADMIN_ROLE, user);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function removeAdmin(address user) external onlyAdmin {
|
|
80
|
+
revokeRole(ADMIN_ROLE, user);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function isAdmin(address user) external view returns (bool) {
|
|
84
|
+
return hasRole(ADMIN_ROLE, user);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// ------ Claims ------
|
|
88
|
+
|
|
89
|
+
/// @notice Claims `amount` for `user` with a Merkle proof. Funds are sent to `user`.
|
|
90
|
+
/// @dev Leaf is keccak256(abi.encode(index, user, token, amount, contestId))
|
|
91
|
+
function claim(
|
|
92
|
+
string calldata contestId,
|
|
93
|
+
IERC20 token,
|
|
94
|
+
uint256 index,
|
|
95
|
+
address user,
|
|
96
|
+
uint256 amount,
|
|
97
|
+
bytes32[] calldata merkleProof
|
|
98
|
+
) external nonReentrant {
|
|
99
|
+
bytes32 key = _rootKey(contestId, token);
|
|
100
|
+
bytes32 root = _roots[key];
|
|
101
|
+
require(root != bytes32(0), "MerkleRewards: root not set");
|
|
102
|
+
require(!_isClaimed(key, index), "MerkleRewards: already claimed");
|
|
103
|
+
|
|
104
|
+
bytes32 leaf = keccak256(abi.encode(index, user, token, amount, contestId));
|
|
105
|
+
require(MerkleProof.verify(merkleProof, root, leaf), "MerkleRewards: invalid proof");
|
|
106
|
+
|
|
107
|
+
_setClaimed(key, index);
|
|
108
|
+
|
|
109
|
+
token.safeTransfer(user, amount);
|
|
110
|
+
|
|
111
|
+
emit Claim(contestId, token, index, user, amount);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/// @notice Claims multiple entries in one transaction. Funds are sent to each entry's `user`.
|
|
115
|
+
function claimMany(
|
|
116
|
+
string[] calldata contestIds,
|
|
117
|
+
IERC20[] calldata tokens,
|
|
118
|
+
uint256[] calldata indices,
|
|
119
|
+
address[] calldata users,
|
|
120
|
+
uint256[] calldata amounts,
|
|
121
|
+
bytes32[][] calldata merkleProofs
|
|
122
|
+
) external nonReentrant {
|
|
123
|
+
uint256 len = contestIds.length;
|
|
124
|
+
require(
|
|
125
|
+
len == tokens.length &&
|
|
126
|
+
len == indices.length &&
|
|
127
|
+
len == users.length &&
|
|
128
|
+
len == amounts.length &&
|
|
129
|
+
len == merkleProofs.length,
|
|
130
|
+
"MerkleRewards: arrays length mismatch"
|
|
131
|
+
);
|
|
132
|
+
|
|
133
|
+
for (uint256 i = 0; i < len; i++) {
|
|
134
|
+
bytes32 key = _rootKey(contestIds[i], tokens[i]);
|
|
135
|
+
bytes32 root = _roots[key];
|
|
136
|
+
require(root != bytes32(0), "MerkleRewards: root not set");
|
|
137
|
+
require(!_isClaimed(key, indices[i]), "MerkleRewards: already claimed");
|
|
138
|
+
|
|
139
|
+
bytes32 leaf = keccak256(abi.encode(indices[i], users[i], tokens[i], amounts[i], contestIds[i]));
|
|
140
|
+
require(MerkleProof.verify(merkleProofs[i], root, leaf), "MerkleRewards: invalid proof");
|
|
141
|
+
|
|
142
|
+
_setClaimed(key, indices[i]);
|
|
143
|
+
tokens[i].safeTransfer(users[i], amounts[i]);
|
|
144
|
+
|
|
145
|
+
emit Claim(contestIds[i], tokens[i], indices[i], users[i], amounts[i]);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// ------ Views ------
|
|
150
|
+
|
|
151
|
+
function getRoot(string calldata contestId, IERC20 token) external view returns (bytes32) {
|
|
152
|
+
return _roots[_rootKey(contestId, token)];
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
function isClaimed(
|
|
156
|
+
string calldata contestId,
|
|
157
|
+
IERC20 token,
|
|
158
|
+
uint256 index
|
|
159
|
+
) external view returns (bool) {
|
|
160
|
+
return _isClaimed(_rootKey(contestId, token), index);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function isClaimedMany(
|
|
164
|
+
string[] calldata contestIds,
|
|
165
|
+
IERC20[] calldata tokens,
|
|
166
|
+
uint256[] calldata indices
|
|
167
|
+
) external view returns (bool[] memory) {
|
|
168
|
+
bool[] memory claims = new bool[](contestIds.length);
|
|
169
|
+
for (uint256 i = 0; i < contestIds.length; i++) {
|
|
170
|
+
claims[i] = _isClaimed(_rootKey(contestIds[i], tokens[i]), indices[i]);
|
|
171
|
+
}
|
|
172
|
+
return claims;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ------ Internal utils ------
|
|
176
|
+
|
|
177
|
+
function _rootKey(string calldata contestId, IERC20 token) private pure returns (bytes32) {
|
|
178
|
+
return keccak256(abi.encode(contestId, token));
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function _isClaimed(bytes32 key, uint256 index) private view returns (bool) {
|
|
182
|
+
uint256 wordIndex = index >> 8; // divide by 256
|
|
183
|
+
uint256 bitIndex = index & 255; // modulo 256
|
|
184
|
+
uint256 word = _claimedBitMap[key][wordIndex];
|
|
185
|
+
uint256 mask = (1 << bitIndex);
|
|
186
|
+
return word & mask == mask;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function _setClaimed(bytes32 key, uint256 index) private {
|
|
190
|
+
uint256 wordIndex = index >> 8;
|
|
191
|
+
uint256 bitIndex = index & 255;
|
|
192
|
+
_claimedBitMap[key][wordIndex] = _claimedBitMap[key][wordIndex] | (1 << bitIndex);
|
|
193
|
+
}
|
|
194
|
+
}
|
package/package.json
CHANGED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// // SPDX-License-Identifier: GPL-2.0
|
|
2
|
+
// pragma solidity ^0.8.26;
|
|
3
|
+
|
|
4
|
+
// import {Script} from "forge-std/Script.sol";
|
|
5
|
+
// import {console} from "forge-std/console.sol";
|
|
6
|
+
// // Import your contracts here
|
|
7
|
+
// import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
8
|
+
// import {PredictionMarketV3_3, IWETH} from "../contracts/PredictionMarketV3_3.sol";
|
|
9
|
+
// import {IPredictionMarketV3Manager} from "../contracts/IPredictionMarketV3Manager.sol";
|
|
10
|
+
// import {PredictionMarketV3Manager, FantasyERC20} from "../contracts/PredictionMarketV3Manager.sol";
|
|
11
|
+
// import {IRealityETH_ERC20} from "../contracts/IRealityETH_ERC20.sol";
|
|
12
|
+
|
|
13
|
+
// contract UpdateMarket is Script {
|
|
14
|
+
// function run() public {
|
|
15
|
+
|
|
16
|
+
// vm.startBroadcast();
|
|
17
|
+
|
|
18
|
+
// address payable PREDICTION_MARKET_V3_3 = payable(address(0x3e0F5F8F5Fb043aBFA475C0308417Bf72c463289));
|
|
19
|
+
// address PREDICTION_MARKET_V3_MANAGER = address(0x68dDc91CCC06e63d74905D901A30edEA7C77EebE);
|
|
20
|
+
|
|
21
|
+
// PredictionMarketV3_3.MarketState state = PredictionMarketV3_3(PREDICTION_MARKET_V3_3).getMarketState(486);
|
|
22
|
+
// console2.log("state: ", state);
|
|
23
|
+
|
|
24
|
+
// PredictionMarketV3_3.MarketUpdateDescription memory description = PredictionMarketV3_3.MarketUpdateDescription({
|
|
25
|
+
// closesAtTimestamp: 1762066800,
|
|
26
|
+
// balance: 456538064447348172635074428,
|
|
27
|
+
// liquidity: 120000000000000000000000000,
|
|
28
|
+
// sharesAvailable: 1272835104225672313766121101,
|
|
29
|
+
// state: PredictionMarketV3_3.MarketState.open,
|
|
30
|
+
// resolution: PredictionMarketV3_3.MarketResolution({
|
|
31
|
+
// resolved: false,
|
|
32
|
+
// realitio: IRealityETH_ERC20(0x71D76Ff3C2729071B2c52A667197d9f715029F2c),
|
|
33
|
+
// outcomeId: 115792089237316195423570985008687907853269984665640564039457584007913129639935,
|
|
34
|
+
// questionId: 0x21d6c6c195572d82a7d0a7ba677251dfd3839b21e09df9b39ae36ec99fa6744d,
|
|
35
|
+
// realitioTimeout: 3600
|
|
36
|
+
// }),
|
|
37
|
+
// feesPoolWeight: 0,
|
|
38
|
+
// feesTreasury: address(0xBc30e9765Dc8c735206c76DE96d369754eBbcc1f),
|
|
39
|
+
// feesDistributor: address(0xBc30e9765Dc8c735206c76DE96d369754eBbcc1f),
|
|
40
|
+
// buyFees: PredictionMarketV3_3.Fees({fee: 0, treasuryFee: 0, distributorFee: 0}),
|
|
41
|
+
// sellFees: PredictionMarketV3_3.Fees({fee: 0, treasuryFee: 0, distributorFee: 0}),
|
|
42
|
+
// outcomeCount: 5,
|
|
43
|
+
// token: IERC20(0x0b07cf011B6e2b7E0803b892d97f751659940F23),
|
|
44
|
+
// manager: IPredictionMarketV3Manager(0x2EbD002d755bdFadb9e5549aA00a80bd7fa408AE),
|
|
45
|
+
// creator: address(0xBc30e9765Dc8c735206c76DE96d369754eBbcc1f),
|
|
46
|
+
// paused: false
|
|
47
|
+
// });
|
|
48
|
+
|
|
49
|
+
// PredictionMarketV3_3(PREDICTION_MARKET_V3_3).updateMarket(486, description);
|
|
50
|
+
// PredictionMarketV3_3(PREDICTION_MARKET_V3_3).updateMarketResolution(486, description);
|
|
51
|
+
|
|
52
|
+
// state = PredictionMarketV3_3(PREDICTION_MARKET_V3_3).getMarketState(486);
|
|
53
|
+
// console2.log("new state: ", state);
|
|
54
|
+
// }
|
|
55
|
+
// }
|
package/src/Application.js
CHANGED
|
@@ -17,6 +17,7 @@ const FantasyERC20Contract = require("./models/index").FantasyERC20Contract;
|
|
|
17
17
|
const WETH9Contract = require("./models/index").WETH9Contract;
|
|
18
18
|
const ArbitrationContract = require("./models/index").ArbitrationContract;
|
|
19
19
|
const ArbitrationProxyContract = require("./models/index").ArbitrationProxyContract;
|
|
20
|
+
const MerkleRewardsDistributorContract = require("./models/index").MerkleRewardsDistributorContract;
|
|
20
21
|
|
|
21
22
|
const DualProvider = require("./utils/DualProvider");
|
|
22
23
|
const Account = require('./utils/Account');
|
|
@@ -412,6 +413,21 @@ class Application {
|
|
|
412
413
|
}
|
|
413
414
|
};
|
|
414
415
|
|
|
416
|
+
/**
|
|
417
|
+
* @name getMerkleRewardsDistributorContract
|
|
418
|
+
* @param {Address} ContractAddress (Opt) If it is deployed
|
|
419
|
+
* @description Create a Merkle Rewards Distributor Contract
|
|
420
|
+
*/
|
|
421
|
+
getMerkleRewardsDistributorContract({ contractAddress = null }) {
|
|
422
|
+
try {
|
|
423
|
+
return new MerkleRewardsDistributorContract({
|
|
424
|
+
...this.contractDefaultParams(contractAddress)
|
|
425
|
+
});
|
|
426
|
+
} catch (err) {
|
|
427
|
+
throw err;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
415
431
|
/***********/
|
|
416
432
|
/** UTILS **/
|
|
417
433
|
/***********/
|
package/src/interfaces/index.js
CHANGED
|
@@ -15,6 +15,7 @@ let index = {
|
|
|
15
15
|
predictionMarketV3Factory: require("../../abis/PredictionMarketV3Factory.json"),
|
|
16
16
|
predictionV3Querier: require("../../abis/PredictionMarketV3Querier.json"),
|
|
17
17
|
realitio: require("../../abis/RealitioERC20.json"),
|
|
18
|
+
merkleRewardsDistributor: require("../../abis/MerkleRewardsDistributor.json"),
|
|
18
19
|
voting: require("../../abis/Voting.json"),
|
|
19
20
|
weth: require("../../abis/WETH9.json"),
|
|
20
21
|
};
|
package/src/models/IContract.js
CHANGED
|
@@ -1138,6 +1138,20 @@ class IContract {
|
|
|
1138
1138
|
async getBlock(blockNumber) {
|
|
1139
1139
|
return await this.params.web3.eth.getBlock(blockNumber);
|
|
1140
1140
|
}
|
|
1141
|
+
|
|
1142
|
+
async soliditySha3(args) {
|
|
1143
|
+
return this.params.web3.utils.soliditySha3(...args)
|
|
1144
|
+
}
|
|
1145
|
+
|
|
1146
|
+
async signMessage(message) {
|
|
1147
|
+
if (this.acc) {
|
|
1148
|
+
return await this.acc.account.sign(message);
|
|
1149
|
+
} else {
|
|
1150
|
+
// TODO need to test with forntend
|
|
1151
|
+
// return await this.params.web3.eth.sign(message, await this.getMyAccount());
|
|
1152
|
+
return await this.params.web3.eth.personal.sign(message, await this.getMyAccount());
|
|
1153
|
+
}
|
|
1154
|
+
}
|
|
1141
1155
|
}
|
|
1142
1156
|
|
|
1143
1157
|
module.exports = IContract;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
// const _ = require("lodash");
|
|
2
|
+
|
|
3
|
+
const merkleRewardsDistributor = require("../interfaces").merkleRewardsDistributor;
|
|
4
|
+
|
|
5
|
+
const Numbers = require("../utils/Numbers");
|
|
6
|
+
const IContract = require('./IContract');
|
|
7
|
+
|
|
8
|
+
class MerkleRewardsDistributorContract extends IContract {
|
|
9
|
+
constructor(params) {
|
|
10
|
+
super({ abi: merkleRewardsDistributor, ...params });
|
|
11
|
+
this.contractName = 'merkleRewardsDistributor';
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// ----- Views -----
|
|
15
|
+
async getRoot({ contestId, tokenAddress }) {
|
|
16
|
+
return await this.params.contract
|
|
17
|
+
.getContract()
|
|
18
|
+
.methods
|
|
19
|
+
.getRoot(contestId, tokenAddress)
|
|
20
|
+
.call();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
async isClaimed({ contestId, tokenAddress, index }) {
|
|
24
|
+
return await this.params.contract
|
|
25
|
+
.getContract()
|
|
26
|
+
.methods
|
|
27
|
+
.isClaimed(contestId, tokenAddress, index)
|
|
28
|
+
.call();
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
async isClaimedMany({ contestIds, tokenAddresses, indices }) {
|
|
32
|
+
return await this.params.contract
|
|
33
|
+
.getContract()
|
|
34
|
+
.methods
|
|
35
|
+
.isClaimedMany(contestIds, tokenAddresses, indices)
|
|
36
|
+
.call();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async isAdmin({ user }) {
|
|
40
|
+
return await this.params.contract
|
|
41
|
+
.getContract()
|
|
42
|
+
.methods
|
|
43
|
+
.isAdmin(user)
|
|
44
|
+
.call();
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async getClaims({ user, tokenAddress, index }) {
|
|
48
|
+
return await this.getEvents(
|
|
49
|
+
'Claim',
|
|
50
|
+
{
|
|
51
|
+
user,
|
|
52
|
+
tokenAddress,
|
|
53
|
+
index
|
|
54
|
+
}
|
|
55
|
+
);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// ----- Admin -----
|
|
59
|
+
async publishRoot({ contestId, tokenAddress, root }) {
|
|
60
|
+
return await this.__sendTx(
|
|
61
|
+
this.getContract().methods.publishRoot(contestId, tokenAddress, root)
|
|
62
|
+
);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async addAdmin({ user }) {
|
|
66
|
+
return await this.__sendTx(
|
|
67
|
+
this.getContract().methods.addAdmin(user)
|
|
68
|
+
);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
async removeAdmin({ user }) {
|
|
72
|
+
return await this.__sendTx(
|
|
73
|
+
this.getContract().methods.removeAdmin(user)
|
|
74
|
+
);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
async withdraw({ tokenAddress, amount }) {
|
|
78
|
+
const amountDecimals = Numbers.toSmartContractDecimals(amount, 18);
|
|
79
|
+
return await this.__sendTx(
|
|
80
|
+
this.getContract().methods.withdraw(tokenAddress, amountDecimals)
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// ----- Claims -----
|
|
85
|
+
async claim({ contestId, tokenAddress, index, user, amount, proof }) {
|
|
86
|
+
const amountDecimals = Numbers.toSmartContractDecimals(amount, 18);
|
|
87
|
+
return await this.__sendTx(
|
|
88
|
+
this.getContract().methods.claim(contestId, tokenAddress, index, user, amountDecimals, proof)
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
async claimMany({ entries }) {
|
|
93
|
+
// entries: array of { contestId, tokenAddress, index, user, amount, proof }
|
|
94
|
+
const contestIds = entries.map(e => e.contestId);
|
|
95
|
+
const tokens = entries.map(e => e.tokenAddress);
|
|
96
|
+
const indices = entries.map(e => e.index);
|
|
97
|
+
const users = entries.map(e => e.user);
|
|
98
|
+
const amounts = entries.map(e => Numbers.toSmartContractDecimals(e.amount, 18));
|
|
99
|
+
const proofs = entries.map(e => e.proof);
|
|
100
|
+
|
|
101
|
+
return await this.__sendTx(
|
|
102
|
+
this.getContract().methods.claimMany(contestIds, tokens, indices, users, amounts, proofs)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = MerkleRewardsDistributorContract;
|
package/src/models/index.js
CHANGED
|
@@ -14,6 +14,7 @@ const FantasyERC20Contract = require('./FantasyERC20Contract');
|
|
|
14
14
|
const WETH9Contract = require('./WETH9Contract');
|
|
15
15
|
const ArbitrationContract = require('./ArbitrationContract');
|
|
16
16
|
const ArbitrationProxyContract = require('./ArbitrationProxyContract');
|
|
17
|
+
const MerkleRewardsDistributorContract = require('./MerkleRewardsDistributorContract');
|
|
17
18
|
|
|
18
19
|
module.exports = {
|
|
19
20
|
ERC20Contract,
|
|
@@ -31,5 +32,6 @@ module.exports = {
|
|
|
31
32
|
ArbitrationContract,
|
|
32
33
|
ArbitrationProxyContract,
|
|
33
34
|
PredictionMarketV3FactoryContract,
|
|
34
|
-
PredictionMarketV3ControllerContract
|
|
35
|
+
PredictionMarketV3ControllerContract,
|
|
36
|
+
MerkleRewardsDistributorContract
|
|
35
37
|
}
|
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.20;
|
|
3
|
+
|
|
4
|
+
import "forge-std/Test.sol";
|
|
5
|
+
import {ERC1967Proxy} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
|
|
6
|
+
import {MerkleProof} from "@openzeppelin/contracts/utils/cryptography/MerkleProof.sol";
|
|
7
|
+
|
|
8
|
+
import {MerkleRewardsDistributor} from "../contracts/MerkleRewardsDistributor.sol";
|
|
9
|
+
import {ERC20MinterPauser} from "../contracts/ERC20MinterPauser.sol";
|
|
10
|
+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
11
|
+
|
|
12
|
+
contract MerkleRewardsDistributorTest is Test {
|
|
13
|
+
MerkleRewardsDistributor internal distributor;
|
|
14
|
+
ERC20MinterPauser internal token;
|
|
15
|
+
|
|
16
|
+
address internal deployer = address(this);
|
|
17
|
+
address internal alice;
|
|
18
|
+
address internal bob;
|
|
19
|
+
address internal carol;
|
|
20
|
+
|
|
21
|
+
function setUp() public {
|
|
22
|
+
alice = makeAddr("ALICE");
|
|
23
|
+
bob = makeAddr("BOB");
|
|
24
|
+
carol = makeAddr("CAROL");
|
|
25
|
+
|
|
26
|
+
address implementation = address(new MerkleRewardsDistributor());
|
|
27
|
+
bytes memory initData = abi.encodeCall(MerkleRewardsDistributor.initialize, (deployer));
|
|
28
|
+
ERC1967Proxy proxy = new ERC1967Proxy(implementation, initData);
|
|
29
|
+
distributor = MerkleRewardsDistributor(address(proxy));
|
|
30
|
+
|
|
31
|
+
token = new ERC20MinterPauser("Test Token", "TEST");
|
|
32
|
+
token.mint(address(distributor), 1_000_000 ether);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
// local Merkle builder (keccak abi.encode)
|
|
36
|
+
function _leaf(uint256 index, address user, address tokenAddr, uint256 amount, string memory contestId)
|
|
37
|
+
internal pure returns (bytes32)
|
|
38
|
+
{
|
|
39
|
+
return keccak256(abi.encode(index, user, tokenAddr, amount, contestId));
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function _buildRoot(bytes32[] memory leaves) internal pure returns (bytes32 root) {
|
|
43
|
+
if (leaves.length == 0) return bytes32(0);
|
|
44
|
+
while (leaves.length > 1) {
|
|
45
|
+
uint256 n = (leaves.length + 1) / 2;
|
|
46
|
+
bytes32[] memory next = new bytes32[](n);
|
|
47
|
+
for (uint256 i = 0; i < leaves.length; i += 2) {
|
|
48
|
+
bytes32 left = leaves[i];
|
|
49
|
+
bytes32 right = (i + 1 < leaves.length) ? leaves[i + 1] : left;
|
|
50
|
+
next[i/2] = _parent(left, right);
|
|
51
|
+
}
|
|
52
|
+
leaves = next;
|
|
53
|
+
}
|
|
54
|
+
return leaves[0];
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function _parent(bytes32 a, bytes32 b) internal pure returns (bytes32) {
|
|
58
|
+
(bytes32 left, bytes32 right) = a <= b ? (a,b) : (b,a);
|
|
59
|
+
return keccak256(abi.encodePacked(left, right));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
function _proof(bytes32[] memory leaves, uint256 index) internal pure returns (bytes32[] memory p) {
|
|
63
|
+
// Build layers copying logic from _buildRoot to also record siblings
|
|
64
|
+
bytes32[] memory current = leaves;
|
|
65
|
+
bytes32[] memory proofTmp = new bytes32[](64);
|
|
66
|
+
uint256 proofLen = 0;
|
|
67
|
+
uint256 idx = index;
|
|
68
|
+
while (current.length > 1) {
|
|
69
|
+
uint256 n = (current.length + 1) / 2;
|
|
70
|
+
bytes32[] memory next = new bytes32[](n);
|
|
71
|
+
for (uint256 i = 0; i < current.length; i += 2) {
|
|
72
|
+
bytes32 left = current[i];
|
|
73
|
+
bytes32 right = (i + 1 < current.length) ? current[i + 1] : left;
|
|
74
|
+
next[i/2] = _parent(left, right);
|
|
75
|
+
if (i == (idx ^ 1) - 1 || i == (idx & ~uint256(1))) {
|
|
76
|
+
// sibling for this level
|
|
77
|
+
bytes32 sib = (idx % 2 == 0) ? right : left;
|
|
78
|
+
if (i + 1 >= current.length && idx % 2 == 1) {
|
|
79
|
+
// when paired with itself, skip duplicate sibling
|
|
80
|
+
} else {
|
|
81
|
+
proofTmp[proofLen++] = sib;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
current = next;
|
|
86
|
+
idx >>= 1;
|
|
87
|
+
}
|
|
88
|
+
p = new bytes32[](proofLen);
|
|
89
|
+
for (uint256 i = 0; i < proofLen; i++) p[i] = proofTmp[i];
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function test_PublishRootAndSingleClaim() public {
|
|
93
|
+
string memory cid = "daily:2025-09-30";
|
|
94
|
+
|
|
95
|
+
bytes32[] memory leaves = new bytes32[](2);
|
|
96
|
+
leaves[0] = _leaf(0, alice, address(token), 100 ether, cid);
|
|
97
|
+
leaves[1] = _leaf(1, bob, address(token), 200 ether, cid);
|
|
98
|
+
bytes32 root = _buildRoot(leaves);
|
|
99
|
+
|
|
100
|
+
distributor.publishRoot(cid, IERC20(address(token)), root);
|
|
101
|
+
assertEq(distributor.getRoot(cid, IERC20(address(token))), root);
|
|
102
|
+
|
|
103
|
+
bytes32[] memory proofAlice = _proof(leaves, 0);
|
|
104
|
+
assertFalse(distributor.isClaimed(cid, IERC20(address(token)), 0));
|
|
105
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 100 ether, proofAlice);
|
|
106
|
+
assertTrue(distributor.isClaimed(cid, IERC20(address(token)), 0));
|
|
107
|
+
assertEq(token.balanceOf(alice), 100 ether);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function test_RevertOnInvalidProof() public {
|
|
111
|
+
string memory cid = "weekly:2025-W40";
|
|
112
|
+
|
|
113
|
+
bytes32[] memory leaves = new bytes32[](1);
|
|
114
|
+
leaves[0] = _leaf(0, alice, address(token), 50 ether, cid);
|
|
115
|
+
bytes32 root = _buildRoot(leaves);
|
|
116
|
+
distributor.publishRoot(cid, IERC20(address(token)), root);
|
|
117
|
+
|
|
118
|
+
bytes32[] memory wrongProof = new bytes32[](0);
|
|
119
|
+
vm.expectRevert(bytes("MerkleRewards: invalid proof"));
|
|
120
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 51 ether, wrongProof);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
function test_RevertOnDoubleClaim() public {
|
|
124
|
+
string memory cid = "monthly:2025-09";
|
|
125
|
+
|
|
126
|
+
bytes32[] memory leaves = new bytes32[](1);
|
|
127
|
+
leaves[0] = _leaf(0, alice, address(token), 10 ether, cid);
|
|
128
|
+
bytes32 root = _buildRoot(leaves);
|
|
129
|
+
distributor.publishRoot(cid, IERC20(address(token)), root);
|
|
130
|
+
|
|
131
|
+
bytes32[] memory proof = _proof(leaves, 0);
|
|
132
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 10 ether, proof);
|
|
133
|
+
|
|
134
|
+
vm.expectRevert(bytes("MerkleRewards: already claimed"));
|
|
135
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 10 ether, proof);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
function test_ClaimMany() public {
|
|
139
|
+
string memory cid1 = "daily:2025-09-30";
|
|
140
|
+
string memory cid2 = "weekly:2025-W40";
|
|
141
|
+
|
|
142
|
+
bytes32[] memory leaves1 = new bytes32[](1);
|
|
143
|
+
leaves1[0] = _leaf(0, alice, address(token), 100 ether, cid1);
|
|
144
|
+
bytes32 root1 = _buildRoot(leaves1);
|
|
145
|
+
distributor.publishRoot(cid1, IERC20(address(token)), root1);
|
|
146
|
+
|
|
147
|
+
bytes32[] memory leaves2 = new bytes32[](2);
|
|
148
|
+
leaves2[0] = _leaf(0, alice, address(token), 5 ether, cid2);
|
|
149
|
+
leaves2[1] = _leaf(1, bob, address(token), 7 ether, cid2);
|
|
150
|
+
bytes32 root2 = _buildRoot(leaves2);
|
|
151
|
+
distributor.publishRoot(cid2, IERC20(address(token)), root2);
|
|
152
|
+
|
|
153
|
+
string[] memory cids = new string[](2);
|
|
154
|
+
cids[0] = cid1; cids[1] = cid2;
|
|
155
|
+
IERC20[] memory tokens = new IERC20[](2);
|
|
156
|
+
tokens[0] = IERC20(address(token)); tokens[1] = IERC20(address(token));
|
|
157
|
+
uint256[] memory idxs = new uint256[](2);
|
|
158
|
+
idxs[0] = 0; idxs[1] = 0;
|
|
159
|
+
address[] memory users = new address[](2);
|
|
160
|
+
users[0] = alice; users[1] = alice;
|
|
161
|
+
uint256[] memory amts = new uint256[](2);
|
|
162
|
+
amts[0] = 100 ether; amts[1] = 5 ether;
|
|
163
|
+
bytes32[][] memory proofs = new bytes32[][](2);
|
|
164
|
+
proofs[0] = _proof(leaves1, 0);
|
|
165
|
+
proofs[1] = _proof(leaves2, 0);
|
|
166
|
+
|
|
167
|
+
distributor.claimMany(cids, tokens, idxs, users, amts, proofs);
|
|
168
|
+
assertTrue(distributor.isClaimed(cid1, IERC20(address(token)), 0));
|
|
169
|
+
assertTrue(distributor.isClaimed(cid2, IERC20(address(token)), 0));
|
|
170
|
+
assertEq(token.balanceOf(alice), 105 ether);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function test_AdminWithdraw() public {
|
|
174
|
+
uint256 balBefore = token.balanceOf(address(distributor));
|
|
175
|
+
distributor.withdraw(IERC20(address(token)), 1 ether);
|
|
176
|
+
assertEq(token.balanceOf(address(distributor)), balBefore - 1 ether);
|
|
177
|
+
assertEq(token.balanceOf(deployer), 1 ether);
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function test_OnlyOwnerGuards() public {
|
|
181
|
+
string memory cid = "daily:2025-10-01";
|
|
182
|
+
bytes32 dummyRoot = bytes32(uint256(1));
|
|
183
|
+
|
|
184
|
+
vm.prank(alice);
|
|
185
|
+
vm.expectRevert(bytes("MerkleRewards: must have admin role"));
|
|
186
|
+
distributor.publishRoot(cid, IERC20(address(token)), dummyRoot);
|
|
187
|
+
|
|
188
|
+
vm.prank(alice);
|
|
189
|
+
vm.expectRevert();
|
|
190
|
+
distributor.withdraw(IERC20(address(token)), 1);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function test_AdminRoleCanPublishRoot() public {
|
|
194
|
+
// grant admin to alice and publish
|
|
195
|
+
distributor.addAdmin(alice);
|
|
196
|
+
assertTrue(distributor.isAdmin(alice));
|
|
197
|
+
|
|
198
|
+
string memory cid = "daily:2025-10-05";
|
|
199
|
+
bytes32[] memory leaves = new bytes32[](1);
|
|
200
|
+
leaves[0] = _leaf(0, alice, address(token), 1 ether, cid);
|
|
201
|
+
bytes32 root = _buildRoot(leaves);
|
|
202
|
+
|
|
203
|
+
vm.prank(alice);
|
|
204
|
+
distributor.publishRoot(cid, IERC20(address(token)), root);
|
|
205
|
+
assertEq(distributor.getRoot(cid, IERC20(address(token))), root);
|
|
206
|
+
|
|
207
|
+
// remove admin and ensure access revoked
|
|
208
|
+
distributor.removeAdmin(alice);
|
|
209
|
+
assertFalse(distributor.isAdmin(alice));
|
|
210
|
+
vm.prank(alice);
|
|
211
|
+
vm.expectRevert(bytes("MerkleRewards: must have admin role"));
|
|
212
|
+
distributor.publishRoot(cid, IERC20(address(token)), root);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
function test_RootNotSet_RevertOnClaim() public {
|
|
216
|
+
string memory cid = "weekly:2025-W41";
|
|
217
|
+
bytes32[] memory proof = new bytes32[](0);
|
|
218
|
+
vm.expectRevert(bytes("MerkleRewards: root not set"));
|
|
219
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 1, proof);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
function test_RootUpdateInvalidatesOldProof() public {
|
|
223
|
+
string memory cid = "monthly:2025-10";
|
|
224
|
+
|
|
225
|
+
// first root
|
|
226
|
+
bytes32[] memory leaves1 = new bytes32[](1);
|
|
227
|
+
leaves1[0] = _leaf(0, alice, address(token), 10 ether, cid);
|
|
228
|
+
bytes32 root1 = _buildRoot(leaves1);
|
|
229
|
+
distributor.publishRoot(cid, IERC20(address(token)), root1);
|
|
230
|
+
bytes32[] memory proof1 = _proof(leaves1, 0);
|
|
231
|
+
|
|
232
|
+
// update root with different allocation
|
|
233
|
+
bytes32[] memory leaves2 = new bytes32[](1);
|
|
234
|
+
leaves2[0] = _leaf(0, alice, address(token), 20 ether, cid);
|
|
235
|
+
bytes32 root2 = _buildRoot(leaves2);
|
|
236
|
+
distributor.publishRoot(cid, IERC20(address(token)), root2);
|
|
237
|
+
|
|
238
|
+
// old proof must fail now
|
|
239
|
+
vm.expectRevert(bytes("MerkleRewards: invalid proof"));
|
|
240
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 10 ether, proof1);
|
|
241
|
+
|
|
242
|
+
// new proof succeeds
|
|
243
|
+
bytes32[] memory proof2 = _proof(leaves2, 0);
|
|
244
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 20 ether, proof2);
|
|
245
|
+
assertEq(token.balanceOf(alice), 20 ether);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function test_ClaimWithWrongTokenOrContest() public {
|
|
249
|
+
string memory cid = "daily:2025-10-02";
|
|
250
|
+
bytes32[] memory leaves = new bytes32[](1);
|
|
251
|
+
leaves[0] = _leaf(0, alice, address(token), 5 ether, cid);
|
|
252
|
+
distributor.publishRoot(cid, IERC20(address(token)), _buildRoot(leaves));
|
|
253
|
+
bytes32[] memory proof = _proof(leaves, 0);
|
|
254
|
+
|
|
255
|
+
// wrong token -> root not set for that key
|
|
256
|
+
ERC20MinterPauser other = new ERC20MinterPauser("Other", "OTH");
|
|
257
|
+
vm.expectRevert(bytes("MerkleRewards: root not set"));
|
|
258
|
+
distributor.claim(cid, IERC20(address(other)), 0, alice, 5 ether, proof);
|
|
259
|
+
|
|
260
|
+
// wrong amount -> invalid proof
|
|
261
|
+
vm.expectRevert(bytes("MerkleRewards: invalid proof"));
|
|
262
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 6 ether, proof);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function test_IsClaimedReflectsState() public {
|
|
266
|
+
string memory cid = "daily:2025-10-03";
|
|
267
|
+
bytes32[] memory leaves = new bytes32[](1);
|
|
268
|
+
leaves[0] = _leaf(0, alice, address(token), 1 ether, cid);
|
|
269
|
+
distributor.publishRoot(cid, IERC20(address(token)), _buildRoot(leaves));
|
|
270
|
+
assertFalse(distributor.isClaimed(cid, IERC20(address(token)), 0));
|
|
271
|
+
distributor.claim(cid, IERC20(address(token)), 0, alice, 1 ether, _proof(leaves, 0));
|
|
272
|
+
assertTrue(distributor.isClaimed(cid, IERC20(address(token)), 0));
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
function test_ClaimMany_LengthMismatchReverts() public {
|
|
276
|
+
string[] memory cid = new string[](1);
|
|
277
|
+
cid[0] = "daily:2025-10-04";
|
|
278
|
+
IERC20[] memory toks = new IERC20[](1);
|
|
279
|
+
toks[0] = IERC20(address(token));
|
|
280
|
+
uint256[] memory idx = new uint256[](1);
|
|
281
|
+
idx[0] = 0;
|
|
282
|
+
address[] memory users = new address[](1);
|
|
283
|
+
users[0] = alice;
|
|
284
|
+
// amounts empty to force mismatch
|
|
285
|
+
uint256[] memory amts = new uint256[](0);
|
|
286
|
+
bytes32[][] memory proofs = new bytes32[][](1);
|
|
287
|
+
proofs[0] = new bytes32[](0);
|
|
288
|
+
|
|
289
|
+
vm.expectRevert(bytes("MerkleRewards: arrays length mismatch"));
|
|
290
|
+
distributor.claimMany(cid, toks, idx, users, amts, proofs);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function test_ClaimMany_DuplicateIndexReverts() public {
|
|
294
|
+
string memory cid = "weekly:2025-W42";
|
|
295
|
+
bytes32[] memory leaves = new bytes32[](1);
|
|
296
|
+
leaves[0] = _leaf(0, alice, address(token), 3 ether, cid);
|
|
297
|
+
distributor.publishRoot(cid, IERC20(address(token)), _buildRoot(leaves));
|
|
298
|
+
|
|
299
|
+
string[] memory cids = new string[](2);
|
|
300
|
+
cids[0] = cid; cids[1] = cid;
|
|
301
|
+
IERC20[] memory toks = new IERC20[](2);
|
|
302
|
+
toks[0] = IERC20(address(token)); toks[1] = IERC20(address(token));
|
|
303
|
+
uint256[] memory idxs = new uint256[](2);
|
|
304
|
+
idxs[0] = 0; idxs[1] = 0; // duplicate same index
|
|
305
|
+
address[] memory users = new address[](2);
|
|
306
|
+
users[0] = alice; users[1] = alice;
|
|
307
|
+
uint256[] memory amts = new uint256[](2);
|
|
308
|
+
amts[0] = 3 ether; amts[1] = 3 ether;
|
|
309
|
+
bytes32[][] memory proofs = new bytes32[][](2);
|
|
310
|
+
proofs[0] = _proof(leaves, 0);
|
|
311
|
+
proofs[1] = _proof(leaves, 0);
|
|
312
|
+
|
|
313
|
+
vm.expectRevert(bytes("MerkleRewards: already claimed"));
|
|
314
|
+
distributor.claimMany(cids, toks, idxs, users, amts, proofs);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
// SPDX-License-Identifier: GPL-2.0
|
|
2
|
-
pragma solidity ^0.8.26;
|
|
3
|
-
|
|
4
|
-
import {Script} from "forge-std/Script.sol";
|
|
5
|
-
import {console} from "forge-std/console.sol";
|
|
6
|
-
// Import your contracts here
|
|
7
|
-
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
|
|
8
|
-
import {PredictionMarketV3_3, IWETH} from "../contracts/PredictionMarketV3_3.sol";
|
|
9
|
-
import {IPredictionMarketV3Manager} from "../contracts/IPredictionMarketV3Manager.sol";
|
|
10
|
-
import {PredictionMarketV3Manager, FantasyERC20} from "../contracts/PredictionMarketV3Manager.sol";
|
|
11
|
-
import {IRealityETH_ERC20} from "../contracts/IRealityETH_ERC20.sol";
|
|
12
|
-
|
|
13
|
-
contract UpdateMarket is Script {
|
|
14
|
-
function run() public {
|
|
15
|
-
|
|
16
|
-
vm.startBroadcast();
|
|
17
|
-
|
|
18
|
-
address payable PREDICTION_MARKET_V3_3 = payable(address(0x3e0F5F8F5Fb043aBFA475C0308417Bf72c463289));
|
|
19
|
-
address PREDICTION_MARKET_V3_MANAGER = address(0x68dDc91CCC06e63d74905D901A30edEA7C77EebE);
|
|
20
|
-
|
|
21
|
-
PredictionMarketV3_3.MarketState state = PredictionMarketV3_3(PREDICTION_MARKET_V3_3).getMarketState(486);
|
|
22
|
-
console2.log("state: ", state);
|
|
23
|
-
|
|
24
|
-
PredictionMarketV3_3.MarketUpdateDescription memory description = PredictionMarketV3_3.MarketUpdateDescription({
|
|
25
|
-
closesAtTimestamp: 1762066800,
|
|
26
|
-
balance: 456538064447348172635074428,
|
|
27
|
-
liquidity: 120000000000000000000000000,
|
|
28
|
-
sharesAvailable: 1272835104225672313766121101,
|
|
29
|
-
state: PredictionMarketV3_3.MarketState.open,
|
|
30
|
-
resolution: PredictionMarketV3_3.MarketResolution({
|
|
31
|
-
resolved: false,
|
|
32
|
-
realitio: IRealityETH_ERC20(0x71D76Ff3C2729071B2c52A667197d9f715029F2c),
|
|
33
|
-
outcomeId: 115792089237316195423570985008687907853269984665640564039457584007913129639935,
|
|
34
|
-
questionId: 0x21d6c6c195572d82a7d0a7ba677251dfd3839b21e09df9b39ae36ec99fa6744d,
|
|
35
|
-
realitioTimeout: 3600
|
|
36
|
-
}),
|
|
37
|
-
feesPoolWeight: 0,
|
|
38
|
-
feesTreasury: address(0xBc30e9765Dc8c735206c76DE96d369754eBbcc1f),
|
|
39
|
-
feesDistributor: address(0xBc30e9765Dc8c735206c76DE96d369754eBbcc1f),
|
|
40
|
-
buyFees: PredictionMarketV3_3.Fees({fee: 0, treasuryFee: 0, distributorFee: 0}),
|
|
41
|
-
sellFees: PredictionMarketV3_3.Fees({fee: 0, treasuryFee: 0, distributorFee: 0}),
|
|
42
|
-
outcomeCount: 5,
|
|
43
|
-
token: IERC20(0x0b07cf011B6e2b7E0803b892d97f751659940F23),
|
|
44
|
-
manager: IPredictionMarketV3Manager(0x2EbD002d755bdFadb9e5549aA00a80bd7fa408AE),
|
|
45
|
-
creator: address(0xBc30e9765Dc8c735206c76DE96d369754eBbcc1f),
|
|
46
|
-
paused: false
|
|
47
|
-
});
|
|
48
|
-
|
|
49
|
-
PredictionMarketV3_3(PREDICTION_MARKET_V3_3).updateMarket(486, description);
|
|
50
|
-
PredictionMarketV3_3(PREDICTION_MARKET_V3_3).updateMarketResolution(486, description);
|
|
51
|
-
|
|
52
|
-
state = PredictionMarketV3_3(PREDICTION_MARKET_V3_3).getMarketState(486);
|
|
53
|
-
console2.log("new state: ", state);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|