diff --git a/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java b/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java index 481fae4dc0d..0b8288abab2 100755 --- a/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java +++ b/src/main/java/org/tron/core/actuator/ExchangeTransactionActuator.java @@ -135,13 +135,18 @@ public boolean validate() throws ContractValidateException { byte[] tokenID = contract.getTokenId().toByteArray(); long tokenQuant = contract.getQuant(); + long tokenExpected = contract.getExpected(); if (!Arrays.equals(tokenID, firstTokenID) && !Arrays.equals(tokenID, secondTokenID)) { throw new ContractValidateException("token is not in exchange"); } if (tokenQuant <= 0) { - throw new ContractValidateException("transaction token balance must greater than zero"); + throw new ContractValidateException("token quant must greater than zero"); + } + + if (tokenExpected <= 0) { + throw new ContractValidateException("token expected must greater than zero"); } if (firstTokenBalance == 0 || secondTokenBalance == 0) { @@ -168,8 +173,8 @@ public boolean validate() throws ContractValidateException { } long anotherTokenQuant = exchangeCapsule.transaction(tokenID, tokenQuant); - if (anotherTokenQuant < 1) { - throw new ContractValidateException("token quant is not enough to buy 1 another token"); + if (anotherTokenQuant < tokenExpected) { + throw new ContractValidateException("token required must greater than expected"); } return true; diff --git a/src/main/protos/core/Contract.proto b/src/main/protos/core/Contract.proto index 5d5c1421f9a..18eafded8f8 100644 --- a/src/main/protos/core/Contract.proto +++ b/src/main/protos/core/Contract.proto @@ -225,4 +225,5 @@ message ExchangeTransactionContract { int64 exchange_id = 2; bytes token_id = 3; int64 quant = 4; + int64 expected = 5; } \ No newline at end of file diff --git a/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java b/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java index edea2de6f39..716619a6895 100644 --- a/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java +++ b/src/test/java/org/tron/core/actuator/ExchangeTransactionActuatorTest.java @@ -130,13 +130,15 @@ public void initTest() { dbManager.getDynamicPropertiesStore().saveNextMaintenanceTime(2000000); } - private Any getContract(String address, long exchangeId, String tokenId, long quant) { + private Any getContract(String address, long exchangeId, String tokenId, + long quant, long expected) { return Any.pack( Contract.ExchangeTransactionContract.newBuilder() .setOwnerAddress(ByteString.copyFrom(ByteArray.fromHexString(address))) .setExchangeId(exchangeId) .setTokenId(ByteString.copyFrom(tokenId.getBytes())) .setQuant(quant) + .setExpected(expected) .build()); } @@ -156,7 +158,7 @@ public void successExchangeTransaction() { Assert.assertEquals(null, assetMap.get("def")); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -221,7 +223,7 @@ public void successExchangeTransaction2() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -286,7 +288,7 @@ public void invalidAddress() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_INVALID, exchangeId, tokenId, quant), + OWNER_ADDRESS_INVALID, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -321,7 +323,7 @@ public void noAccount() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_NOACCOUNT, exchangeId, tokenId, quant), + OWNER_ADDRESS_NOACCOUNT, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -357,7 +359,7 @@ public void exchangeNotExist() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -393,7 +395,7 @@ public void tokenIsNotInExchange() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -429,7 +431,7 @@ public void tokenBalanceZero() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -455,7 +457,7 @@ public void tokenBalanceZero() { } /** - * withdraw token quant must greater than zero + * token quant must greater than zero */ @Test public void tokenQuantLessThanZero() { @@ -473,7 +475,7 @@ public void tokenQuantLessThanZero() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -483,7 +485,7 @@ public void tokenQuantLessThanZero() { fail(); } catch (ContractValidateException e) { Assert.assertTrue(e instanceof ContractValidateException); - Assert.assertEquals("transaction token balance must greater than zero", + Assert.assertEquals("token quant must greater than zero", e.getMessage()); } catch (ContractExeException e) { Assert.assertFalse(e instanceof ContractExeException); @@ -509,7 +511,7 @@ public void tokenBalanceGreaterThanBalanceLimit() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -544,7 +546,7 @@ public void balanceNotEnough() { dbManager.getAccountStore().put(ownerAddress, accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -562,7 +564,7 @@ public void balanceNotEnough() { } /** - * first token balance is not enough + * token balance is not enough */ @Test public void tokenBalanceNotEnough() { @@ -580,7 +582,7 @@ public void tokenBalanceNotEnough() { dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( - OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant), + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, 1), dbManager); TransactionResultCapsule ret = new TransactionResultCapsule(); @@ -596,4 +598,49 @@ public void tokenBalanceNotEnough() { Assert.assertFalse(e instanceof ContractExeException); } } + + /** + * token required must greater than expected + */ + @Test + public void tokenRequiredNotEnough() { + long exchangeId = 2; + String tokenId = "abc"; + long quant = 1_000L; + String buyTokenId = "def"; + + byte[] ownerAddress = ByteArray.fromHexString(OWNER_ADDRESS_SECOND); + AccountCapsule accountCapsule = dbManager.getAccountStore().get(ownerAddress); + accountCapsule.addAssetAmount(tokenId.getBytes(), quant); + Map assetMap = accountCapsule.getAssetMap(); + Assert.assertEquals(20000_000000L, accountCapsule.getBalance()); + Assert.assertEquals(null, assetMap.get(buyTokenId)); + dbManager.getAccountStore().put(accountCapsule.createDbKey(), accountCapsule); + + long expected = 0; + try { + ExchangeCapsule exchangeCapsule = dbManager.getExchangeStore() + .get(ByteArray.fromLong(exchangeId)); + expected = exchangeCapsule.transaction(tokenId.getBytes(), quant); + } catch (ItemNotFoundException e) { + fail(); + } + + ExchangeTransactionActuator actuator = new ExchangeTransactionActuator(getContract( + OWNER_ADDRESS_SECOND, exchangeId, tokenId, quant, expected + 1), + dbManager); + TransactionResultCapsule ret = new TransactionResultCapsule(); + + try { + actuator.validate(); + actuator.execute(ret); + fail("should not run here"); + } catch (ContractValidateException e) { + Assert.assertTrue(e instanceof ContractValidateException); + Assert.assertEquals("token required must greater than expected", + e.getMessage()); + } catch (ContractExeException e) { + Assert.assertFalse(e instanceof ContractExeException); + } + } } \ No newline at end of file