boolean pending = paymentLog.getTransactionStatus() == TransactionStatus.PENDING; boolean allocationMailSent = paymentLog.isAllocationMessageSent(); boolean refundEntryExists = paymentLog.getEligibleForRefund() == null;
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testDistributeToSingleTier() throws Throwable { // setup TestTier tt = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.2"), new BigInteger("1000").multiply(tomicsFactor()), true, false); Date blockTime = Date.valueOf("1970-01-02"); final BigInteger tomicsToSell = tt.getTomicsMax().divide(BigInteger.valueOf(2)); tt.tomicsSoldMustBe(tomicsToSell); final BigDecimal payment = monitorService.convertTomicsToUsd(tomicsToSell, tt.getDiscount()); // test PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsToSell)); tt.assertTier(); }
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testOverflowWithSingleTier() throws Throwable { // setup TestTier tt = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), new BigInteger("1000").multiply(tomicsFactor()), true, false); Date blockTime = Date.valueOf("1970-01-02"); tt.newEndDateMustBe(blockTime); tt.mustBeFull(); final BigDecimal overflow = BigDecimal.TEN; final BigDecimal payment = monitorService.convertTomicsToUsd(tt.getTomicsMax(), tt.getDiscount()) .add(overflow); // test PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() == null) fail(); // rounding the resulting USD overflow because that will be the actual precision with which the overflow // will be stored for refunds. assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(overflow)); assertEquals(0, log.getAllocatedTomics().compareTo(tt.getTomicsMax())); tt.assertTier(); }
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testConcurrentPaymentsWithoutOverflow() throws InterruptedException { final Date blockTime = Date.valueOf("1970-01-02"); final TestTier t = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), totalTomicsAmount().divide(new BigInteger("2")), true, false); int nrOfPayments = 10; BigDecimal singlePayment = BigDecimal.ONE; BigInteger singleSoldTomics = monitorService.convertUsdToTomics(singlePayment, t.getDiscount()).toBigInteger(); t.tomicsSoldMustBe(singleSoldTomics.multiply(BigInteger.valueOf(nrOfPayments))); Investor investor = createInvestor(); ThreadTestUtils.runMultiThread( () -> { try { PaymentLog log = createPaymentLog(singlePayment, blockTime, investor); log = ethereumMonitor.allocateTokensWithRetries(log); if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(singleSoldTomics)); LOG.info("Distributed tomics: {}", log.getAllocatedTomics().toString()); } catch (Throwable throwable) { throwable.printStackTrace(); } }, nrOfPayments ); t.assertTier(); }
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testOverflowTotalTokenAmountButNotTier() throws Throwable { // setup final Date blockTime = Date.valueOf("1970-01-02"); // tier with a capacity of total token amount plus one token. final TestTier tt1 = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), totalTomicsAmount().add(tomicsFactor()), true, false); tt1.tomicsSoldMustBe(totalTomicsAmount()); final BigDecimal overflow = appConfig.getFiatBasePerToken().divide(new BigDecimal("2")); final BigDecimal payment = monitorService.convertTomicsToUsd(totalTomicsAmount(), tt1.getDiscount()).add(overflow); // test PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(totalTomicsAmount())); assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(overflow)); tt1.assertTier(); }
/** * Prepares and converts a payment in the amount of tokenMax (from the given tier) divided by the given divisor. * Fails if the conversion throws a TokenAllocationResult. Asserts the returned amount of tokens. * Sets the amount of tokens that have to be sold on the given test tier for later assertions. */ private void makeAndConvertPaymentFailingOnOverflow(TestTier t, Date blockTime, int divisor) throws Throwable { BigInteger tomicsFromTier = t.getTomicsMax().divide(BigInteger.valueOf(divisor)); BigDecimal payment = monitorService.convertTomicsToUsd(tomicsFromTier, t.getDiscount()); t.tomicsSoldMustBe(t.tomicsSold.add(tomicsFromTier)); PaymentLog log = createPaymentLog(payment, blockTime, createInvestor()); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsFromTier)); }
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testOverflowTotalTokenAmountInSecondTier() throws Throwable { final BigInteger tomicsOverflowOverTier1 = tomicsFactor(); final Date blockTime = Date.valueOf("1970-01-02"); final TestTier tt1 = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), totalTomicsAmount().subtract(tomicsOverflowOverTier1), true, false); tt1.mustBeFull(); tt1.newEndDateMustBe(blockTime); final TestTier tt2 = new TestTier(2, "1970-01-03", "1970-01-05", new BigDecimal("0.10"), totalTomicsAmount(), true, false); tt2.tomicsSoldMustBe(tomicsOverflowOverTier1); tt2.datesMustBeShiftedBy(tt1.getTier().getEndDate().getTime() - blockTime.getTime()); // payment setup final BigInteger tomicsToTier2 = tomicsOverflowOverTier1.multiply(BigInteger.valueOf(2)); final BigDecimal paymentToTier1 = monitorService.convertTomicsToUsd(tt1.getTomicsMax(), tt1.getDiscount()); final BigDecimal paymentToTier2 = monitorService.convertTomicsToUsd(tomicsToTier2, tt2.getDiscount()); final BigDecimal payment = paymentToTier1.add(paymentToTier2); final BigDecimal overflow = paymentToTier2.divide(new BigDecimal(2), new MathContext(6, RoundingMode.HALF_EVEN)); // test PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(totalTomicsAmount())); assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(overflow)); tt1.assertTier(); tt2.assertTier(); }
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testOverflowTotalTokenAmountWithHalfFullTier() throws Throwable { final Date blockTime = Date.valueOf("1970-01-02"); // tier with a capacity of total token amount plus one token. final TestTier t = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), totalTomicsAmount().add(tomicsFactor()), true, false); BigInteger tomicsFromTier = totalTomicsAmount().divide(new BigInteger("2")); BigDecimal payment = monitorService.convertTomicsToUsd(tomicsFromTier, t.getDiscount()); PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); t.tomicsSoldMustBe(tomicsFromTier); if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsFromTier)); t.assertTier(); final BigDecimal overflow = appConfig.getFiatBasePerToken().divide(new BigDecimal("2")); payment = monitorService.convertTomicsToUsd(tomicsFromTier, t.getDiscount()).add(overflow); t.tomicsSoldMustBe(totalTomicsAmount()); log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsFromTier)); assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(overflow)); t.assertTier(); }
PaymentLog log = createPaymentLog(singlePayment, blockTime, investor); log = ethereumMonitor.allocateTokensWithRetries(log); if (log.getEligibleForRefund() != null) fail(); LOG.info("Distributed tomics: {}", log.getAllocatedTomics().toString()); } catch (Throwable throwable) {
if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tt1.getTomicsMax().add(tt2.getTomicsMax()).add(tt3.getTomicsMax()))); assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(overflow)); tt1.assertTier(); tt2.assertTier(); if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(BigInteger.ZERO)); assertEquals(0, log.getEligibleForRefund().getUsdAmount().compareTo(BigDecimal.TEN));
/** * Two tiers, one payment that spills into the second tier. First tier has static duration behavior and therefore * doesn't change his end date nore the dates of the next tiers. */ @Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testOverflowIntoSecondTierStaticDuration() throws Throwable { // setup Date blockTime = Date.valueOf("1970-01-02"); TestTier tt1 = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), new BigInteger("1000").multiply(tomicsFactor()), false, false); final BigInteger tomicsToSellFromTier1 = tt1.getTomicsMax(); tt1.mustBeFull(); tt1.tomicsSoldMustBe(tomicsToSellFromTier1); TestTier tt2 = new TestTier(2, "1970-01-03", "1970-01-05", new BigDecimal("0.1"), new BigInteger("1000").multiply(tomicsFactor()), false, false); final BigInteger tomicsToSellFromTier2 = tt2.getTomicsMax().divide(BigInteger.valueOf(3)); tt2.tomicsSoldMustBe(tomicsToSellFromTier2); final BigDecimal paymentToTier1 = monitorService.convertTomicsToUsd(tomicsToSellFromTier1, tt1.getDiscount()); final BigDecimal paymentToTier2 = monitorService.convertTomicsToUsd(tomicsToSellFromTier2, tt2.getDiscount()); BigDecimal payment = paymentToTier1.add(paymentToTier2); // test PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsToSellFromTier1.add(tomicsToSellFromTier2))); tt1.assertTier(); tt2.assertTier(); makeAndConvertPaymentFailingOnOverflow(tt2, blockTime, 3); tt1.assertTier(); tt2.assertTier(); }
@Test @Transactional(propagation = Propagation.NOT_SUPPORTED) public void testOverflowTotalTokenAmountAndTier() throws Throwable { // setup final Date blockTime = Date.valueOf("1970-01-02"); // tier with a capacity of total token amount plus one token. final TestTier tt1 = new TestTier(1, "1970-01-01", "1970-01-03", new BigDecimal("0.25"), totalTomicsAmount().add(tomicsFactor()), true, false); tt1.tomicsSoldMustBe(totalTomicsAmount()); // only the total amount of tokens can be disttributed/converted. final BigDecimal usdAmountConverted = monitorService.convertTomicsToUsd(totalTomicsAmount(), tt1.getDiscount()); final BigDecimal overflowOverTier = BigDecimal.TEN; final BigDecimal payment = monitorService.convertTomicsToUsd(tt1.getTomicsMax(), tt1.getDiscount()) .add(overflowOverTier); final BigDecimal overflow = payment.subtract(usdAmountConverted); // test PaymentLog log = createPaymentLog(payment, blockTime); log = monitorService.allocateTokens(log); if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(totalTomicsAmount())); assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(overflow)); tt1.assertTier(); }
log = monitorService.allocateTokens(log); assertEquals(0, tomicsFromTier1.compareTo(log.getAllocatedTomics())); if (log.getEligibleForRefund() != null) fail(); tiers.forEach(TestTier::assertTier); log = monitorService.allocateTokens(log); assertEquals(0, tomicsFromTier3.compareTo(log.getAllocatedTomics())); if (log.getEligibleForRefund() != null) fail(); tiers.forEach(TestTier::assertTier); log = monitorService.allocateTokens(log); assertEquals(0, overallRemainingTomics.compareTo(log.getAllocatedTomics())); if (log.getEligibleForRefund() == null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(overallRemainingTomics)); assertEquals(0, log.getEligibleForRefund().getUsdAmount().round(new MathContext(6, RoundingMode.HALF_EVEN)).compareTo(BigDecimal.TEN)); tiers.forEach(TestTier::assertTier); assertEquals(0, totalTomicsAmount().compareTo(saleTierService.getTotalTomicsSold()));
if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsToSellFromTier1.add(tomicsToSellFromTier2))); tt1.assertTier();
if (log.getEligibleForRefund() != null) fail(); assertEquals(0, log.getAllocatedTomics().compareTo(tomicsToSellFromTier1.add(tomicsToSellFromTier2))); tt1.assertTier();