-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBinaryModule.sol
More file actions
145 lines (120 loc) · 6.66 KB
/
Copy pathBinaryModule.sol
File metadata and controls
145 lines (120 loc) · 6.66 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.34;
import { Initializable } from "@solady/src/utils/Initializable.sol";
import { UUPSUpgradeable } from "@solady/src/utils/UUPSUpgradeable.sol";
import { ConditionId, ConditionIdLib, ResolutionChain } from "@polymarket-v2/src/libraries/Ids.sol";
import { ModuleIds } from "@polymarket-v2/src/libraries/ModuleIds.sol";
import { BaseModule } from "./abstract/BaseModule.sol";
import { BinaryMigrationMixin } from "./migration/BinaryMigrationMixin.sol";
/// @title BinaryModule
/// @author Polymarket
/// @notice Unified module for binary markets and legacy binary migration
/// @dev Registered at moduleId=1 (BINARY)
/// ConditionId encodes:
/// [moduleId(8) | baseHash(128) | arity(16) | reserved(64) | resolutionChain(16) |
/// conditionIndex(16) | outcomeIndex(8)]
/// Binary conditions use arity = 0, conditionIndex = 0, outcomeIndex = 0.
contract BinaryModule is UUPSUpgradeable, Initializable, BaseModule, BinaryMigrationMixin {
/*--------------------------------------------------------------
CONSTRUCTOR
--------------------------------------------------------------*/
/// @notice Initialize the BinaryModule contract
/// @param _positionManager The PositionManager contract address
/// @param _conditionalTokens The legacy CTF contract address
/// @param _usdceToken The USDC.e token address
/// @param _moduleResolutionChain Chain enum allowed to resolve module conditions
constructor(
address _positionManager,
address _conditionalTokens,
address _usdceToken,
ResolutionChain _moduleResolutionChain
) BaseModule(_positionManager, _moduleResolutionChain) BinaryMigrationMixin(_conditionalTokens, _usdceToken) {
_disableInitializers();
}
/*--------------------------------------------------------------
INITIALIZER
--------------------------------------------------------------*/
/// @notice Initializes the proxied module owner and admin.
/// @param _owner The owner address.
/// @param _admin The initial admin address.
function initialize(address _owner, address _admin) external initializer {
_initializeOwner(_owner);
_grantRoles(_admin, _ROLE_0);
}
/*--------------------------------------------------------------
ONLY RESOLVER
--------------------------------------------------------------*/
/// @notice Report result for a binary condition
/// @param _conditionId The condition ID to report on
/// @param _result The result array [yes, no] summing to 1e6
function reportResult(ConditionId _conditionId, uint256[] calldata _result)
external
override
onlyResolver(_conditionId)
{
require(_conditionId.moduleId() == ModuleIds.BINARY, InvalidEventId());
bool isMigrationCondition_ = _isMigrationCondition(_conditionId);
// Resolver roles cannot resolve migration conditions.
if (isMigrationCondition_ && hasAllRoles(msg.sender, RESOLVER_ROLE)) revert MigrationNotSupported();
uint256[] storage storedResult = result[_conditionId];
if (storedResult.length > 0) {
// If the result being proposed by the resolver or bridge is different from the stored result, revert.
// This is catastrophic and should never happen.
if (_result.length != 2 || _result[0] != storedResult[0] || _result[1] != storedResult[1]) {
revert ExistingPayoutMismatch();
}
// The condition is already resolved; if the caller is a resolver role, revert.
// Resolvers that are calling should handle possible reverts.
if (hasAllRoles(msg.sender, RESOLVER_ROLE)) revert ConditionAlreadyResolved();
// The condition is already resolved; if the caller is a bridge role, return silently.
return;
}
// If the condition is a migration condition, resolve it and return.
if (isMigrationCondition_) {
_resolveMigrationCondition(_conditionId);
// Verify that the result being proposed by the bridge is equal to the result we just got from the CTF.
// Something is wrong if this is not the case.
uint256[] storage resolvedResult = result[_conditionId];
if (_result.length != 2 || _result[0] != resolvedResult[0] || _result[1] != resolvedResult[1]) {
revert ExistingPayoutMismatch();
}
return;
}
// The condition is not a migration condition, and has not been resolved yet.
// (It is a native condition being resolved by a resolver or bridge).
_storeResult(_conditionId, _result);
emit ResultReported(msg.sender, _conditionId, _result);
}
/*--------------------------------------------------------------
MODULE IDENTITY
--------------------------------------------------------------*/
/// @notice Returns the module identifier for binary markets
/// @return The BINARY module ID constant
function moduleId() external pure override returns (uint256) {
return ModuleIds.BINARY;
}
/*--------------------------------------------------------------
PUBLIC
--------------------------------------------------------------*/
/// @notice Get condition ID from data
/// @dev Uses conditionIndex=0 for binary
/// @param _data Data used to derive the condition ID
/// @return The derived condition ID
function getConditionId(bytes calldata _data) public view returns (ConditionId) {
return ConditionIdLib.encodeFromData(ModuleIds.BINARY, 0, _data, RESOLUTION_CHAIN);
}
/*--------------------------------------------------------------
UUPS AUTHORIZATION
--------------------------------------------------------------*/
/// @dev Restricts upgrades to the owner and enforces immutable config compatibility.
/// @param newImplementation The proposed implementation contract.
function _authorizeUpgrade(address newImplementation) internal view override onlyOwner {
BinaryModule newImpl = BinaryModule(newImplementation);
if (
newImpl.moduleId() != ModuleIds.BINARY || address(newImpl.POSITION_MANAGER()) != address(POSITION_MANAGER)
|| address(newImpl.COLLATERAL_TOKEN()) != address(COLLATERAL_TOKEN)
|| address(newImpl.CONDITIONAL_TOKENS()) != address(CONDITIONAL_TOKENS) || newImpl.USDCE() != USDCE
|| newImpl.RESOLUTION_CHAIN() != RESOLUTION_CHAIN
) revert IncompatibleImplementation();
}
}