Skip to content

Commit d006378

Browse files
committed
(fix) merge conflicts
2 parents aac8a45 + 2afada5 commit d006378

File tree

6 files changed

+552
-0
lines changed

6 files changed

+552
-0
lines changed

contracts/Basket.sol

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import "./zeppelin/StandardToken.sol";
2222
import "./zeppelin/ERC20.sol";
2323

2424
import "./BasketRegistry.sol";
25+
import "./BasketSwap.sol";
2526

2627
/// @title Basket -- Basket contract for bundling and debundling tokens
2728
/// @author CoinAlpha, Inc. <[email protected]>
@@ -40,7 +41,11 @@ contract Basket is StandardToken {
4041

4142
// mapping of token addresses to mapping of account balances
4243
// ADDRESS USER || ADDRESS TOKEN || UINT BALANCE
44+
<<<<<<< HEAD
4345
mapping(address => mapping(address => uint)) public outstandingBalance;
46+
=======
47+
mapping(address => mapping(address => uint)) public outstandingBalances;
48+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
4449

4550
// Modules
4651
IBasketRegistry public basketRegistry;
@@ -124,24 +129,50 @@ contract Basket is StandardToken {
124129
/// @param _quantity Quantity of basket tokens to convert back to original tokens
125130
/// @return success Operation successful
126131
function debundleAndWithdraw(uint _quantity) public returns (bool success) {
132+
<<<<<<< HEAD
127133
assert(debundle(_quantity, msg.sender, msg.sender));
134+
=======
135+
assert(debundle(_quantity, msg.sender, msg.sender, true));
136+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
128137
emit LogDebundleAndWithdraw(msg.sender, _quantity);
129138
return true;
130139
}
131140

141+
<<<<<<< HEAD
142+
=======
143+
/// @dev Convert basketTokens back to original tokens (does not throw if single token transfer fails)
144+
/// @param _quantity Quantity of basket tokens to partial debundle
145+
/// @return success Operation successful
146+
function partialDebundle(uint _quantity) public returns (bool success) {
147+
assert(debundle(_quantity, msg.sender, msg.sender, false));
148+
emit LogPartialDebundle(msg.sender, _quantity);
149+
return true;
150+
}
151+
152+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
132153
/// @dev Convert basketTokens back to original tokens and transfer to swap contract and initiate swap
133154
/// @param _quantity Quantity of basket tokens to swap
134155
/// @param _sender Address of transaction sender
135156
/// @param _recipient Address of token recipient
157+
<<<<<<< HEAD
158+
=======
159+
/// @param _revertOnFailedTransfer If partial debundle is allowed (allow when tokens are paused / debundle function is stuck)
160+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
136161
/// @return success Operation successful
137162
function debundle(
138163
uint _quantity,
139164
address _sender,
165+
<<<<<<< HEAD
140166
address _recipient
167+
=======
168+
address _recipient,
169+
bool _revertOnFailedTransfer
170+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
141171
) internal returns (bool success) {
142172
require(balances[_sender] >= _quantity, "Insufficient basket balance to debundle");
143173
// decrease holder balance and total supply by _quantity
144174
balances[_sender] = balances[_sender].sub(_quantity);
175+
<<<<<<< HEAD
145176
totalSupply_ = totalSupply_.sub(_quantity);
146177

147178
// transfer tokens back to holder
@@ -160,24 +191,42 @@ contract Basket is StandardToken {
160191
/// @return success Operation successful
161192
function burn(uint _quantity) public returns (bool success) {
162193
balances[msg.sender] = balances[msg.sender].sub(_quantity);
194+
=======
195+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
163196
totalSupply_ = totalSupply_.sub(_quantity);
164197

165198
// increase outstanding balance of each of the tokens by their weights
166199
for (uint i = 0; i < tokens.length; i++) {
167200
address t = tokens[i];
168201
uint w = weights[i];
202+
<<<<<<< HEAD
169203
outstandingBalance[msg.sender][t] = outstandingBalance[msg.sender][t].add(w.mul(_quantity).div(10 ** 18));
170204
}
171205

172206
basketRegistry.incrementBasketsBurned(_quantity, msg.sender);
207+
=======
208+
bool successfulTransfer = ERC20(t).transfer(_recipient, w.mul(_quantity).div(10 ** 18));
209+
if (_revertOnFailedTransfer) {
210+
assert(successfulTransfer);
211+
} else if (successfulTransfer != true) {
212+
outstandingBalances[_sender][t] = outstandingBalances[_sender][t].add(w.mul(_quantity).div(10 ** 18));
213+
}
214+
}
215+
216+
basketRegistry.incrementBasketsBurned(_quantity, _sender);
217+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
173218
return true;
174219
}
175220

176221
/// @dev Allow holder to withdraw outstanding balances from contract (such as previously paused tokens)
177222
/// @param _token Address of token to withdraw
178223
/// @return success Operation successful
179224
function withdraw(address _token) public returns (bool success) {
225+
<<<<<<< HEAD
180226
uint bal = outstandingBalance[msg.sender][_token];
227+
=======
228+
uint bal = outstandingBalances[msg.sender][_token];
229+
>>>>>>> 2afada5ddf4d902117ef5d8299a56d7b65a3823c
181230
require(bal > 0);
182231
assert(ERC20(_token).transfer(msg.sender, bal));
183232

contracts/BasketSwap.sol

Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
/*
2+
3+
Copyright 2018 CoinAlpha, Inc.
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
16+
*/
17+
18+
pragma solidity ^0.4.22;
19+
20+
import "./zeppelin/SafeMath.sol";
21+
import "./zeppelin/ERC20.sol";
22+
import "./Basket.sol";
23+
24+
25+
contract IBasketSwap {
26+
// Called by Basket
27+
function swap(address, address, address, uint) public returns (bool) {}
28+
}
29+
30+
31+
/// @title BasketSwap -- BasketSwap contract for swapping one basket token for another
32+
/// @author CoinAlpha, Inc. <[email protected]>
33+
contract BasketSwap {
34+
using SafeMath for uint;
35+
36+
// Constants set at contract inception
37+
address public arranger;
38+
address public fromBasket;
39+
address public toBasket;
40+
uint public exchangeRate;
41+
uint public exchangeRateDecimals;
42+
43+
// Events
44+
event LogWithdraw(address token, uint quantity);
45+
event LogSetExchangeRate(uint oldRate, uint newRate);
46+
event LogSwap(address holder, uint quantity);
47+
48+
// Modifiers
49+
modifier onlyArranger {
50+
require(msg.sender == arranger, "Only the Arranger can call this function");
51+
_;
52+
}
53+
54+
/// @dev BasketSwap constructor
55+
/// @param _arranger Address of arranger (cannot be reset)
56+
/// @param _fromBasket Address of original basket
57+
/// @param _toBasket Address of new basket
58+
/// @param _exchangeRate Original basket / New basket
59+
/// @param _exchangeRateDecimals Number of decimals for exchange rate
60+
constructor(
61+
address _arranger,
62+
address _fromBasket,
63+
address _toBasket,
64+
uint _exchangeRate,
65+
uint _exchangeRateDecimals
66+
) public {
67+
arranger = _arranger;
68+
fromBasket = _fromBasket;
69+
toBasket = _toBasket;
70+
exchangeRate = _exchangeRate;
71+
exchangeRateDecimals = _exchangeRateDecimals;
72+
}
73+
74+
/// @dev Withdraw ERC20 tokens from contract
75+
/// @param _token Token to withdraw
76+
/// @param _quantity Amount of tokens to withdraw
77+
/// @return success Operation successful
78+
function withdraw(address _token, uint _quantity) public onlyArranger returns (bool success) {
79+
assert(ERC20(_token).transfer(msg.sender, _quantity));
80+
emit LogWithdraw(_token, _quantity);
81+
return true;
82+
}
83+
84+
/// @dev Change exchange rate between to baskets
85+
/// @param _newRate New exchange rate between to baskets
86+
/// @return success Operation successful
87+
function setExchangeRate(uint _newRate) public onlyArranger returns (bool success) {
88+
uint oldRate = exchangeRate;
89+
exchangeRate = _newRate;
90+
91+
emit LogSetExchangeRate(oldRate, _newRate);
92+
return true;
93+
}
94+
95+
/// @dev Swap basket for other baskets Only basket holders can initiate this transaction
96+
/// @param _quantity Quantity of baskets to swap
97+
/// @return success Operation successful
98+
function swap(address _holder, uint _quantity) public returns (bool success) {
99+
require(msg.sender == fromBasket, "Transaction did not come from original basket");
100+
uint newBasketQuantity = exchangeRate.mul(_quantity).div(10 ** exchangeRateDecimals);
101+
102+
assert(Basket(toBasket).depositAndBundle(newBasketQuantity));
103+
assert(ERC20(toBasket).transfer(this, newBasketQuantity));
104+
105+
emit LogSwap(_holder, _quantity);
106+
return true;
107+
}
108+
109+
110+
/// @dev Fallback to reject any ether sent to contract
111+
function () public payable { revert("BasketSwap does not accept ETH transfers"); }
112+
}

contracts/BasketSwapFactory.sol

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
/*
2+
3+
Copyright 2018 CoinAlpha, Inc.
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
16+
*/
17+
18+
pragma solidity ^0.4.22;
19+
20+
import "./zeppelin/SafeMath.sol";
21+
import "./BasketSwap.sol";
22+
import "./BasketRegistry.sol";
23+
24+
/**
25+
* @title BasketFactory -- Factory contract for creating different baskets
26+
* @author CoinAlpha, Inc. <[email protected]>
27+
*/
28+
contract BasketSwapFactory {
29+
using SafeMath for uint;
30+
31+
address public admin;
32+
address public basketRegistryAddress;
33+
34+
uint public rebalanceFee;
35+
address public rebalanceFeeRecipient;
36+
37+
uint public exchangeRateDecimals;
38+
39+
// Modules
40+
IBasketRegistry public basketRegistry;
41+
42+
// Modifiers
43+
modifier onlyAdmin {
44+
require(msg.sender == admin, "Only the admin can call this function");
45+
_;
46+
}
47+
48+
// Events
49+
event LogBasketSwapCreated(address basketSwapAddress, address arranger);
50+
event LogRebalanceFeeRecipientChange(address oldRecipient, address newRecipient);
51+
event LogRebalanceFeeChange(uint oldFee, uint newFee);
52+
53+
/// @dev BasketFactory constructor
54+
/// @param _basketRegistryAddress Address of basket registry
55+
/// @param _rebalanceFeeRecipient Address to receive rebalance fee
56+
/// @param _rebalanceFee Amount of rebalance fee
57+
/// @param _exchangeRateDecimals Number of decimals in exchange
58+
constructor(
59+
address _basketRegistryAddress,
60+
address _rebalanceFeeRecipient,
61+
uint _rebalanceFee,
62+
uint _exchangeRateDecimals
63+
) public {
64+
admin = msg.sender;
65+
66+
basketRegistryAddress = _basketRegistryAddress;
67+
basketRegistry = IBasketRegistry(_basketRegistryAddress);
68+
69+
rebalanceFeeRecipient = _rebalanceFeeRecipient;
70+
rebalanceFee = _rebalanceFee;
71+
exchangeRateDecimals = _exchangeRateDecimals;
72+
}
73+
74+
/// @dev Deploy a new basketSwap contract
75+
/// @param _fromBasket Address of original basket
76+
/// @param _toBasket Address of new basket
77+
/// @param _exchangeRate Exchange rate between original and new basket
78+
/// @return deployed basketSwap
79+
function createBasketSwap(
80+
address _fromBasket,
81+
address _toBasket,
82+
uint _exchangeRate
83+
)
84+
public payable returns (address newBasketSwap) {
85+
// charging arrangers a fee to deploy new basketSwap
86+
require(msg.value >= rebalanceFee, "Insufficient ETH for basketSwap creation fee");
87+
rebalanceFeeRecipient.transfer(msg.value);
88+
89+
require(msg.sender == basketRegistry.getBasketArranger(_fromBasket), "Only the arranger of original basket can create swaps");
90+
require(msg.sender == basketRegistry.getBasketArranger(_toBasket), "Only the arranger of new basket can create swaps");
91+
92+
BasketSwap bs = new BasketSwap(
93+
msg.sender,
94+
_fromBasket,
95+
_toBasket,
96+
_exchangeRate,
97+
exchangeRateDecimals
98+
);
99+
100+
emit LogBasketSwapCreated(bs, msg.sender);
101+
return bs;
102+
}
103+
104+
/// @dev Change recipient of rebalance fees
105+
/// @param _newRecipient New fee recipient
106+
/// @return success Operation successful
107+
function changeRebalanceFeeRecipient(address _newRecipient) public onlyAdmin returns (bool success) {
108+
address oldRecipient = rebalanceFeeRecipient;
109+
rebalanceFeeRecipient = _newRecipient;
110+
111+
emit LogRebalanceFeeRecipientChange(oldRecipient, rebalanceFeeRecipient);
112+
return true;
113+
}
114+
115+
/// @dev Change amount of fee charged for every basket created
116+
/// @param _newFee New fee amount
117+
/// @return success Operation successful
118+
function changeRebalanceFee(uint _newFee) public onlyAdmin returns (bool success) {
119+
uint oldFee = rebalanceFee;
120+
rebalanceFee = _newFee;
121+
122+
emit LogRebalanceFeeChange(oldFee, rebalanceFee);
123+
return true;
124+
}
125+
126+
/// @dev Fallback to reject any ether sent to contract
127+
function () public payable { revert("BasketSwapFactory do not accept ETH transfers"); }
128+
}

0 commit comments

Comments
 (0)