1
+ //SPDX-License-Identifier: Unlicense
2
+ pragma solidity ^ 0.6.10 ;
3
+
4
+ import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol " ;
5
+ import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/SafeERC20.sol " ;
6
+ import { SafeMath } from "@openzeppelin/contracts/math/SafeMath.sol " ;
7
+
8
+ import { Vesting } from "./Vesting.sol " ;
9
+
10
+ /**
11
+ * @title OtcEscrow
12
+ * @author Badger DAO (Modified by Set Protocol)
13
+ *
14
+ * A simple OTC swap contract allowing two users to set the parameters of an OTC
15
+ * deal in the constructor arguments, and deposits the sold tokens into a vesting
16
+ * contract when a swap is completed.
17
+ */
18
+ contract OtcEscrow {
19
+
20
+ using SafeMath for uint256 ;
21
+ using SafeERC20 for IERC20 ;
22
+
23
+ /* ========== Events =========== */
24
+
25
+ event VestingDeployed (address vesting );
26
+
27
+ /* ====== Modifiers ======== */
28
+
29
+ /**
30
+ * Throws if the sender is not Index Gov
31
+ */
32
+ modifier onlyIndexGov () {
33
+ require (msg .sender == indexGov, "unauthorized " );
34
+ _;
35
+ }
36
+
37
+ /**
38
+ * Throws if run more than once
39
+ */
40
+ modifier onlyOnce () {
41
+ require (! hasRun, "swap already executed " );
42
+ hasRun = true ;
43
+ _;
44
+ }
45
+
46
+ /* ======== State Variables ======= */
47
+
48
+ address public usdc;
49
+ address public index;
50
+
51
+ address public indexGov;
52
+ address public beneficiary;
53
+
54
+ uint256 public vestingStart;
55
+ uint256 public vestingEnd;
56
+ uint256 public vestingCliff;
57
+
58
+ uint256 public usdcAmount;
59
+ uint256 public indexAmount;
60
+
61
+ bool hasRun;
62
+
63
+
64
+
65
+ /* ====== Constructor ======== */
66
+
67
+ /**
68
+ * Sets the state variables that encode the terms of the OTC sale
69
+ *
70
+ * @param _beneficiary Address that will purchase INDEX
71
+ * @param _indexGov Address that will receive USDC
72
+ * @param _vestingStart Timestamp of vesting start
73
+ * @param _vestingCliff Timestamp of vesting cliff
74
+ * @param _vestingEnd Timestamp of vesting end
75
+ * @param _usdcAmount Amount of USDC swapped for the sale
76
+ * @param _indexAmount Amount of INDEX swapped for the sale
77
+ * @param _usdcAddress Address of the USDC token
78
+ * @param _indexAddress Address of the Index token
79
+ */
80
+ constructor (
81
+ address _beneficiary ,
82
+ address _indexGov ,
83
+ uint256 _vestingStart ,
84
+ uint256 _vestingCliff ,
85
+ uint256 _vestingEnd ,
86
+ uint256 _usdcAmount ,
87
+ uint256 _indexAmount ,
88
+ address _usdcAddress ,
89
+ address _indexAddress
90
+ ) public {
91
+ beneficiary = _beneficiary;
92
+ indexGov = _indexGov;
93
+
94
+ vestingStart = _vestingStart;
95
+ vestingCliff = _vestingCliff;
96
+ vestingEnd = _vestingEnd;
97
+
98
+ usdcAmount = _usdcAmount;
99
+ indexAmount = _indexAmount;
100
+
101
+ usdc = _usdcAddress;
102
+ index = _indexAddress;
103
+ hasRun = false ;
104
+ }
105
+
106
+ /* ======= External Functions ======= */
107
+
108
+ /**
109
+ * Executes the OTC deal. Sends the USDC from the beneficiary to Index Governance, and
110
+ * locks the INDEX in the vesting contract. Can only be called once.
111
+ */
112
+ function swap () external onlyOnce {
113
+
114
+ require (IERC20 (index).balanceOf (address (this )) >= indexAmount, "insufficient INDEX " );
115
+
116
+ // Transfer expected USDC from beneficiary
117
+ IERC20 (usdc).safeTransferFrom (beneficiary, address (this ), usdcAmount);
118
+
119
+ // Create Vesting contract
120
+ Vesting vesting = new Vesting (index, beneficiary, indexAmount, vestingStart, vestingCliff, vestingEnd);
121
+
122
+ // Transfer index to vesting contract
123
+ IERC20 (index).safeTransfer (address (vesting), indexAmount);
124
+
125
+ // Transfer USDC to index governance
126
+ IERC20 (usdc).safeTransfer (indexGov, usdcAmount);
127
+
128
+ emit VestingDeployed (address (vesting));
129
+ }
130
+
131
+ /**
132
+ * Return INDEX to Index Governance to revoke the deal
133
+ */
134
+ function revoke () external onlyIndexGov {
135
+ uint256 indexBalance = IERC20 (index).balanceOf (address (this ));
136
+ IERC20 (index).safeTransfer (indexGov, indexBalance);
137
+ }
138
+
139
+ /**
140
+ * Recovers USDC accidentally sent to the contract
141
+ */
142
+ function recoverUsdc () external {
143
+ uint256 usdcBalance = IERC20 (usdc).balanceOf (address (this ));
144
+ IERC20 (usdc).safeTransfer (beneficiary, usdcBalance);
145
+ }
146
+ }
0 commit comments