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

Commit

Permalink
Merge 7e2d068 into dd0ee90
Browse files Browse the repository at this point in the history
  • Loading branch information
shuffledex committed Nov 27, 2019
2 parents dd0ee90 + 7e2d068 commit a1300ae
Show file tree
Hide file tree
Showing 13 changed files with 549 additions and 174 deletions.
6 changes: 4 additions & 2 deletions examples/usdTieredSTO.ts
Expand Up @@ -26,10 +26,12 @@ export const usdTieredSTO = async (polymathAPI: PolymathAPI, ticker: string) =>
tokensPerTierDiscountPoly: [new BigNumber(8), new BigNumber(8)],
nonAccreditedLimitUSD: new BigNumber(5),
minimumInvestmentUSD: new BigNumber(5),
fundRaiseTypes: [FundRaiseType.ETH, FundRaiseType.POLY],
fundRaiseTypes: [FundRaiseType.StableCoin],
wallet: '0x3333333333333333333333333333333333333333',
treasuryWallet: '0x5555555555555555555555555555555555555555',
usdTokens: ['0x6666666666666666666666666666666666666666', '0x4444444444444444444444444444444444444444'],
stableTokens: ['0x6666666666666666666666666666666666666666', '0x4444444444444444444444444444444444444444'],
customOracleAddresses: ['0x1666666666666666666666666666666666666666', '0x1444444444444444444444444444444444444444'],
denominatedCurrency: 'USDC',
};
const options: AddingModuleOpts = {
data: usdTieredSTOData,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Expand Up @@ -88,7 +88,7 @@
"@0x/subproviders": "5.0.4",
"@0x/types": "2.4.3",
"@0x/typescript-typings": "4.3.0",
"@polymathnetwork/abi-wrappers": "4.0.0-beta.8",
"@polymathnetwork/abi-wrappers": "4.0.0-beta.9",
"@types/bluebird": "^3.5.27",
"@types/semver": "^6.0.1",
"bluebird": "^3.5.5",
Expand Down
35 changes: 33 additions & 2 deletions src/contract_wrappers/modules/sto/usd_tiered_sto_wrapper/3.0.0.ts
@@ -1,11 +1,20 @@
import { USDTieredSTOContract_3_0_0, BigNumber, Web3Wrapper } from '@polymathnetwork/abi-wrappers';
import { USDTieredSTOContract_3_0_0, BigNumber, Web3Wrapper, PolyResponse } from '@polymathnetwork/abi-wrappers';
import USDTieredSTOCommon, { TierIndexParams } from './common';
import assert from '../../../../utils/assert';
import { ErrorCode, ContractVersion, TxParams, FULL_DECIMALS, Constructor } from '../../../../types';
import { ErrorCode, ContractVersion, TxParams, FULL_DECIMALS, Constructor, FundRaiseType } from '../../../../types';
import { numberToBigNumber, weiToValue } from '../../../../utils/convert';
import ContractFactory from '../../../../factories/contractFactory';
import { WithSTO_3_0_0 } from '../sto_wrapper';

/**
* @param fundRaiseType Actual currency
* @param oracleAddress Address of the oracle
*/
export interface ModifyOracleParams extends TxParams {
fundRaiseType: FundRaiseType;
oracleAddress: string;
}

interface MintedByTier {
mintedInETH: BigNumber;
mintedInPOLY: BigNumber;
Expand Down Expand Up @@ -125,6 +134,28 @@ export class USDTieredSTO_3_0_0 extends USDTieredSTOBase_3_0_0 {
// we can't execute mint to validate the method
return (await this.contract).finalize.sendTransactionAsync(params.txData, params.safetyFactor);
};

/**
* Modifies oracle
*/
public modifyOracle = async (params: ModifyOracleParams): Promise<PolyResponse> => {
assert.assert(
await this.isCallerTheSecurityTokenOwner(params.txData),
ErrorCode.Unauthorized,
'The caller must be the ST owner',
);
assert.assert(
params.fundRaiseType === FundRaiseType.POLY || params.fundRaiseType === FundRaiseType.ETH,
ErrorCode.InvalidData,
'Invalid currency',
);
return (await this.contract).modifyOracle.sendTransactionAsync(
params.fundRaiseType,
params.oracleAddress,
params.txData,
params.safetyFactor,
);
};
}

export function isUSDTieredSTO_3_0_0(wrapper: USDTieredSTOCommon): wrapper is USDTieredSTO_3_0_0 {
Expand Down
123 changes: 122 additions & 1 deletion src/contract_wrappers/modules/sto/usd_tiered_sto_wrapper/3.1.0.ts
Expand Up @@ -2,12 +2,15 @@ import {
USDTieredSTOContract_3_1_0,
USDTieredSTOEvents_3_1_0,
USDTieredSTOEventArgs_3_1_0,
USDTieredSTOSetOraclesEventArgs_3_1_0,
USDTieredSTOUsageFeeDeductedEventArgs_3_1_0,
USDTieredSTOReserveTokenTransferEventArgs_3_1_0,
USDTieredSTOAllowPreMintFlagEventArgs_3_1_0,
USDTieredSTORevokePreMintFlagEventArgs_3_1_0,
LogWithDecodedArgs,
BigNumber,
Web3Wrapper,
PolyResponse,
} from '@polymathnetwork/abi-wrappers';
import { schemas } from '@0x/json-schemas';
import USDTieredSTOCommon, {
Expand All @@ -24,11 +27,38 @@ import {
FULL_DECIMALS,
Constructor,
EventCallback,
TxParams,
FundRaiseType,
} from '../../../../types';
import { numberToBigNumber, weiToValue, bigNumberToDate, weiArrayToValueArray } from '../../../../utils/convert';
import {
numberToBigNumber,
weiToValue,
bigNumberToDate,
weiArrayToValueArray,
stringToBytes32,
bytes32ToString,
} from '../../../../utils/convert';
import ContractFactory from '../../../../factories/contractFactory';
import { WithSTO_3_1_0 } from '../sto_wrapper';

interface SetOraclesSubscribeAsyncParams extends SubscribeAsyncParams {
eventName: USDTieredSTOEvents_3_1_0.SetOracles;
callback: EventCallback<USDTieredSTOSetOraclesEventArgs_3_1_0>;
}

interface GetSetOraclesLogsAsyncParams extends GetLogsAsyncParams {
eventName: USDTieredSTOEvents_3_1_0.SetOracles;
}

interface UsageFeeDeductedSubscribeAsyncParams extends SubscribeAsyncParams {
eventName: USDTieredSTOEvents_3_1_0.UsageFeeDeducted;
callback: EventCallback<USDTieredSTOUsageFeeDeductedEventArgs_3_1_0>;
}

interface GetUsageFeeDeductedLogsAsyncParams extends GetLogsAsyncParams {
eventName: USDTieredSTOEvents_3_1_0.UsageFeeDeducted;
}

interface ReserveTokenTransferSubscribeAsyncParams extends SubscribeAsyncParams {
eventName: USDTieredSTOEvents_3_1_0.ReserveTokenTransfer;
callback: EventCallback<USDTieredSTOReserveTokenTransferEventArgs_3_1_0>;
Expand Down Expand Up @@ -60,6 +90,8 @@ interface USDTieredSTOSubscribeAsyncParams_3_1_0 extends USDTieredSTOSubscribeAs
(params: ReserveTokenTransferSubscribeAsyncParams): Promise<string>;
(params: AllowPreMintFlagSubscribeAsyncParams): Promise<string>;
(params: RevokePreMintFlagSubscribeAsyncParams): Promise<string>;
(params: SetOraclesSubscribeAsyncParams): Promise<string>;
(params: UsageFeeDeductedSubscribeAsyncParams): Promise<string>;
}

interface GetUSDTieredSTOLogsAsyncParams_3_1_0 extends GetUSDTieredSTOLogsAsyncParams {
Expand All @@ -72,6 +104,10 @@ interface GetUSDTieredSTOLogsAsyncParams_3_1_0 extends GetUSDTieredSTOLogsAsyncP
(params: GetRevokePreMintFlagLogsAsyncParams): Promise<
LogWithDecodedArgs<USDTieredSTORevokePreMintFlagEventArgs_3_1_0>[]
>;
(params: GetSetOraclesLogsAsyncParams): Promise<LogWithDecodedArgs<USDTieredSTOSetOraclesEventArgs_3_1_0>[]>;
(params: GetUsageFeeDeductedLogsAsyncParams): Promise<
LogWithDecodedArgs<USDTieredSTOUsageFeeDeductedEventArgs_3_1_0>[]
>;
}

interface MintedByTier {
Expand Down Expand Up @@ -107,6 +143,22 @@ export interface USDTieredSTOData {
preMintingAllowed: boolean;
}

/**
* @param customOracleAddresses Addresses of the oracles
* @param denominatedCurrencySymbol Symbol of the Fiat currency used for denomination
*/
export interface ModifyOraclesParams extends TxParams {
customOracleAddresses: string[];
denominatedCurrencySymbol: string;
}

/**
* @param fundRaiseType Fund raise type to get rate of
*/
export interface GetCustomOracleAddressParams {
fundRaiseType: FundRaiseType;
}

interface Tier {
/** How many token units a buyer gets per USD in this tier */
rate: BigNumber;
Expand Down Expand Up @@ -217,6 +269,75 @@ export class USDTieredSTO_3_1_0 extends USDTieredSTOBase_3_1_0 {
return typedResult;
};

/**
* Return symbol of the denominated currency
* @return token symbol string
*/
public denominatedCurrency = async () => {
const result = await (await this.contract).denominatedCurrency.callAsync();
return bytes32ToString(result);
};

/**
* Modifies oracle
*/
public modifyOracles = async (params: ModifyOraclesParams): Promise<PolyResponse> => {
assert.assert(
await this.isCallerTheSecurityTokenOwner(params.txData),
ErrorCode.Unauthorized,
'The caller must be the ST owner',
);

if ((await this.denominatedCurrency()) !== params.denominatedCurrencySymbol) {
assert.isFutureDate(
await this.startTime(),
"The denominated currency can change only if the STO hasn't started yet",
);
}

if (params.customOracleAddresses.length > 0) {
assert.assert(
params.denominatedCurrencySymbol !== '',
ErrorCode.InvalidData,
'Denominated currency symbol can not be empty',
);
assert.assert(
params.customOracleAddresses.length === 2,
ErrorCode.InvalidLength,
'Custom oracle addresses array must have two values',
);

if (await this.fundRaiseTypes({ type: FundRaiseType.ETH })) {
assert.isNonZeroETHAddressHex('ETH Oracle Address', params.customOracleAddresses[0]);
}

if (await this.fundRaiseTypes({ type: FundRaiseType.POLY })) {
assert.isNonZeroETHAddressHex('POLY Oracle Address', params.customOracleAddresses[1]);
}
} else {
assert.assert(
params.denominatedCurrencySymbol === '',
ErrorCode.InvalidData,
'Invalid denominatedCurrencySymbol',
);
}

return (await this.contract).modifyOracles.sendTransactionAsync(
params.customOracleAddresses,
stringToBytes32(params.denominatedCurrencySymbol),
params.txData,
params.safetyFactor,
);
};

/**
* Returns the custom oracle address
*/
public getCustomOracleAddress = async (params: GetCustomOracleAddressParams) => {
const result = await (await this.contract).getCustomOracleAddress.callAsync(params.fundRaiseType);
return result;
};

/**
* Subscribe to an event type emitted by the contract.
* @return Subscription token used later to unsubscribe
Expand Down
Expand Up @@ -12,9 +12,9 @@ import USDTieredSTOCommon from '../common';
import { USDTieredSTO_3_0_0 } from '../3.0.0';
import ContractFactory from '../../../../../factories/contractFactory';
import { weiToValue } from '../../../../../utils/convert';
import { FULL_DECIMALS } from '../../../../../types';
import { FULL_DECIMALS, FundRaiseType } from '../../../../../types';

describe('USD Tiered STO 3.0.0', () => {
describe('USD Tiered STO 3.0.0', () => {
let target: USDTieredSTO_3_0_0;
let mockedWrapper: Web3Wrapper;
let mockedContract: USDTieredSTOContract_3_0_0;
Expand Down Expand Up @@ -318,6 +318,72 @@ describe('USD Tiered STO 3.0.0', () => {
});
});

describe('ModifyOracle', () => {
test('should modifyOracle', async () => {
// Mock Only Owner and Security Token
const expectedOwnerResult = '0x5555555555555555555555555555555555555555';
// Security Token Address expected
const expectedSecurityTokenAddress = '0x3333333333333333333333333333333333333333';
// Setup get Security Token Address
const mockedGetSecurityTokenAddressMethod = mock(MockedCallMethod);
when(mockedContract.securityToken).thenReturn(instance(mockedGetSecurityTokenAddressMethod));
when(mockedGetSecurityTokenAddressMethod.callAsync()).thenResolve(expectedSecurityTokenAddress);
when(mockedContractFactory.getSecurityTokenContract(expectedSecurityTokenAddress)).thenResolve(
instance(mockedSecurityTokenContract),
);
const mockedSecurityTokenOwnerMethod = mock(MockedCallMethod);
when(mockedSecurityTokenOwnerMethod.callAsync()).thenResolve(expectedOwnerResult);
when(mockedSecurityTokenContract.owner).thenReturn(instance(mockedSecurityTokenOwnerMethod));

// Mock web3 wrapper owner
when(mockedWrapper.getAvailableAddressesAsync()).thenResolve([expectedOwnerResult]);

const mockedParams = {
oracleAddress: '0x1111111111111111111111111111111111111111',
fundRaiseType: FundRaiseType.ETH,
txData: {},
safetyFactor: 10,
};

const expectedResult = getMockedPolyResponse();
// Mocked method
const mockedMethod = mock(MockedSendMethod);
// Stub the method
when(mockedContract.modifyOracle).thenReturn(instance(mockedMethod));
// Stub the request
when(
mockedMethod.sendTransactionAsync(
mockedParams.fundRaiseType,
mockedParams.oracleAddress,
mockedParams.txData,
mockedParams.safetyFactor,
),
).thenResolve(expectedResult);

// Real call
const result = await target.modifyOracle(mockedParams);

// Result expectation
expect(result).toBe(expectedResult);
// Verifications
verify(mockedContract.modifyOracle).once();
verify(
mockedMethod.sendTransactionAsync(
mockedParams.fundRaiseType,
mockedParams.oracleAddress,
mockedParams.txData,
mockedParams.safetyFactor,
),
).once();
verify(mockedContract.securityToken).once();
verify(mockedGetSecurityTokenAddressMethod.callAsync()).once();
verify(mockedContractFactory.getSecurityTokenContract(expectedSecurityTokenAddress)).once();
verify(mockedSecurityTokenOwnerMethod.callAsync()).once();
verify(mockedSecurityTokenContract.owner).once();
verify(mockedWrapper.getAvailableAddressesAsync()).once();
});
});

describe('SubscribeAsync', () => {
test('should throw as eventName does not belong to FeatureRegistryEvents', async () => {
// Mocked parameters
Expand Down

0 comments on commit a1300ae

Please sign in to comment.