This repository has been archived by the owner on Jan 18, 2023. It is now read-only.
/
TakerWalletWrapper.sol
168 lines (142 loc) Β· 5.67 KB
/
TakerWalletWrapper.sol
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
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
/*
Copyright 2018 Set Labs Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
pragma solidity 0.4.25;
pragma experimental "ABIEncoderV2";
import { SafeMath } from "openzeppelin-solidity/contracts/math/SafeMath.sol";
import { ERC20Wrapper } from "../../lib/ERC20Wrapper.sol";
import { ICore } from "../interfaces/ICore.sol";
import { ITransferProxy } from "../interfaces/ITransferProxy.sol";
import { LibBytes } from "../../external/0x/LibBytes.sol";
import { OrderLibrary } from "../lib/OrderLibrary.sol";
import { ExchangeWrapperLibrary } from "../lib/ExchangeWrapperLibrary.sol";
/**
* @title TakerWalletWrapper
* @author Set Protocol
*
* The TakerWalletWrapper contract wrapper to transfer tokens directly from order taker
*/
contract TakerWalletWrapper {
using LibBytes for bytes;
using SafeMath for uint256;
/* ============ State Variables ============ */
address public core;
address public transferProxy;
/* ============ Constructor ============ */
/**
* Sets the transferProxy and Core address for the contract
*
* @param _core Deployed Core contract
* @param _transferProxy Address of current transferProxy
*/
constructor(
address _core,
address _transferProxy
)
public
{
core = _core;
transferProxy = _transferProxy;
}
/* ============ Public Functions ============ */
/**
* The TakerWalletWrapper contract wrapper to transfer tokens directly from order taker
*
* @param _exchangeData Standard exchange wrapper interface object containing exchange metadata
* @param _transfersData Arbitrary bytes data for any information to pass to the exchange
* @return address[] The addresses of required components
* @return uint256[] The quantities of required components retrieved by the wrapper
*/
function exchange(
ExchangeWrapperLibrary.ExchangeData _exchangeData,
bytes _transfersData
)
public
returns(address[], uint256[])
{
require(
ICore(core).validModules(msg.sender),
"TakerWalletWrapper.exchange: Sender must be approved module"
);
OrderLibrary.FractionFilled memory fractionFilled = OrderLibrary.FractionFilled({
filled: _exchangeData.fillQuantity,
attempted: _exchangeData.attemptedFillQuantity
});
uint256 numOrders = _exchangeData.orderCount;
address[] memory takerTokens = new address[](numOrders);
uint256[] memory takerTokenAmounts = new uint256[](numOrders);
uint256 scannedBytes = 0;
while (scannedBytes < _transfersData.length) {
// Record taker token and amount to return values
uint256 orderCount = scannedBytes >> 6;
// Transfer the tokens from the taker
(takerTokens[orderCount], takerTokenAmounts[orderCount]) = transferFromTaker(
_exchangeData.taker,
scannedBytes,
fractionFilled,
_transfersData
);
// Update scanned bytes with length of each transfer request (64)
scannedBytes = scannedBytes.add(64);
}
return (takerTokens, takerTokenAmounts);
}
/* ============ Private ============ */
/**
* Parses and executes transfer from the issuance order taker's wallet
*
* @param _taker Taker wallet to transfer components from
* @param _offset Offset to start scanning for current transfer
* @param _fractionFilled Fraction of the issuance order that has been filled
* @param _transfersData Byte array of (multiple) taker wallet transfers
* @return address Address of token transferred
* @return uint256 Amount of the token transferred
*/
function transferFromTaker(
address _taker,
uint256 _offset,
OrderLibrary.FractionFilled _fractionFilled,
bytes _transfersData
)
private
returns (address, uint256)
{
uint256 transferDataStart = _offset.add(32);
// Read the next transfer
address takerToken;
uint256 takerTokenAmount;
assembly {
takerToken := mload(add(_transfersData, transferDataStart))
takerTokenAmount := mload(add(_transfersData, add(transferDataStart, 32)))
}
uint256 takerTokenExecutionAmount = OrderLibrary.getPartialAmount(
takerTokenAmount,
_fractionFilled.filled,
_fractionFilled.attempted
);
// Transfer from taker's wallet to this wrapper
ITransferProxy(transferProxy).transfer(
takerToken,
takerTokenExecutionAmount,
_taker,
address(this)
);
// Ensure the component token is allowed to be transferred by Set TransferProxy
ERC20Wrapper.ensureAllowance(
takerToken,
address(this),
transferProxy,
takerTokenExecutionAmount
);
return (takerToken, takerTokenExecutionAmount);
}
}