-
Notifications
You must be signed in to change notification settings - Fork 160
/
Copy pathzb_signed_transfer_manager.js
309 lines (258 loc) · 13.8 KB
/
zb_signed_transfer_manager.js
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
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
import latestTime from "./helpers/latestTime";
import { duration, promisifyLogWatch, latestBlock } from "./helpers/utils";
import { takeSnapshot, increaseTime, revertToSnapshot } from "./helpers/time";
import { getSignSTMData } from "./helpers/signData";
import { pk } from "./helpers/testprivateKey";
import { encodeProxyCall, encodeModuleCall } from "./helpers/encodeCall";
import { catchRevert } from "./helpers/exceptions";
import { setUpPolymathNetwork, deployGPMAndVerifyed, deploySignedTMAndVerifyed} from "./helpers/createInstances";
const DummySTO = artifacts.require("./DummySTO.sol");
const SecurityToken = artifacts.require("./SecurityToken.sol");
const GeneralTransferManager = artifacts.require("./GeneralTransferManager");
const GeneralPermissionManager = artifacts.require("./GeneralPermissionManager");
const SignedTransferManager = artifacts.require("./SignedTransferManager");
const STGetter = artifacts.require("./STGetter.sol");
const Web3 = require("web3");
let BN = Web3.utils.BN;
const web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545")); // Hardcoded development port
contract("SignedTransferManager", accounts => {
// Accounts Variable declaration
let account_polymath;
let account_issuer;
let token_owner;
let token_owner_pk;
let account_investor1;
let account_investor2;
let account_investor3;
let account_investor4;
// Contract Instance Declaration
let I_GeneralPermissionManagerFactory;
let I_GeneralTransferManagerFactory;
let I_SecurityTokenRegistryProxy;
let I_GeneralPermissionManager;
let I_GeneralTransferManager;
let I_ModuleRegistryProxy;
let I_ModuleRegistry;
let I_FeatureRegistry;
let I_SecurityTokenRegistry;
let I_DummySTOFactory;
let I_STFactory;
let I_SecurityToken;
let I_STRProxied;
let I_MRProxied;
let I_DummySTO;
let I_PolyToken;
let I_PolymathRegistry;
let I_SignedTransferManagerFactory;
let P_SignedTransferManagerFactory;
let I_SignedTransferManager;
let I_STGetter;
let stGetter;
// SecurityToken Details
const name = "Team";
const symbol = "sap";
const tokenDetails = "This is equity type of issuance";
const decimals = 18;
const contact = "[email protected]";
const address_zero = "0x0000000000000000000000000000000000000000";
// Module key
const delegateManagerKey = 1;
const transferManagerKey = 2;
const stoKey = 3;
// Initial fee for ticker registry and security token registry
const initRegFee = web3.utils.toWei("1000");
let currentTime;
let validFrom = new BN(0);
before(async () => {
// Accounts setup
currentTime = new BN(await latestTime());
account_polymath = accounts[0];
account_issuer = accounts[1];
token_owner = account_issuer;
token_owner_pk = pk.account_1;
account_investor1 = accounts[8];
account_investor2 = accounts[9];
account_investor3 = accounts[6];
account_investor4 = accounts[7];
// Step 1: Deploy the genral PM ecosystem
let instances = await setUpPolymathNetwork(account_polymath, token_owner);
[
I_PolymathRegistry,
I_PolyToken,
I_FeatureRegistry,
I_ModuleRegistry,
I_ModuleRegistryProxy,
I_MRProxied,
I_GeneralTransferManagerFactory,
I_STFactory,
I_SecurityTokenRegistry,
I_SecurityTokenRegistryProxy,
I_STRProxied,
I_STGetter
] = instances;
// STEP 2: Deploy the GeneralPermissionManagerFactory
[I_GeneralPermissionManagerFactory] = await deployGPMAndVerifyed(account_polymath, I_MRProxied, new BN(0));
// STEP 3: Deploy the SignedTransferManagerFactory
[I_SignedTransferManagerFactory] = await deploySignedTMAndVerifyed(account_polymath, I_MRProxied, new BN(0));
// STEP 4: Deploy the Paid SignedTransferManagerFactory
[P_SignedTransferManagerFactory] = await deploySignedTMAndVerifyed(account_polymath, I_MRProxied, web3.utils.toWei("500", "ether"));
// Printing all the contract addresses
console.log(`
--------------------- Polymath Network Smart Contracts: ---------------------
PolymathRegistry: ${I_PolymathRegistry.address}
SecurityTokenRegistryProxy: ${I_SecurityTokenRegistryProxy.address}
SecurityTokenRegistry: ${I_SecurityTokenRegistry.address}
ModuleRegistryProxy: ${I_ModuleRegistryProxy.address}
ModuleRegistry: ${I_ModuleRegistry.address}
FeatureRegistry: ${I_FeatureRegistry.address}
ManualApprovalTransferManagerFactory: ${I_SignedTransferManagerFactory.address}
-----------------------------------------------------------------------------
`);
});
describe("Generate the SecurityToken", async () => {
it("Should register the ticker before the generation of the security token", async () => {
await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner });
let tx = await I_STRProxied.registerNewTicker(token_owner, symbol, { from: token_owner });
assert.equal(tx.logs[0].args._owner, token_owner);
assert.equal(tx.logs[0].args._ticker, symbol.toUpperCase());
});
it("Should generate the new security token with the same symbol as registered above", async () => {
await I_PolyToken.approve(I_STRProxied.address, initRegFee, { from: token_owner });
let tx = await I_STRProxied.generateNewSecurityToken(name, symbol, tokenDetails, false, token_owner, 0, { from: token_owner });
// Verify the successful generation of the security token
assert.equal(tx.logs[1].args._ticker, symbol.toUpperCase(), "SecurityToken doesn't get deployed");
I_SecurityToken = await SecurityToken.at(tx.logs[1].args._securityTokenAddress);
stGetter = await STGetter.at(I_SecurityToken.address);
assert.equal(await stGetter.getTreasuryWallet.call(), token_owner, "Incorrect wallet set");
const log = (await I_SecurityToken.getPastEvents('ModuleAdded', {filter: {transactionHash: tx.transactionHash}}))[0];
// Verify that GeneralTransferManager module get added successfully or not
assert.equal(log.args._types[0].toNumber(), 2);
assert.equal(web3.utils.toAscii(log.args._name).replace(/\u0000/g, ""), "GeneralTransferManager");
});
it("Should initialize the auto attached modules", async () => {
let moduleData = (await stGetter.getModulesByType(2))[0];
I_GeneralTransferManager = await GeneralTransferManager.at(moduleData);
});
});
describe("signed transfer manager tests", async () => {
it("Should Buy the tokens", async () => {
// Add the Investor in to the whitelist
let tx = await I_GeneralTransferManager.modifyKYCData(
account_investor1,
currentTime,
currentTime,
currentTime.add(new BN(duration.days(10))),
{
from: account_issuer
}
);
assert.equal(
tx.logs[0].args._investor.toLowerCase(),
account_investor1.toLowerCase(),
"Failed in adding the investor in whitelist"
);
// Jump time
await increaseTime(5000);
// Mint some tokens
await I_SecurityToken.issue(account_investor1, new BN(web3.utils.toWei("2", "ether")), "0x0", { from: token_owner });
assert.equal((await I_SecurityToken.balanceOf(account_investor1)).toString(), new BN(web3.utils.toWei("2", "ether")).toString());
});
it("Should successfully attach the SignedTransferManager with the security token", async () => {
const tx = await I_SecurityToken.addModule(I_SignedTransferManagerFactory.address, "0x0",new BN(0),new BN(0), false, { from: token_owner });
assert.equal(tx.logs[2].args._types[0].toNumber(), transferManagerKey, "SignedTransferManager doesn't get deployed");
assert.equal(
web3.utils.toUtf8(tx.logs[2].args._name),
"SignedTransferManager",
"SignedTransferManager module was not added"
);
I_SignedTransferManager = await SignedTransferManager.at(tx.logs[2].args._module);
});
it("should fail to transfer because transaction is not verified yet.", async () => {
await catchRevert(I_SecurityToken.transfer(account_investor2, web3.utils.toWei("1", "ether"), { from: account_investor1 }));
});
it("Should successfully attach the permission manager factory with the security token", async () => {
console.log((await I_GeneralPermissionManagerFactory.setupCostInPoly.call()).toString());
const tx = await I_SecurityToken.addModule(I_GeneralPermissionManagerFactory.address, "0x0", new BN(0), new BN(0), false, { from: token_owner });
assert.equal(tx.logs[2].args._types[0].toNumber(), delegateManagerKey, "GeneralPermissionManager doesn't get deployed");
assert.equal(
web3.utils.toAscii(tx.logs[2].args._name).replace(/\u0000/g, ""),
"GeneralPermissionManager",
"GeneralPermissionManager module was not added"
);
I_GeneralPermissionManager = await GeneralPermissionManager.at(tx.logs[2].args._module);
});
it("should allow to invalidate siganture if sender is the signer and is in the signer list", async () => {
let oneeth = new BN(web3.utils.toWei("1", "ether"));
let signer = web3.eth.accounts.create();
await web3.eth.personal.importRawKey(signer.privateKey, "");
await web3.eth.personal.unlockAccount(signer.address, "", 6000);
await web3.eth.sendTransaction({ from: token_owner, to: signer.address, value: oneeth });
let log = await I_GeneralPermissionManager.addDelegate(signer.address, web3.utils.fromAscii("My details"), { from: token_owner });
assert.equal(log.logs[0].args._delegate, signer.address);
await I_GeneralPermissionManager.changePermission(signer.address, I_SignedTransferManager.address, web3.utils.fromAscii("OPERATOR"), true, {
from: token_owner
});
let nonce = new BN(10);
let expiry = new BN(currentTime.add(new BN(duration.days(100))));
let data = await getSignSTMData(
I_SignedTransferManager.address,
nonce,
validFrom,
expiry,
account_investor1,
account_investor2,
oneeth,
signer.privateKey
);
assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), true);
await I_SignedTransferManager.invalidateSignature(account_investor1, account_investor2, oneeth, data, {from: signer.address});
assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), false);
});
it("should allow transfer with valid sig", async () => {
let signer = web3.eth.accounts.create();
let log = await I_GeneralPermissionManager.addDelegate(signer.address, web3.utils.fromAscii("My details"), { from: token_owner });
assert.equal(log.logs[0].args._delegate, signer.address);
await I_GeneralPermissionManager.changePermission(signer.address, I_SignedTransferManager.address, web3.utils.fromAscii("OPERATOR"), true, {
from: token_owner
});
let oneeth = new BN(web3.utils.toWei("1", "ether"));
let nonce = new BN(10);
let expiry = new BN(currentTime.add(new BN(duration.days(100))));
let data = await getSignSTMData(
I_SignedTransferManager.address,
nonce,
validFrom,
expiry,
account_investor1,
account_investor2,
oneeth,
signer.privateKey
);
let balance11 = await I_SecurityToken.balanceOf(account_investor1);
let balance21 = await I_SecurityToken.balanceOf(account_investor2);
assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), true);
await I_SecurityToken.transferWithData(account_investor2, oneeth, data, {from: account_investor1});
assert.equal(await I_SignedTransferManager.checkSignatureValidity(data), false);
await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, data, {from: account_investor1}));
assert.equal(balance11.sub(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor1)).toString());
assert.equal(balance21.add(oneeth).toString(), (await I_SecurityToken.balanceOf(account_investor2)).toString());
});
it("should not allow transfer if the signer is not on the signer list", async () => {
let signer = web3.eth.accounts.create();
let oneeth = new BN(web3.utils.toWei("1", "ether"));
let nonce = new BN(10);
let expiry = new BN(currentTime.add(new BN(duration.days(100))));
let data = await getSignSTMData(
I_SignedTransferManager.address,
nonce,
validFrom,
expiry,
account_investor1,
account_investor2,
oneeth,
signer.privateKey
);
await catchRevert(I_SecurityToken.transferWithData(account_investor2, oneeth, data, {from: account_investor1}));
});
});
});