Skip to content
This repository was archived by the owner on Jul 6, 2022. It is now read-only.

Commit 562b7f5

Browse files
committed
fix: 🐛 Validate if issuer and beneficiaries were added in the
1 parent 0feb657 commit 562b7f5

File tree

3 files changed

+98
-12
lines changed

3 files changed

+98
-12
lines changed

src/contract_wrappers/tokens/__tests__/security_token_wrapper.test.ts

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import {
2828
Partition,
2929
Perm,
3030
CappedSTOFundRaiseType,
31+
TransferStatusCodes
3132
} from '../../../types';
3233
import SecurityTokenWrapper from '../security_token_wrapper';
3334
import ContractFactory from '../../../factories/contractFactory';
@@ -950,7 +951,7 @@ describe('SecurityTokenWrapper', () => {
950951
test.todo('should fail as granularity is a zero big number');
951952

952953
test('should call to canTransferFrom', async () => {
953-
const expectedStatusCode = 'X';
954+
const expectedStatusCode = TransferStatusCodes.TransferSuccess;
954955
const expectedReasonCode = 'Reason';
955956
const expectedResult = [expectedStatusCode, stringToBytes32(expectedReasonCode)];
956957

@@ -1005,7 +1006,7 @@ describe('SecurityTokenWrapper', () => {
10051006
test.todo('should fail as granularity is a zero big number');
10061007

10071008
test('should call to canTransfer', async () => {
1008-
const expectedStatusCode = 'X';
1009+
const expectedStatusCode = TransferStatusCodes.TransferSuccess;
10091010
const expectedReasonCode = 'Reason';
10101011
const expectedResult = [expectedStatusCode, stringToBytes32(expectedReasonCode)];
10111012

@@ -1058,7 +1059,7 @@ describe('SecurityTokenWrapper', () => {
10581059
test.todo('should fail as granularity is a zero big number');
10591060

10601061
test('should call to canTransferByPartition', async () => {
1061-
const expectedStatusCode = 'X';
1062+
const expectedStatusCode = TransferStatusCodes.TransferSuccess;
10621063
const expectedReasonCode = 'Reason';
10631064
const expectedPartition = Partition.Unlocked;
10641065
const expectedResult = [
@@ -2532,9 +2533,9 @@ describe('SecurityTokenWrapper', () => {
25322533
test('should send the transaction to issue', async () => {
25332534
// Mocked parameters
25342535
const mockedParams = {
2535-
investor: '0x1111111111111111111111111111111111111111',
2536+
investor: '0x1234111111111111111111111111111111111111',
25362537
value: new BigNumber(2),
2537-
data: 'string',
2538+
data: '0x00',
25382539
txData: {},
25392540
safetyFactor: 10,
25402541
};
@@ -2571,16 +2572,28 @@ describe('SecurityTokenWrapper', () => {
25712572
// Mock web3 wrapper owner
25722573
when(mockedWrapper.getAvailableAddressesAsync()).thenResolve([expectedOwnerResult]);
25732574

2575+
// canTransefer
2576+
const expectedStatusCode = TransferStatusCodes.TransferSuccess;
2577+
const expectedReasonCode = 'Reason';
2578+
const expectedCanResult = [expectedStatusCode, stringToBytes32(expectedReasonCode)];
2579+
2580+
const mockedCanMethod = mock(MockedCallMethod);
2581+
when(mockedContract.canTransfer).thenReturn(instance(mockedCanMethod));
2582+
when(mockedCanMethod.callAsync({
2583+
to: mockedParams.investor,
2584+
value: objectContaining(valueToWei(mockedParams.value, expectedDecimalsResult)),
2585+
data: mockedParams.data
2586+
})).thenResolve(expectedCanResult);
2587+
25742588
const expectedIsIssuableResult = true;
25752589
// Mocked method
25762590
const mockedIsIssuableMethod = mock(MockedCallMethod);
25772591
// Stub the method
25782592
when(mockedContract.isIssuable).thenReturn(instance(mockedIsIssuableMethod));
25792593
// Stub the request
25802594
when(mockedIsIssuableMethod.callAsync()).thenResolve(expectedIsIssuableResult);
2581-
25822595
// Real call
2583-
const result = await target.issue(mockedParams);
2596+
const result = await target.issue(mockedParams);
25842597

25852598
// Result expectation
25862599
expect(result).toBe(expectedResult);
@@ -2602,6 +2615,12 @@ describe('SecurityTokenWrapper', () => {
26022615
verify(mockedWrapper.getAvailableAddressesAsync()).once();
26032616
verify(mockedContract.decimals).once();
26042617
verify(mockedDecimalsMethod.callAsync()).once();
2618+
verify(mockedContract.canTransfer).once()
2619+
verify(mockedCanMethod.callAsync({
2620+
to: mockedParams.investor,
2621+
value: objectContaining(valueToWei(mockedParams.value, expectedDecimalsResult)),
2622+
data: mockedParams.data
2623+
})).once()
26052624
});
26062625
});
26072626

src/contract_wrappers/tokens/security_token_wrapper.ts

Lines changed: 60 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@ import {
7373
SubscribeAsyncParams,
7474
TxParams,
7575
CappedSTOFundRaiseType,
76+
TransferStatusCodes
7677
} from '../../types';
7778
import {
7879
bigNumberToDate,
@@ -848,7 +849,7 @@ interface DocumentData {
848849

849850
interface CanTransferFromData {
850851
/** Status Code */
851-
statusCode: string;
852+
statusCode: TransferStatusCodes;
852853
/** Reason Code */
853854
reasonCode: string;
854855
}
@@ -1220,6 +1221,12 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
12201221
assert.isNonZeroETHAddressHex('investor', params.investor);
12211222
await this.checkOnlyOwner(params.txData);
12221223
assert.assert(await this.isIssuable(), 'Issuance frozen');
1224+
const canTransfer = await this.canTransfer({
1225+
to: params.investor,
1226+
value: params.value,
1227+
data: params.data || "0x00"
1228+
});
1229+
assert.assert(canTransfer.statusCode !== TransferStatusCodes.TransferFailure, `Transfer Status: ${canTransfer.statusCode}`)
12231230
return (await this.contract).issue.sendTransactionAsync(
12241231
params.investor,
12251232
valueToWei(params.value, await this.decimals()),
@@ -1571,6 +1578,52 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
15711578
return typedResult;
15721579
};
15731580

1581+
private getTransferStatusCode = (result: string) => {
1582+
let status: TransferStatusCodes = TransferStatusCodes.TransferSuccess;
1583+
switch(result) {
1584+
case "0x50": {
1585+
status = TransferStatusCodes.TransferFailure;
1586+
break
1587+
}
1588+
case "0x51": {
1589+
status = TransferStatusCodes.TransferSuccess;
1590+
break
1591+
}
1592+
case "0x52": {
1593+
status = TransferStatusCodes.InsufficientBalance;
1594+
break
1595+
}
1596+
case "0x53": {
1597+
status = TransferStatusCodes.InsufficientAllowance;
1598+
break
1599+
}
1600+
case "0x54": {
1601+
status = TransferStatusCodes.TransfersHalted;
1602+
break
1603+
}
1604+
case "0x55": {
1605+
status = TransferStatusCodes.FundsLocked;
1606+
break
1607+
}
1608+
case "0x56": {
1609+
status = TransferStatusCodes.InvalidSender;
1610+
break
1611+
}
1612+
case "0x57": {
1613+
status = TransferStatusCodes.InvalidReceiver;
1614+
break
1615+
}
1616+
case "0x58": {
1617+
status = TransferStatusCodes.InvalidOperator;
1618+
break
1619+
}
1620+
default: {
1621+
break
1622+
}
1623+
}
1624+
return status
1625+
}
1626+
15741627
/**
15751628
* Validates if can transfer
15761629
* @return statusCode, reasonCode
@@ -1582,9 +1635,9 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
15821635
valueToWei(params.value, await this.decimals()),
15831636
params.data,
15841637
);
1585-
1638+
const status = this.getTransferStatusCode(result[0]);
15861639
const typedResult: CanTransferFromData = {
1587-
statusCode: result[0],
1640+
statusCode: status,
15881641
reasonCode: bytes32ToString(result[1]),
15891642
};
15901643
return typedResult;
@@ -1603,8 +1656,9 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
16031656
valueToWei(params.value, await this.decimals()),
16041657
params.data,
16051658
);
1659+
const status = this.getTransferStatusCode(result[0]);
16061660
const typedResult: CanTransferFromData = {
1607-
statusCode: result[0],
1661+
statusCode: status,
16081662
reasonCode: bytes32ToString(result[1]),
16091663
};
16101664
return typedResult;
@@ -1624,8 +1678,9 @@ export default class SecurityTokenWrapper extends ERC20TokenWrapper {
16241678
valueToWei(params.value, await this.decimals()),
16251679
params.data,
16261680
);
1681+
const status = this.getTransferStatusCode(result[0]);
16271682
const typedResult: CanTransferByPartitionData = {
1628-
statusCode: result[0],
1683+
statusCode: status,
16291684
reasonCode: bytes32ToString(result[1]),
16301685
partition: parsePartitionBytes32Value(result[2]),
16311686
};

src/types.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,18 @@ export enum ModuleName {
159159
EtherDividendCheckpoint = 'EtherDividendCheckpoint',
160160
}
161161

162+
export enum TransferStatusCodes {
163+
TransferFailure = 'TransferFailure',
164+
TransferSuccess = 'TransferSuccess',
165+
InsufficientBalance = 'InsufficientBalance',
166+
InsufficientAllowance = 'InsufficientAllowance',
167+
TransfersHalted = 'TransfersHalted',
168+
FundsLocked = 'FundsLocked',
169+
InvalidSender = 'InvalidSender',
170+
InvalidReceiver = 'InvalidReceiver',
171+
InvalidOperator = 'InvalidOperator',
172+
}
173+
162174
export enum Perm {
163175
Admin = 'ADMIN',
164176
Operator = 'OPERATOR',

0 commit comments

Comments
 (0)