@dolomite-exchange/dolomite-margin 0.2.6 → 0.2.7
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/build/contracts/Account.json +11 -11
- package/build/contracts/Actions.json +11 -11
- package/build/contracts/Address.json +1 -1
- package/build/contracts/Admin.json +23 -23
- package/build/contracts/AdminImpl.json +35 -307
- package/build/contracts/AdvancedMath.json +7 -7
- package/build/contracts/AmmRebalancerProxy.json +577 -621
- package/build/contracts/AmmRebalancerProxyV1.json +78 -32
- package/build/contracts/Babylonian.json +1 -1
- package/build/contracts/Bits.json +9 -9
- package/build/contracts/Cache.json +13 -13
- package/build/contracts/ChainlinkPriceOracleV1.json +16 -16
- package/build/contracts/Context.json +1 -1
- package/build/contracts/CustomTestToken.json +9 -9
- package/build/contracts/Decimal.json +9 -9
- package/build/contracts/DelayedMultiSig.json +9 -9
- package/build/contracts/DolomiteAmmERC20.json +11 -11
- package/build/contracts/DolomiteAmmFactory.json +14 -52
- package/build/contracts/DolomiteAmmLibrary.json +24 -24
- package/build/contracts/DolomiteAmmPair.json +27 -27
- package/build/contracts/DolomiteAmmRouterProxy.json +30 -363
- package/build/contracts/DolomiteMargin.json +21 -67
- package/build/contracts/DoubleExponentInterestSetter.json +15 -21
- package/build/contracts/EnumerableSet.json +7 -7
- package/build/contracts/ErroringOmiseToken.json +9 -9
- package/build/contracts/ErroringToken.json +10 -10
- package/build/contracts/Events.json +17 -17
- package/build/contracts/ExcessivelySafeCall.json +35 -35
- package/build/contracts/Exchange.json +15 -15
- package/build/contracts/Expiry.json +36 -36
- package/build/contracts/Getters.json +33 -33
- package/build/contracts/IAutoTrader.json +9 -9
- package/build/contracts/ICallee.json +7 -7
- package/build/contracts/IChainlinkAggregator.json +5 -5
- package/build/contracts/IDolomiteAmmERC20.json +5 -5
- package/build/contracts/IDolomiteAmmFactory.json +9 -9
- package/build/contracts/IDolomiteAmmPair.json +9 -9
- package/build/contracts/IDolomiteMargin.json +23 -23
- package/build/contracts/IERC20.json +1 -1
- package/build/contracts/IERC20Detailed.json +5 -5
- package/build/contracts/IExchangeWrapper.json +5 -5
- package/build/contracts/IExpiry.json +9 -9
- package/build/contracts/IInterestSetter.json +7 -7
- package/build/contracts/ILiquidationCallback.json +7 -7
- package/build/contracts/IMakerOracle.json +5 -5
- package/build/contracts/IOasisDex.json +5 -5
- package/build/contracts/IPriceOracle.json +7 -7
- package/build/contracts/IRecyclable.json +9 -9
- package/build/contracts/ITransferProxy.json +5 -5
- package/build/contracts/IUniswapV2Callee.json +5 -5
- package/build/contracts/IUniswapV2Factory.json +5 -5
- package/build/contracts/IUniswapV2Pair.json +5 -5
- package/build/contracts/IUniswapV2Router.json +5 -5
- package/build/contracts/IWETH.json +5 -5
- package/build/contracts/Interest.json +15 -15
- package/build/contracts/LiquidateOrVaporizeImpl.json +32 -83
- package/build/contracts/LiquidatorProxyHelper.json +23 -23
- package/build/contracts/LiquidatorProxyV1.json +30 -36
- package/build/contracts/LiquidatorProxyV1WithAmm.json +49 -105
- package/build/contracts/Math.json +1 -1
- package/build/contracts/Migrations.json +8 -14
- package/build/contracts/Monetary.json +7 -7
- package/build/contracts/MultiCall.json +8 -14
- package/build/contracts/MultiSig.json +7 -7
- package/build/contracts/OmiseToken.json +8 -8
- package/build/contracts/OnlyDolomiteMargin.json +11 -11
- package/build/contracts/Operation.json +15 -15
- package/build/contracts/OperationImpl.json +39 -47
- package/build/contracts/Ownable.json +1 -1
- package/build/contracts/PartiallyDelayedMultiSig.json +9 -9
- package/build/contracts/PayableProxy.json +17 -23
- package/build/contracts/Permission.json +11 -11
- package/build/contracts/PolynomialInterestSetter.json +13 -13
- package/build/contracts/RecyclableTokenProxy.json +25 -25
- package/build/contracts/ReentrancyGuard.json +1 -1
- package/build/contracts/Require.json +7 -7
- package/build/contracts/SafeERC20.json +1 -1
- package/build/contracts/SafeETH.json +7 -7
- package/build/contracts/SafeLiquidationCallback.json +17 -17
- package/build/contracts/SafeMath.json +1 -1
- package/build/contracts/SignedOperationProxy.json +21 -104
- package/build/contracts/SimpleFeeOwner.json +18 -63
- package/build/contracts/State.json +9 -9
- package/build/contracts/Storage.json +37 -37
- package/build/contracts/TestAmmRebalancerProxy.json +32 -58
- package/build/contracts/TestAutoTrader.json +22 -22
- package/build/contracts/TestBtcUsdChainlinkAggregator.json +10 -10
- package/build/contracts/TestCallee.json +19 -19
- package/build/contracts/TestChainlinkPriceOracleV1.json +10 -94
- package/build/contracts/TestCounter.json +7 -7
- package/build/contracts/TestDaiUsdChainlinkAggregator.json +11 -11
- package/build/contracts/TestDolomiteMargin.json +22 -22
- package/build/contracts/TestDoubleExponentInterestSetter.json +10 -10
- package/build/contracts/TestEthUsdChainlinkAggregator.json +11 -11
- package/build/contracts/TestExchangeWrapper.json +28 -28
- package/build/contracts/TestInterestSetter.json +13 -13
- package/build/contracts/TestLib.json +22 -22
- package/build/contracts/TestLinkUsdChainlinkAggregator.json +11 -11
- package/build/contracts/TestLiquidateCallback.json +719 -719
- package/build/contracts/TestLiquidationCallback.json +13 -13
- package/build/contracts/TestLrcEthChainlinkAggregator.json +11 -11
- package/build/contracts/TestMakerOracle.json +10 -10
- package/build/contracts/TestMaticUsdChainlinkAggregator.json +10 -10
- package/build/contracts/TestOasisDex.json +12 -12
- package/build/contracts/TestOperationImpl.json +14 -14
- package/build/contracts/TestPolynomialInterestSetter.json +10 -10
- package/build/contracts/TestPriceAggregator.json +9 -9
- package/build/contracts/TestPriceOracle.json +13 -13
- package/build/contracts/TestRecyclableToken.json +9 -9
- package/build/contracts/TestSimpleCallee.json +15 -15
- package/build/contracts/TestToken.json +9 -9
- package/build/contracts/TestTrader.json +17 -17
- package/build/contracts/TestUniswapAmmRebalancerProxy.json +16 -16
- package/build/contracts/TestUsdcUsdChainlinkAggregator.json +11 -11
- package/build/contracts/TestWETH.json +9 -9
- package/build/contracts/Time.json +9 -9
- package/build/contracts/Token.json +9 -9
- package/build/contracts/TokenA.json +10 -10
- package/build/contracts/TokenB.json +10 -10
- package/build/contracts/TokenC.json +10 -10
- package/build/contracts/TokenD.json +10 -10
- package/build/contracts/TokenE.json +10 -10
- package/build/contracts/TokenF.json +10 -10
- package/build/contracts/TransferProxy.json +22 -28
- package/build/contracts/TypedSignature.json +9 -9
- package/build/contracts/Types.json +9 -9
- package/build/contracts/UQ112x112.json +7 -7
- package/build/contracts/UniswapV2ERC20.json +7 -7
- package/build/contracts/UniswapV2Factory.json +12 -12
- package/build/contracts/UniswapV2Library.json +20 -20
- package/build/contracts/UniswapV2Pair.json +17 -17
- package/build/contracts/UniswapV2Router02.json +16 -16
- package/build/contracts/WETH9.json +1 -1
- package/contracts/external/amm/DolomiteAmmERC20.sol +135 -0
- package/contracts/external/amm/DolomiteAmmFactory.sol +122 -0
- package/contracts/external/amm/DolomiteAmmPair.sol +573 -0
- package/contracts/external/amm/SimpleFeeOwner.sol +107 -0
- package/contracts/external/helpers/LiquidatorProxyHelper.sol +252 -0
- package/contracts/external/helpers/OnlyDolomiteMargin.sol +63 -0
- package/contracts/external/interestsetters/DoubleExponentInterestSetter.sol +212 -0
- package/contracts/external/interestsetters/PolynomialInterestSetter.sol +205 -0
- package/contracts/external/interfaces/IChainlinkAggregator.sol +33 -0
- package/contracts/external/interfaces/IDolomiteAmmERC20.sol +52 -0
- package/contracts/external/interfaces/IDolomiteAmmFactory.sol +42 -0
- package/contracts/external/interfaces/IDolomiteAmmPair.sol +116 -0
- package/contracts/external/interfaces/IExpiry.sol +70 -0
- package/contracts/external/interfaces/IMakerOracle.sol +52 -0
- package/contracts/external/interfaces/IOasisDex.sol +326 -0
- package/contracts/external/interfaces/ITransferProxy.sol +53 -0
- package/contracts/external/interfaces/IUniswapV2Router.sol +134 -0
- package/contracts/external/lib/AdvancedMath.sol +23 -0
- package/contracts/external/lib/DolomiteAmmLibrary.sol +323 -0
- package/contracts/external/lib/TypedSignature.sol +120 -0
- package/contracts/external/lib/UQ112x112.sol +22 -0
- package/contracts/external/multisig/DelayedMultiSig.sol +206 -0
- package/contracts/external/multisig/MultiSig.sol +571 -0
- package/contracts/external/multisig/PartiallyDelayedMultiSig.sol +174 -0
- package/contracts/external/oracles/ChainlinkPriceOracleV1.sol +197 -0
- package/contracts/external/oracles/TestChainlinkPriceOracleV1.sol +98 -0
- package/contracts/external/proxies/AmmRebalancerProxyV1.sol +465 -0
- package/contracts/external/proxies/DolomiteAmmRouterProxy.sol +877 -0
- package/contracts/external/proxies/LiquidatorProxyV1.sol +507 -0
- package/contracts/external/proxies/LiquidatorProxyV1WithAmm.sol +574 -0
- package/contracts/external/proxies/PayableProxy.sol +146 -0
- package/contracts/external/proxies/RecyclableTokenProxy.sol +463 -0
- package/contracts/external/proxies/SignedOperationProxy.sol +553 -0
- package/contracts/external/proxies/TransferProxy.sol +207 -0
- package/contracts/external/traders/Expiry.sol +532 -0
- package/contracts/external/uniswap-v2/UniswapV2ERC20.sol +118 -0
- package/contracts/external/uniswap-v2/UniswapV2Factory.sol +67 -0
- package/contracts/external/uniswap-v2/UniswapV2Pair.sol +283 -0
- package/contracts/external/uniswap-v2/UniswapV2Router02.sol +566 -0
- package/contracts/external/uniswap-v2/interfaces/IUniswapV2Callee.sol +13 -0
- package/contracts/external/uniswap-v2/interfaces/IUniswapV2Factory.sol +18 -0
- package/contracts/external/uniswap-v2/interfaces/IUniswapV2Pair.sol +67 -0
- package/contracts/external/uniswap-v2/interfaces/IWETH.sol +7 -0
- package/contracts/external/uniswap-v2/libraries/SafeETH.sol +29 -0
- package/contracts/external/uniswap-v2/libraries/UniswapV2Library.sol +117 -0
- package/contracts/external/utils/MultiCall.sol +95 -0
- package/contracts/protocol/impl/artifacts/OperationImpl.json +80 -0
- package/contracts/protocol/impl/artifacts/OperationImpl_metadata.json +193 -0
- package/dist/build/published_contracts/AdminImpl.json +2 -2
- package/dist/build/published_contracts/AmmRebalancerProxyV1.json +5 -0
- package/dist/build/published_contracts/ChainlinkPriceOracleV1.json +1 -1
- package/dist/build/published_contracts/DolomiteAmmFactory.json +1 -1
- package/dist/build/published_contracts/DolomiteAmmRouterProxy.json +1 -1
- package/dist/build/published_contracts/DoubleExponentInterestSetter.json +2 -2
- package/dist/build/published_contracts/Expiry.json +1 -1
- package/dist/build/published_contracts/LiquidatorProxyV1.json +1 -1
- package/dist/build/published_contracts/LiquidatorProxyV1WithAmm.json +1 -1
- package/dist/build/published_contracts/MultiCall.json +1 -1
- package/dist/build/published_contracts/PayableProxy.json +2 -2
- package/dist/build/published_contracts/SignedOperationProxy.json +2 -2
- package/dist/build/published_contracts/SimpleFeeOwner.json +1 -1
- package/dist/build/published_contracts/TestUniswapAmmRebalancerProxy.json +140 -0
- package/dist/build/published_contracts/TransferProxy.json +1 -1
- package/dist/src/lib/Contracts.d.ts +3 -1
- package/dist/src/lib/Contracts.js +7 -3
- package/dist/src/lib/Contracts.js.map +1 -1
- package/package.json +2 -1
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
/*
|
|
2
|
+
|
|
3
|
+
Copyright 2021 Dolomite.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
pragma solidity >=0.5.0;
|
|
20
|
+
|
|
21
|
+
import "@openzeppelin/contracts/math/SafeMath.sol";
|
|
22
|
+
|
|
23
|
+
import "../../protocol/lib/Require.sol";
|
|
24
|
+
|
|
25
|
+
import "../uniswap-v2/interfaces/IUniswapV2Pair.sol";
|
|
26
|
+
|
|
27
|
+
import "../interfaces/IDolomiteAmmFactory.sol";
|
|
28
|
+
import "../interfaces/IDolomiteAmmPair.sol";
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
library DolomiteAmmLibrary {
|
|
32
|
+
using SafeMath for uint;
|
|
33
|
+
|
|
34
|
+
bytes32 private constant FILE = "DolomiteAmmLibrary";
|
|
35
|
+
bytes32 private constant PAIR_INIT_CODE_HASH = 0x752b18f9c5dbceeac7339c1e7d27b76a85637748e21b577cfb0b8768a8fd5ce7;
|
|
36
|
+
|
|
37
|
+
function getPairInitCodeHash() internal pure returns (bytes32) {
|
|
38
|
+
return PAIR_INIT_CODE_HASH;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function getPools(
|
|
42
|
+
address factory,
|
|
43
|
+
address[] memory path
|
|
44
|
+
) internal pure returns (address[] memory) {
|
|
45
|
+
return getPools(factory, PAIR_INIT_CODE_HASH, path);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function getPools(
|
|
49
|
+
address factory,
|
|
50
|
+
bytes32 initCodeHash,
|
|
51
|
+
address[] memory path
|
|
52
|
+
) internal pure returns (address[] memory) {
|
|
53
|
+
Require.that(
|
|
54
|
+
path.length >= 2,
|
|
55
|
+
FILE,
|
|
56
|
+
"invalid path length"
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
address[] memory pools = new address[](path.length - 1);
|
|
60
|
+
for (uint i = 0; i < path.length - 1; i++) {
|
|
61
|
+
pools[i] = pairFor(
|
|
62
|
+
factory,
|
|
63
|
+
path[i],
|
|
64
|
+
path[i + 1],
|
|
65
|
+
initCodeHash
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return pools;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// returns sorted token addresses, used to handle return values from pairs sorted in this order
|
|
72
|
+
function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
|
|
73
|
+
Require.that(
|
|
74
|
+
tokenA != tokenB,
|
|
75
|
+
FILE,
|
|
76
|
+
"identical addresses"
|
|
77
|
+
);
|
|
78
|
+
(token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
|
|
79
|
+
Require.that(
|
|
80
|
+
token0 != address(0),
|
|
81
|
+
FILE,
|
|
82
|
+
"zero address"
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// calculates the CREATE2 address for a pair without making any external calls
|
|
87
|
+
function pairFor(address factory, address tokenA, address tokenB) internal pure returns (address pair) {
|
|
88
|
+
return pairFor(
|
|
89
|
+
factory,
|
|
90
|
+
tokenA,
|
|
91
|
+
tokenB,
|
|
92
|
+
PAIR_INIT_CODE_HASH
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function pairFor(
|
|
97
|
+
address factory,
|
|
98
|
+
address tokenA,
|
|
99
|
+
address tokenB,
|
|
100
|
+
bytes32 initCodeHash
|
|
101
|
+
) internal pure returns (address pair) {
|
|
102
|
+
(address token0, address token1) = sortTokens(tokenA, tokenB);
|
|
103
|
+
pair = address(
|
|
104
|
+
uint(
|
|
105
|
+
keccak256(
|
|
106
|
+
abi.encodePacked(
|
|
107
|
+
hex"ff",
|
|
108
|
+
factory,
|
|
109
|
+
keccak256(abi.encodePacked(token0, token1)),
|
|
110
|
+
initCodeHash
|
|
111
|
+
)
|
|
112
|
+
)
|
|
113
|
+
)
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// fetches and sorts the reserves for a pair
|
|
118
|
+
function getReservesWei(
|
|
119
|
+
address factory,
|
|
120
|
+
address tokenA,
|
|
121
|
+
address tokenB
|
|
122
|
+
) internal view returns (uint reserveA, uint reserveB) {
|
|
123
|
+
return getReservesWei(
|
|
124
|
+
factory,
|
|
125
|
+
PAIR_INIT_CODE_HASH,
|
|
126
|
+
tokenA,
|
|
127
|
+
tokenB
|
|
128
|
+
);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function getReserves(
|
|
132
|
+
address factory,
|
|
133
|
+
bytes32 initCodeHash,
|
|
134
|
+
address tokenA,
|
|
135
|
+
address tokenB
|
|
136
|
+
) internal view returns (uint reserveA, uint reserveB) {
|
|
137
|
+
(address token0,) = sortTokens(tokenA, tokenB);
|
|
138
|
+
(uint reserve0, uint reserve1,) = IUniswapV2Pair(
|
|
139
|
+
pairFor(
|
|
140
|
+
factory,
|
|
141
|
+
tokenA,
|
|
142
|
+
tokenB,
|
|
143
|
+
initCodeHash
|
|
144
|
+
)
|
|
145
|
+
).getReserves();
|
|
146
|
+
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function getReservesWei(
|
|
150
|
+
address factory,
|
|
151
|
+
bytes32 initCodeHash,
|
|
152
|
+
address tokenA,
|
|
153
|
+
address tokenB
|
|
154
|
+
) internal view returns (uint reserveA, uint reserveB) {
|
|
155
|
+
(address token0,) = sortTokens(tokenA, tokenB);
|
|
156
|
+
(uint reserve0, uint reserve1,) = IDolomiteAmmPair(
|
|
157
|
+
pairFor(
|
|
158
|
+
factory,
|
|
159
|
+
tokenA,
|
|
160
|
+
tokenB,
|
|
161
|
+
initCodeHash
|
|
162
|
+
)
|
|
163
|
+
).getReservesWei();
|
|
164
|
+
(reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
|
|
168
|
+
function quote(uint amountA, uint reserveA, uint reserveB) internal pure returns (uint amountB) {
|
|
169
|
+
Require.that(
|
|
170
|
+
amountA > 0,
|
|
171
|
+
FILE,
|
|
172
|
+
"insufficient amount"
|
|
173
|
+
);
|
|
174
|
+
Require.that(
|
|
175
|
+
reserveA > 0 && reserveB > 0,
|
|
176
|
+
FILE,
|
|
177
|
+
"insufficient liquidity"
|
|
178
|
+
);
|
|
179
|
+
amountB = amountA.mul(reserveB) / reserveA;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
|
|
183
|
+
function getAmountOut(uint amountIn, uint reserveIn, uint reserveOut) internal pure returns (uint amountOut) {
|
|
184
|
+
Require.that(
|
|
185
|
+
amountIn > 0,
|
|
186
|
+
FILE,
|
|
187
|
+
"insufficient input amount"
|
|
188
|
+
);
|
|
189
|
+
Require.that(
|
|
190
|
+
reserveIn > 0 && reserveOut > 0,
|
|
191
|
+
FILE,
|
|
192
|
+
"insufficient liquidity"
|
|
193
|
+
);
|
|
194
|
+
uint amountInWithFee = amountIn.mul(997);
|
|
195
|
+
uint numerator = amountInWithFee.mul(reserveOut);
|
|
196
|
+
uint denominator = reserveIn.mul(1000).add(amountInWithFee);
|
|
197
|
+
amountOut = numerator / denominator;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// given an output amount of an asset and pair reserves, returns a required input amount of the other asset
|
|
201
|
+
function getAmountIn(uint amountOut, uint reserveIn, uint reserveOut) internal pure returns (uint amountIn) {
|
|
202
|
+
Require.that(
|
|
203
|
+
amountOut > 0,
|
|
204
|
+
FILE,
|
|
205
|
+
"insufficient output amount"
|
|
206
|
+
);
|
|
207
|
+
Require.that(
|
|
208
|
+
reserveIn > 0 && reserveOut > 0,
|
|
209
|
+
FILE,
|
|
210
|
+
"insufficient liquidity"
|
|
211
|
+
);
|
|
212
|
+
uint numerator = reserveIn.mul(amountOut).mul(1000);
|
|
213
|
+
uint denominator = reserveOut.sub(amountOut).mul(997);
|
|
214
|
+
// reverts from the 'sub'
|
|
215
|
+
amountIn = numerator.div(denominator).add(1);
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// performs chained getAmountOut calculations on any number of pairs
|
|
219
|
+
function getAmountsOutWei(
|
|
220
|
+
address factory,
|
|
221
|
+
uint amountIn,
|
|
222
|
+
address[] memory path
|
|
223
|
+
) internal view returns (uint[] memory amounts) {
|
|
224
|
+
Require.that(
|
|
225
|
+
path.length >= 2,
|
|
226
|
+
FILE,
|
|
227
|
+
"invalid path"
|
|
228
|
+
);
|
|
229
|
+
amounts = new uint[](path.length);
|
|
230
|
+
amounts[0] = amountIn;
|
|
231
|
+
for (uint i; i < path.length - 1; i++) {
|
|
232
|
+
(uint reserveIn, uint reserveOut) = getReservesWei(factory, path[i], path[i + 1]);
|
|
233
|
+
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// performs chained getAmountOut calculations on any number of pairs
|
|
238
|
+
function getAmountsOutWei(
|
|
239
|
+
address factory,
|
|
240
|
+
bytes32 initCodeHash,
|
|
241
|
+
uint amountIn,
|
|
242
|
+
address[] memory path
|
|
243
|
+
) internal view returns (uint[] memory amounts) {
|
|
244
|
+
Require.that(
|
|
245
|
+
path.length >= 2,
|
|
246
|
+
FILE,
|
|
247
|
+
"invalid path"
|
|
248
|
+
);
|
|
249
|
+
amounts = new uint[](path.length);
|
|
250
|
+
amounts[0] = amountIn;
|
|
251
|
+
for (uint i; i < path.length - 1; i++) {
|
|
252
|
+
(uint reserveIn, uint reserveOut) = getReservesWei(
|
|
253
|
+
factory,
|
|
254
|
+
initCodeHash,
|
|
255
|
+
path[i],
|
|
256
|
+
path[i + 1]
|
|
257
|
+
);
|
|
258
|
+
amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function getAmountsInWei(
|
|
263
|
+
address factory,
|
|
264
|
+
bytes32 initCodeHash,
|
|
265
|
+
uint amountOut,
|
|
266
|
+
address[] memory path
|
|
267
|
+
) internal view returns (uint[] memory amounts) {
|
|
268
|
+
Require.that(
|
|
269
|
+
path.length >= 2,
|
|
270
|
+
FILE,
|
|
271
|
+
"invalid path"
|
|
272
|
+
);
|
|
273
|
+
amounts = new uint[](path.length);
|
|
274
|
+
amounts[amounts.length - 1] = amountOut;
|
|
275
|
+
for (uint i = path.length - 1; i > 0; i--) {
|
|
276
|
+
(uint reserveIn, uint reserveOut) = getReservesWei(
|
|
277
|
+
factory,
|
|
278
|
+
initCodeHash,
|
|
279
|
+
path[i - 1],
|
|
280
|
+
path[i]
|
|
281
|
+
);
|
|
282
|
+
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
function getAmountsIn(
|
|
287
|
+
address factory,
|
|
288
|
+
bytes32 initCodeHash,
|
|
289
|
+
uint amountOut,
|
|
290
|
+
address[] memory path
|
|
291
|
+
) internal view returns (uint[] memory amounts) {
|
|
292
|
+
Require.that(
|
|
293
|
+
path.length >= 2,
|
|
294
|
+
FILE,
|
|
295
|
+
"invalid path"
|
|
296
|
+
);
|
|
297
|
+
amounts = new uint[](path.length);
|
|
298
|
+
amounts[amounts.length - 1] = amountOut;
|
|
299
|
+
for (uint i = path.length - 1; i > 0; i--) {
|
|
300
|
+
(uint reserveIn, uint reserveOut) = getReserves(
|
|
301
|
+
factory,
|
|
302
|
+
initCodeHash,
|
|
303
|
+
path[i - 1],
|
|
304
|
+
path[i]
|
|
305
|
+
);
|
|
306
|
+
amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
// performs chained getAmountIn calculations on any number of pairs
|
|
311
|
+
function getAmountsInWei(
|
|
312
|
+
address factory,
|
|
313
|
+
uint amountOut,
|
|
314
|
+
address[] memory path
|
|
315
|
+
) internal view returns (uint[] memory amounts) {
|
|
316
|
+
return getAmountsInWei(
|
|
317
|
+
factory,
|
|
318
|
+
PAIR_INIT_CODE_HASH,
|
|
319
|
+
amountOut,
|
|
320
|
+
path
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/*
|
|
2
|
+
|
|
3
|
+
Copyright 2019 dYdX Trading Inc.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
pragma solidity ^0.5.7;
|
|
20
|
+
pragma experimental ABIEncoderV2;
|
|
21
|
+
|
|
22
|
+
import { Require } from "../../protocol/lib/Require.sol";
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @title TypedSignature
|
|
27
|
+
* @author dYdX
|
|
28
|
+
*
|
|
29
|
+
* Library to unparse typed signatures
|
|
30
|
+
*/
|
|
31
|
+
library TypedSignature {
|
|
32
|
+
|
|
33
|
+
// ============ Constants ============
|
|
34
|
+
|
|
35
|
+
bytes32 constant private FILE = "TypedSignature";
|
|
36
|
+
|
|
37
|
+
// prepended message with the length of the signed hash in decimal
|
|
38
|
+
bytes constant private PREPEND_DEC = "\x19Ethereum Signed Message:\n32";
|
|
39
|
+
|
|
40
|
+
// prepended message with the length of the signed hash in hexadecimal
|
|
41
|
+
bytes constant private PREPEND_HEX = "\x19Ethereum Signed Message:\n\x20";
|
|
42
|
+
|
|
43
|
+
// Number of bytes in a typed signature
|
|
44
|
+
uint256 constant private NUM_SIGNATURE_BYTES = 66;
|
|
45
|
+
|
|
46
|
+
// ============ Enums ============
|
|
47
|
+
|
|
48
|
+
// Different RPC providers may implement signing methods differently, so we allow different
|
|
49
|
+
// signature types depending on the string prepended to a hash before it was signed.
|
|
50
|
+
enum SignatureType {
|
|
51
|
+
NoPrepend, // No string was prepended.
|
|
52
|
+
Decimal, // PREPEND_DEC was prepended.
|
|
53
|
+
Hexadecimal, // PREPEND_HEX was prepended.
|
|
54
|
+
Invalid // Not a valid type. Used for bound-checking.
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// ============ Functions ============
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Gives the address of the signer of a hash. Also allows for the commonly prepended string of
|
|
61
|
+
* '\x19Ethereum Signed Message:\n' + message.length
|
|
62
|
+
*
|
|
63
|
+
* @param hash Hash that was signed (does not include prepended message)
|
|
64
|
+
* @param signatureWithType Type and ECDSA signature with structure: {32:r}{32:s}{1:v}{1:type}
|
|
65
|
+
* @return address of the signer of the hash
|
|
66
|
+
*/
|
|
67
|
+
function recover(
|
|
68
|
+
bytes32 hash,
|
|
69
|
+
bytes memory signatureWithType
|
|
70
|
+
)
|
|
71
|
+
internal
|
|
72
|
+
pure
|
|
73
|
+
returns (address)
|
|
74
|
+
{
|
|
75
|
+
Require.that(
|
|
76
|
+
signatureWithType.length == NUM_SIGNATURE_BYTES,
|
|
77
|
+
FILE,
|
|
78
|
+
"Invalid signature length"
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
bytes32 r;
|
|
82
|
+
bytes32 s;
|
|
83
|
+
uint8 v;
|
|
84
|
+
uint8 rawSigType;
|
|
85
|
+
|
|
86
|
+
/* solium-disable-next-line security/no-inline-assembly */
|
|
87
|
+
assembly {
|
|
88
|
+
r := mload(add(signatureWithType, 0x20))
|
|
89
|
+
s := mload(add(signatureWithType, 0x40))
|
|
90
|
+
let lastSlot := mload(add(signatureWithType, 0x60))
|
|
91
|
+
v := byte(0, lastSlot)
|
|
92
|
+
rawSigType := byte(1, lastSlot)
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
Require.that(
|
|
96
|
+
rawSigType < uint8(SignatureType.Invalid),
|
|
97
|
+
FILE,
|
|
98
|
+
"Invalid signature type"
|
|
99
|
+
);
|
|
100
|
+
|
|
101
|
+
SignatureType sigType = SignatureType(rawSigType);
|
|
102
|
+
|
|
103
|
+
bytes32 signedHash;
|
|
104
|
+
if (sigType == SignatureType.NoPrepend) {
|
|
105
|
+
signedHash = hash;
|
|
106
|
+
} else if (sigType == SignatureType.Decimal) {
|
|
107
|
+
signedHash = keccak256(abi.encodePacked(PREPEND_DEC, hash));
|
|
108
|
+
} else {
|
|
109
|
+
assert(sigType == SignatureType.Hexadecimal);
|
|
110
|
+
signedHash = keccak256(abi.encodePacked(PREPEND_HEX, hash));
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
return ecrecover(
|
|
114
|
+
signedHash,
|
|
115
|
+
v,
|
|
116
|
+
r,
|
|
117
|
+
s
|
|
118
|
+
);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
pragma solidity ^0.5.16;
|
|
2
|
+
|
|
3
|
+
// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))
|
|
4
|
+
|
|
5
|
+
// range: [0, 2**112 - 1]
|
|
6
|
+
// resolution: 1 / 2**112
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
library UQ112x112 {
|
|
10
|
+
uint224 constant Q112 = 2 ** 112;
|
|
11
|
+
|
|
12
|
+
// encode a uint112 as a UQ112x112
|
|
13
|
+
function encode(uint112 y) internal pure returns (uint224 z) {
|
|
14
|
+
// never overflows
|
|
15
|
+
z = uint224(y) * Q112;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// divide a UQ112x112 by a uint112, returning a UQ112x112
|
|
19
|
+
function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
|
|
20
|
+
z = x / uint224(y);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
/*
|
|
2
|
+
|
|
3
|
+
Copyright 2019 dYdX Trading Inc.
|
|
4
|
+
|
|
5
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
6
|
+
you may not use this file except in compliance with the License.
|
|
7
|
+
You may obtain a copy of the License at
|
|
8
|
+
|
|
9
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
|
|
11
|
+
Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
See the License for the specific language governing permissions and
|
|
15
|
+
limitations under the License.
|
|
16
|
+
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
pragma solidity ^0.5.7;
|
|
20
|
+
pragma experimental ABIEncoderV2;
|
|
21
|
+
|
|
22
|
+
import { MultiSig } from "./MultiSig.sol";
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* @title DelayedMultiSig
|
|
27
|
+
* @author dYdX
|
|
28
|
+
*
|
|
29
|
+
* Multi-Signature Wallet with delay in execution.
|
|
30
|
+
* Allows multiple parties to execute a transaction after a time lock has passed.
|
|
31
|
+
* Adapted from Amir Bandeali's MultiSigWalletWithTimeLock contract.
|
|
32
|
+
|
|
33
|
+
* Logic Changes:
|
|
34
|
+
* - Only owners can execute transactions
|
|
35
|
+
* - Require that each transaction succeeds
|
|
36
|
+
* - Added function to execute multiple transactions within the same Ethereum transaction
|
|
37
|
+
*/
|
|
38
|
+
contract DelayedMultiSig is
|
|
39
|
+
MultiSig
|
|
40
|
+
{
|
|
41
|
+
// ============ Events ============
|
|
42
|
+
|
|
43
|
+
event ConfirmationTimeSet(uint256 indexed transactionId, uint256 confirmationTime);
|
|
44
|
+
event TimeLockChange(uint32 secondsTimeLocked);
|
|
45
|
+
|
|
46
|
+
// ============ Storage ============
|
|
47
|
+
|
|
48
|
+
uint32 public secondsTimeLocked;
|
|
49
|
+
mapping (uint256 => uint256) public confirmationTimes;
|
|
50
|
+
|
|
51
|
+
// ============ Modifiers ============
|
|
52
|
+
|
|
53
|
+
modifier notFullyConfirmed(
|
|
54
|
+
uint256 transactionId
|
|
55
|
+
) {
|
|
56
|
+
require(
|
|
57
|
+
!isConfirmed(transactionId),
|
|
58
|
+
"TX_FULLY_CONFIRMED"
|
|
59
|
+
);
|
|
60
|
+
_;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
modifier fullyConfirmed(
|
|
64
|
+
uint256 transactionId
|
|
65
|
+
) {
|
|
66
|
+
require(
|
|
67
|
+
isConfirmed(transactionId),
|
|
68
|
+
"TX_NOT_FULLY_CONFIRMED"
|
|
69
|
+
);
|
|
70
|
+
_;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
modifier pastTimeLock(
|
|
74
|
+
uint256 transactionId
|
|
75
|
+
) {
|
|
76
|
+
require(
|
|
77
|
+
block.timestamp >= confirmationTimes[transactionId] + secondsTimeLocked,
|
|
78
|
+
"TIME_LOCK_INCOMPLETE"
|
|
79
|
+
);
|
|
80
|
+
_;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// ============ Constructor ============
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Contract constructor sets initial owners, required number of confirmations, and time lock.
|
|
87
|
+
*
|
|
88
|
+
* @param _owners List of initial owners.
|
|
89
|
+
* @param _required Number of required confirmations.
|
|
90
|
+
* @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it
|
|
91
|
+
* becomes executable, in seconds.
|
|
92
|
+
*/
|
|
93
|
+
constructor (
|
|
94
|
+
address[] memory _owners,
|
|
95
|
+
uint256 _required,
|
|
96
|
+
uint32 _secondsTimeLocked
|
|
97
|
+
)
|
|
98
|
+
public
|
|
99
|
+
MultiSig(_owners, _required)
|
|
100
|
+
{
|
|
101
|
+
secondsTimeLocked = _secondsTimeLocked;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ============ Wallet-Only Functions ============
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Changes the duration of the time lock for transactions.
|
|
108
|
+
*
|
|
109
|
+
* @param _secondsTimeLocked Duration needed after a transaction is confirmed and before it
|
|
110
|
+
* becomes executable, in seconds.
|
|
111
|
+
*/
|
|
112
|
+
function changeTimeLock(
|
|
113
|
+
uint32 _secondsTimeLocked
|
|
114
|
+
)
|
|
115
|
+
public
|
|
116
|
+
onlyWallet
|
|
117
|
+
{
|
|
118
|
+
secondsTimeLocked = _secondsTimeLocked;
|
|
119
|
+
emit TimeLockChange(_secondsTimeLocked);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ============ Admin Functions ============
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Allows an owner to confirm a transaction.
|
|
126
|
+
* Overrides the function in MultiSig.
|
|
127
|
+
*
|
|
128
|
+
* @param transactionId Transaction ID.
|
|
129
|
+
*/
|
|
130
|
+
function confirmTransaction(
|
|
131
|
+
uint256 transactionId
|
|
132
|
+
)
|
|
133
|
+
public
|
|
134
|
+
ownerExists(msg.sender)
|
|
135
|
+
transactionExists(transactionId)
|
|
136
|
+
notConfirmed(transactionId, msg.sender)
|
|
137
|
+
notFullyConfirmed(transactionId)
|
|
138
|
+
{
|
|
139
|
+
confirmations[transactionId][msg.sender] = true;
|
|
140
|
+
emit Confirmation(msg.sender, transactionId);
|
|
141
|
+
if (isConfirmed(transactionId)) {
|
|
142
|
+
setConfirmationTime(transactionId, block.timestamp);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Allows an owner to execute a confirmed transaction.
|
|
148
|
+
* Overrides the function in MultiSig.
|
|
149
|
+
*
|
|
150
|
+
* @param transactionId Transaction ID.
|
|
151
|
+
*/
|
|
152
|
+
function executeTransaction(
|
|
153
|
+
uint256 transactionId
|
|
154
|
+
)
|
|
155
|
+
public
|
|
156
|
+
ownerExists(msg.sender)
|
|
157
|
+
notExecuted(transactionId)
|
|
158
|
+
fullyConfirmed(transactionId)
|
|
159
|
+
pastTimeLock(transactionId)
|
|
160
|
+
{
|
|
161
|
+
Transaction storage txn = transactions[transactionId];
|
|
162
|
+
txn.executed = true;
|
|
163
|
+
bool success = externalCall(
|
|
164
|
+
txn.destination,
|
|
165
|
+
txn.value,
|
|
166
|
+
txn.data.length,
|
|
167
|
+
txn.data
|
|
168
|
+
);
|
|
169
|
+
require(
|
|
170
|
+
success,
|
|
171
|
+
"TX_REVERTED"
|
|
172
|
+
);
|
|
173
|
+
emit Execution(transactionId);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
* Allows an owner to execute multiple confirmed transactions.
|
|
178
|
+
*
|
|
179
|
+
* @param transactionIds List of transaction IDs.
|
|
180
|
+
*/
|
|
181
|
+
function executeMultipleTransactions(
|
|
182
|
+
uint256[] memory transactionIds
|
|
183
|
+
)
|
|
184
|
+
public
|
|
185
|
+
ownerExists(msg.sender)
|
|
186
|
+
{
|
|
187
|
+
for (uint256 i = 0; i < transactionIds.length; i++) {
|
|
188
|
+
executeTransaction(transactionIds[i]);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ============ Helper Functions ============
|
|
193
|
+
|
|
194
|
+
/**
|
|
195
|
+
* Sets the time of when a submission first passed.
|
|
196
|
+
*/
|
|
197
|
+
function setConfirmationTime(
|
|
198
|
+
uint256 transactionId,
|
|
199
|
+
uint256 confirmationTime
|
|
200
|
+
)
|
|
201
|
+
internal
|
|
202
|
+
{
|
|
203
|
+
confirmationTimes[transactionId] = confirmationTime;
|
|
204
|
+
emit ConfirmationTimeSet(transactionId, confirmationTime);
|
|
205
|
+
}
|
|
206
|
+
}
|