public void Buy_CalculatesStratoshisToSend_Success(ulong amountToBuy, uint fullTokenInStratoshies)
        {
            amountToBuy = DefaultAmount >= amountToBuy ? amountToBuy : DefaultAmount;

            var order = NewSimpleSellOrder(Seller, DefaultZeroValue, DefaultPrice, DefaultAmount, fullTokenInStratoshies);

            ulong orderCost = amountToBuy * DefaultPrice;
            ulong updatedContractBalance = order.Balance - orderCost;

            MockContractState.Setup(x => x.Message).Returns(new Message(ContractAddress, BuyerOne, orderCost));

            var amountInStratoshis = amountToBuy * fullTokenInStratoshies;
            var expectedCallParams = new object[] { Seller, BuyerOne, amountInStratoshis };

            MockInternalExecutor.Setup(x =>
                                       x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0))
            .Returns(TransferResult.Transferred(true));

            MockInternalExecutor.Setup(x => x.Transfer(It.IsAny <ISmartContractState>(), It.IsAny <Address>(), It.IsAny <ulong>()))
            .Callback(() => MockContractState.Setup(x => x.GetBalance).Returns(() => updatedContractBalance));

            MockPersistentState.Setup(x => x.SetUInt64(nameof(Amount), DefaultAmount - amountToBuy))
            .Callback(() => MockPersistentState.Setup(x => x.GetUInt64(nameof(Amount))).Returns(DefaultAmount - amountToBuy));

            order.Buy(amountToBuy);

            MockInternalExecutor.Verify(x =>
                                        x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0), Times.Once);

            MockContractState.Verify(x => x.InternalTransactionExecutor
                                     .Transfer(It.IsAny <ISmartContractState>(), Seller, orderCost), Times.Once);
        }
        public void Success_GetOrderDetails()
        {
            var order = NewSimpleSellOrder(Seller, DefaultZeroValue, DefaultPrice, DefaultAmount);

            MockContractState.Setup(x => x.Message).Returns(new Message(ContractAddress, BuyerOne, DefaultZeroValue));

            var expectedBalance    = DefaultAmount * 100_000_000;
            var expectedCallParams = new object[] { Seller, ContractAddress };

            MockInternalExecutor.Setup(x =>
                                       x.Call(It.IsAny <ISmartContractState>(), Token, 0, "Allowance", expectedCallParams, 0))
            .Returns(TransferResult.Transferred(expectedBalance));

            var actualOrderDetails = order.GetOrderDetails();

            var expectedOrderDetails = new OrderDetails
            {
                Seller    = Seller,
                Token     = Token,
                Price     = DefaultPrice,
                Amount    = DefaultAmount,
                OrderType = nameof(SimpleSellOrder),
                IsActive  = true,
                Balance   = expectedBalance
            };

            Assert.Equal(expectedOrderDetails, actualOrderDetails);
        }
        public void Buy_Fails_If_SrcTransfer_Fails()
        {
            var order = NewSimpleSellOrder(Seller, DefaultZeroValue, DefaultPrice, DefaultAmount);

            MockContractState.Setup(x => x.Message).Returns(new Message(ContractAddress, BuyerOne, DefaultCostValue));

            var amountInStratoshis = DefaultAmount * 100_000_000;
            var expectedCallParams = new object[] { Seller, BuyerOne, amountInStratoshis };

            MockInternalExecutor.Setup(x =>
                                       x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0))
            .Returns(TransferResult.Transferred(false));

            Assert.ThrowsAny <SmartContractAssertException>(() => order.Buy(DefaultAmount));

            MockInternalExecutor.Verify(x =>
                                        x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0), Times.Once);

            MockInternalExecutor.Verify(x => x.Transfer(It.IsAny <ISmartContractState>(), Seller, DefaultCostValue), Times.Never);

            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), It.IsAny <Transaction>()), Times.Never);

            MockPersistentState.Verify(x => x.SetUInt64(nameof(Amount), 0), Times.Never);

            MockPersistentState.Verify(x => x.SetBool(nameof(IsActive), false), Times.Never);
        }
        public void Approve_Succeeds(ulong amountToTransfer, ulong contractBalance)
        {
            var contract = Newcontract(Owner, Owner, 0, StartTime, EndTime);

            MockPersistentState.Setup(s => s.GetString($"Status:{ApplicationId}")).Returns(ApprovedStatus);
            MockPersistentState.Setup(x => x.GetInt32($"{ApplicationId}:Category")).Returns(ApplicationDefaultCategory);
            MockPersistentState.Setup(s => s.GetAddress($"{ApplicationId}")).Returns(Applicant);
            MockPersistentState.Setup(s => s.GetUInt64($"Category:{ApplicationDefaultCategory}")).Returns(amountToTransfer);
            MockContractState.Setup(x => x.GetBalance).Returns(() => contractBalance);

            MockInternalExecutor.Setup(s =>
                                       s.Transfer(
                                           MockContractState.Object,
                                           Applicant,
                                           amountToTransfer))
            .Returns(TransferResult.Transferred(new object()));

            var result = contract.Approve(ApplicationId);

            Assert.True(result);

            MockPersistentState.Verify(x => x.SetString($"Status:{ApplicationId}", ApprovedStatus), Times.Once);
            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), new StatusLog {
                Id = ApplicationId, Applicant = Applicant, Status = ApprovedStatus
            }), Times.Once);
            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), new TransactionLog {
                From = ContractAddress, To = Applicant, Amount = amountToTransfer
            }), Times.Once);
        }
Exemple #5
0
        protected IOpdexMiningPool CreateNewMiningPool(ulong block = 10)
        {
            _mockContractState.Setup(x => x.Message).Returns(new Message(MiningPool1, Pool1, 0));

            SetupBalance(0);
            SetupBlock(block);

            SetupCall(StakingToken, 0, "get_MiningGovernance", null, TransferResult.Transferred(MiningGovernance));
            SetupCall(MiningGovernance, 0, "get_MiningDuration", null, TransferResult.Transferred(BlocksPerMonth));

            return(new OpdexMiningPool(_mockContractState.Object, StakingToken, Pool1));
        }
Exemple #6
0
        public void CreateContract_Throws_InvalidGovernanceAddress()
        {
            SetupBalance(0);
            SetupBlock(10);

            SetupCall(StakingToken, 0, "get_MiningGovernance", null, TransferResult.Transferred(Address.Zero));

            this.Invoking(p => p.BlankMiningPool())
            .Should()
            .Throw <SmartContractAssertException>()
            .WithMessage("OPDEX: INVALID_GOVERNANCE_ADDRESS");
        }
Exemple #7
0
        public void CreateContract_Throws_InvalidDurationAmount()
        {
            SetupBalance(0);
            SetupBlock(10);

            SetupCall(StakingToken, 0, "get_MiningGovernance", null, TransferResult.Transferred(MiningGovernance));
            SetupCall(MiningGovernance, 0, "get_MiningDuration", null, TransferResult.Transferred(0ul));

            this.Invoking(p => p.BlankMiningPool())
            .Should()
            .Throw <SmartContractAssertException>()
            .WithMessage("OPDEX: INVALID_DURATION_AMOUNT");
        }
        public void NotifyDistribution_Throws_InvalidMiningPool()
        {
            var pools = new[] { Pool1, Pool2, Pool3, Pool4 };
            var gov   = CreateNewOpdexMiningGovernance();

            SetupMessage(MiningGovernance, ODX);

            SetupCall(Pool1, 0, GetMiningPoolMethod, null, TransferResult.Transferred(Address.Zero));

            gov
            .Invoking(g => g.NotifyDistribution(pools[0], pools[1], pools[2], pools[3]))
            .Should()
            .Throw <SmartContractAssertException>()
            .WithMessage("OPDEX: INVALID_MINING_POOL");
        }
        public void Buy_Success_Remaining_Amount_IsZero_CloseOrder(ulong amountToBuy)
        {
            amountToBuy = DefaultAmount >= amountToBuy ? amountToBuy : DefaultAmount;

            var order = NewSimpleSellOrder(Seller, DefaultZeroValue, DefaultPrice, DefaultAmount);

            ulong orderCost = amountToBuy * DefaultPrice;
            ulong updatedContractBalance = order.Balance - orderCost;

            MockContractState.Setup(x => x.Message).Returns(new Message(ContractAddress, BuyerOne, orderCost));

            var amountInStratoshis = amountToBuy * 100_000_000;
            var expectedCallParams = new object[] { Seller, BuyerOne, amountInStratoshis };

            MockInternalExecutor.Setup(x =>
                                       x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0))
            .Returns(TransferResult.Transferred(true));

            MockInternalExecutor.Setup(x => x.Transfer(It.IsAny <ISmartContractState>(), It.IsAny <Address>(), It.IsAny <ulong>()))
            .Callback(() => MockContractState.Setup(x => x.GetBalance).Returns(() => updatedContractBalance));

            MockPersistentState.Setup(x => x.SetUInt64(nameof(Amount), DefaultAmount - amountToBuy))
            .Callback(() => MockPersistentState.Setup(x => x.GetUInt64(nameof(Amount))).Returns(DefaultAmount - amountToBuy));

            order.Buy(amountToBuy);

            MockInternalExecutor.Verify(x =>
                                        x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0), Times.Once);

            MockContractState.Verify(x => x.InternalTransactionExecutor
                                     .Transfer(It.IsAny <ISmartContractState>(), Seller, orderCost), Times.Once);

            // Only runs on the second test if there is a balance to transfer
            MockContractState.Verify(x => x.InternalTransactionExecutor
                                     .Transfer(It.IsAny <ISmartContractState>(), BuyerOne, order.Balance), Times.AtMostOnce());

            MockPersistentState.Verify(x => x.SetUInt64(nameof(Amount), 0), Times.Once);

            MockPersistentState.Verify(x => x.SetBool(nameof(IsActive), false), Times.Once);

            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), It.IsAny <Transaction>()), Times.Once);
        }
        public void AddFundToContract_Succeeds(ulong amount)
        {
            var contract = Newcontract(Owner, Owner, amount, StartTime, EndTime);

            MockInternalExecutor.Setup(s =>
                                       s.Transfer(
                                           MockContractState.Object,
                                           ContractAddress,
                                           amount))
            .Returns(TransferResult.Transferred(new object()));

            var result = contract.AddFundToContract();

            Assert.True(result);

            MockInternalExecutor.Verify(s => s.Transfer(MockContractState.Object, ContractAddress, amount), Times.Once);
            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), new TransactionLog {
                From = Owner, To = ContractAddress, Amount = amount
            }), Times.Once);
        }
        public void NotifyDistribution_SetStakingTokens_Success()
        {
            // Arrange
            const ulong block                    = 100;
            UInt256     expectedBalance          = 30_000_000_000_000_000; // 300 million
            UInt256     expectedMiningPoolReward = 625_000_000_000_000;    // 6,250,000 million
            var         pools                    = new[] { Pool1, Pool2, Pool3, Pool4 };
            var         gov = CreateNewOpdexMiningGovernance(block);

            var getBalanceParams = new object[] { MiningGovernance };

            SetupCall(ODX, 0ul, nameof(IOpdexMinedToken.GetBalance), getBalanceParams, TransferResult.Transferred(expectedBalance));

            SetupCall(Pool1, 0, GetMiningPoolMethod, null, TransferResult.Transferred(MiningPool1));
            SetupCall(Pool2, 0, GetMiningPoolMethod, null, TransferResult.Transferred(MiningPool2));
            SetupCall(Pool3, 0, GetMiningPoolMethod, null, TransferResult.Transferred(MiningPool3));
            SetupCall(Pool4, 0, GetMiningPoolMethod, null, TransferResult.Transferred(MiningPool4));

            SetupMessage(MiningGovernance, ODX);

            // Act
            gov.NotifyDistribution(pools[0], pools[1], pools[2], pools[3]);

            gov.MiningPoolReward.Should().Be(expectedMiningPoolReward);
            gov.MiningPoolsFunded.Should().Be(0);
            gov.Notified.Should().BeFalse();
            gov.Nominations.Length.Should().Be(pools.Length);
            gov.NominationPeriodEnd.Should().Be(block + BlocksPerMonth);
            foreach (var govNomination in gov.Nominations)
            {
                pools.ToList().Any(p => p == govNomination.StakingPool).Should().BeTrue();
            }

            VerifyCall(Pool1, 0, GetMiningPoolMethod, null, Times.Once);
            VerifyCall(Pool2, 0, GetMiningPoolMethod, null, Times.Once);
            VerifyCall(Pool3, 0, GetMiningPoolMethod, null, Times.Once);
            VerifyCall(Pool4, 0, GetMiningPoolMethod, null, Times.Once);

            VerifyCall(ODX, 0ul, nameof(IOpdexMinedToken.GetBalance), getBalanceParams, Times.Once);
        }
        public void BuyItem_Fails_If_Buyer_Balance_Insufficient()
        {
            var seller    = PartyA;
            var buyer     = PartyB;
            var itemPrice = 1UL;

            // Setup the expected state values.
            this.mockPersistentState.Setup(s => s.GetUInt64(nameof(ItemListing.ItemPrice))).Returns(itemPrice);
            this.mockPersistentState.Setup(s => s.GetAddress(nameof(ItemListing.Seller))).Returns(seller);
            this.mockPersistentState.Setup(s => s.GetAddress(nameof(ItemListing.ParentContract))).Returns(ParentContract);

            this.mockContractState.Setup(s => s.Message.Sender).Returns(ParentContract);
            var itemListing = new ItemListing(this.mockContractState.Object, "Test", itemPrice, seller, ParentContract, PartyA, PartyB);

            this.mockInternalExecutor
            .Setup(c => c.Call(
                       It.IsAny <ISmartContractState>(),
                       It.IsAny <Address>(),
                       It.IsAny <ulong>(),
                       nameof(Bazaar.HasBalance),
                       It.IsAny <object[]>(),
                       It.IsAny <ulong>()))
            .Returns(TransferResult.Transferred(false));

            this.mockContractState.Setup(s => s.Message.Sender).Returns(buyer);

            Assert.Throws <SmartContractAssertException>(() => itemListing.BuyItem());

            this.mockInternalExecutor
            .Verify(
                c => c.Call(
                    It.IsAny <ISmartContractState>(),
                    ParentContract,
                    0,
                    nameof(Bazaar.HasBalance),
                    It.Is <object[]>(o => (Address)o[0] == buyer && (ulong)o[1] == itemPrice),
                    0),
                Times.Once);
        }
        public void SendPing_Opponent_Finished_Success()
        {
            var player = this.NewPlayer();

            this.mockContractState.Setup(s => s.Message.Sender).Returns(PlayerAddress);
            this.mockPersistentState.Setup(s => s.GetUInt32(nameof(Player.State))).Returns((uint)Player.StateType.ReceivedPing);

            // Return true
            this.mockInternalExecutor.Setup(s =>
                                            s.Call(
                                                It.IsAny <ISmartContractState>(),
                                                It.IsAny <Address>(),
                                                It.IsAny <ulong>(),
                                                nameof(Player.IsFinished),
                                                It.IsAny <object[]>(),
                                                It.IsAny <ulong>()))
            .Returns(TransferResult.Transferred(true));

            player.SendPing();

            this.mockInternalExecutor.Verify(s => s.Call(this.mockContractState.Object, OpponentAddress, 0, nameof(Player.IsFinished), null, 0));
            this.mockPersistentState.Verify(s => s.SetUInt32(nameof(Player.State), (uint)Player.StateType.Finished), Times.Once);
        }
        public void Withdraw_Success()
        {
            CurrentBlock = EndBlock;
            var sender         = Registrant;
            var expectedStatus = FundedStatus;
            var airdrop        = NewAirdrop(sender, Owner, CurrentBlock, EndBlock, TotalSupply);

            // Setup sender as already registered
            MockPersistentState.Setup(x => x.GetUInt64(nameof(NumberOfRegistrants))).Returns(1);
            MockPersistentState.Setup(x => x.GetString($"Status:{sender}")).Returns(EnrolledStatus);

            // Mock contract call
            MockInternalExecutor.Setup(s =>
                                       s.Call(
                                           It.IsAny <ISmartContractState>(),
                                           It.IsAny <Address>(),
                                           It.IsAny <ulong>(),
                                           "TransferFrom",
                                           It.IsAny <object[]>(),
                                           It.IsAny <ulong>()))
            .Returns(TransferResult.Transferred(true));

            // Withdraw should succeed
            Assert.True(airdrop.Withdraw());

            // Verify the withdraw method made the call, set the new status, and logged the result
            var amountToDistribute = airdrop.GetAmountToDistribute();
            var transferFromParams = new object[] { Owner, Registrant, amountToDistribute };

            MockInternalExecutor.Verify(s => s
                                        .Call(MockContractState.Object, TokenContractAddress, amountToDistribute, "TransferFrom", transferFromParams, 0), Times.Once);
            MockPersistentState.Verify(x => x.SetString($"Status:{sender}", expectedStatus));
            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), new StatusLog {
                Registrant = sender, Status = expectedStatus
            }), Times.Once);
        }
Exemple #15
0
        private void StartMining(IOpdexMiningPool miningPool, Address miner, UInt256 amount)
        {
            SetupMessage(MiningPool1, miner);
            SetupCall(Pool1, 0, nameof(IOpdexPool.TransferFrom), new object[] { miner, MiningPool1, amount }, TransferResult.Transferred(true));

            var currentBalance      = miningPool.GetBalance(miner);
            var expectedTotalSupply = miningPool.TotalSupply + amount;

            miningPool.StartMining(amount);
            miningPool.GetBalance(miner).Should().Be(currentBalance + amount);
            miningPool.TotalSupply.Should().Be(expectedTotalSupply);

            VerifyCall(Pool1, 0, nameof(IOpdexPool.TransferFrom), new object[] { miner, MiningPool1, amount }, Times.Once);
            VerifyLog(new MineLog {
                Miner = miner, Amount = amount, TotalSupply = expectedTotalSupply, EventType = (byte)MineEventType.StartMining
            }, Times.Once);
        }
Exemple #16
0
        public void StopMining_Success(ulong currentBlock, ulong lastUpdateBlock, UInt256 totalSupply, UInt256 minerBalance,
                                       UInt256 minerWithdraw, UInt256 expectedReward)
        {
            const ulong periodStart  = 100;
            const ulong periodFinish = 200;
            UInt256     rewardRate   = 100_000_000;

            var expectedTotalSupply = totalSupply - minerWithdraw;

            State.SetUInt256(nameof(IOpdexMiningPool.RewardPerStakedTokenLast), UInt256.Zero);
            State.SetUInt256(nameof(IOpdexMiningPool.TotalSupply), totalSupply);
            State.SetUInt256(nameof(IOpdexMiningPool.RewardRate), rewardRate);
            State.SetUInt64(nameof(IOpdexMiningPool.LastUpdateBlock), lastUpdateBlock);
            State.SetUInt64(nameof(IOpdexMiningPool.MiningPeriodEndBlock), periodFinish);
            State.SetUInt256($"Balance:{Miner1}", minerBalance);

            var transferRewardParams = new object[] { Miner1, expectedReward };

            SetupCall(StakingToken, 0ul, nameof(IStandardToken256.TransferTo), transferRewardParams, TransferResult.Transferred(true));

            var transferStakingTokensParams = new object[] { Miner1, minerWithdraw };

            SetupCall(Pool1, 0ul, nameof(IStandardToken256.TransferTo), transferStakingTokensParams, TransferResult.Transferred(true));

            var miningPool = CreateNewMiningPool(periodStart);

            SetupBlock(currentBlock);
            SetupMessage(MiningPool1, Miner1);

            miningPool.StopMining(minerWithdraw);

            miningPool.GetStoredReward(Miner1).Should().Be(UInt256.Zero);
            miningPool.TotalSupply.Should().Be(expectedTotalSupply);
            miningPool.GetBalance(Miner1).Should().Be(minerBalance - minerWithdraw);
            miningPool.LastUpdateBlock.Should().Be(currentBlock);

            VerifyCall(Pool1, 0, nameof(IStandardToken256.TransferTo), transferStakingTokensParams, Times.Once);
            VerifyLog(new MineLog {
                Miner = Miner1, Amount = minerWithdraw, TotalSupply = expectedTotalSupply, EventType = (byte)MineEventType.StopMining
            }, Times.Once);

            if (expectedReward > 0)
            {
                VerifyCall(StakingToken, 0, nameof(IStandardToken256.TransferTo), transferRewardParams, Times.Once);
                VerifyLog(new CollectMiningRewardsLog {
                    Miner = Miner1, Amount = expectedReward
                }, Times.Once);
            }
            else
            {
                VerifyCall(StakingToken, 0, nameof(IStandardToken256.TransferTo), transferRewardParams, Times.Never);
                VerifyLog(new CollectMiningRewardsLog {
                    Miner = It.IsAny <Address>(), Amount = It.IsAny <UInt256>()
                }, Times.Never);
            }
        }
        public void Buy_Success_Until_Amount_IsGone()
        {
            var order = NewSimpleSellOrder(Seller, DefaultZeroValue, DefaultPrice, DefaultAmount);

            // First Seller
            ulong amountToBuy           = DefaultAmount - 5;
            ulong expectedUpdatedAmount = DefaultAmount - amountToBuy;
            ulong orderCost             = amountToBuy * DefaultPrice;

            MockContractState.Setup(x => x.Message).Returns(new Message(ContractAddress, BuyerOne, orderCost));

            var amountInStratoshis = amountToBuy * 100_000_000;
            var expectedCallParams = new object[] { Seller, BuyerOne, amountInStratoshis };

            MockInternalExecutor.Setup(x =>
                                       x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0))
            .Returns(TransferResult.Transferred(true));

            // Transfers CRS to seller, callback to update the contracts balance
            MockInternalExecutor.Setup(x => x.Transfer(It.IsAny <ISmartContractState>(), Seller, orderCost))
            .Callback(() => MockContractState.Setup(x => x.GetBalance).Returns(() => DefaultCostValue - orderCost));

            MockPersistentState.Setup(x => x.SetUInt64(nameof(Amount), expectedUpdatedAmount))
            .Callback(() => MockPersistentState.Setup(x => x.GetUInt64(nameof(Amount))).Returns(expectedUpdatedAmount));

            order.Buy(amountToBuy);

            MockInternalExecutor.Verify(x =>
                                        x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", expectedCallParams, 0), Times.Once);

            MockContractState.Verify(x => x.InternalTransactionExecutor
                                     .Transfer(It.IsAny <ISmartContractState>(), Seller, orderCost), Times.Once);

            MockPersistentState.Verify(x => x.SetUInt64(nameof(Amount), expectedUpdatedAmount));

            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), It.IsAny <Transaction>()), Times.Once);


            // Second Seller
            ulong secondAmountToBuy   = expectedUpdatedAmount;
            ulong secondUpdatedAmount = secondAmountToBuy - expectedUpdatedAmount;
            ulong secondOrderCost     = secondAmountToBuy * DefaultPrice;

            MockContractState.Setup(x => x.Message).Returns(new Message(ContractAddress, BuyerTwo, secondOrderCost));

            var secondAmountInStratoshis = secondAmountToBuy * 100_000_000;
            var secondExpectedCallParams = new object[] { Seller, BuyerTwo, secondAmountInStratoshis };

            MockInternalExecutor.Setup(x =>
                                       x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", secondExpectedCallParams, 0))
            .Returns(TransferResult.Transferred(true));

            MockPersistentState.Setup(x => x.SetUInt64(nameof(Amount), secondUpdatedAmount))
            .Callback(() => MockPersistentState.Setup(x => x.GetUInt64(nameof(Amount))).Returns(secondUpdatedAmount));

            order.Buy(secondAmountToBuy);

            MockInternalExecutor.Verify(x =>
                                        x.Call(It.IsAny <ISmartContractState>(), Token, 0, "TransferFrom", secondExpectedCallParams, 0), Times.Once);

            // Runs twice because in this case we're sending the same amount to the same seller (owner)
            MockContractState.Verify(x => x.InternalTransactionExecutor
                                     .Transfer(It.IsAny <ISmartContractState>(), Seller, secondOrderCost), Times.AtLeast(2));

            MockPersistentState.Verify(x => x.SetUInt64(nameof(Amount), secondUpdatedAmount));

            // Shouldn't have enough balance to continue, close contract
            MockPersistentState.Verify(x => x.SetBool(nameof(IsActive), false), Times.Once);

            MockContractLogger.Verify(x => x.Log(It.IsAny <ISmartContractState>(), It.IsAny <Transaction>()), Times.AtLeast(2));
        }
Exemple #18
0
        public void NotifyRewardAmount_Active_Success()
        {
            UInt256     rewardAmount  = 100_000;
            UInt256     balance       = 150_000;
            UInt256     rewardRate    = 1_000;
            UInt256     newRewardRate = 1_500;
            const ulong duration      = 100;
            const ulong startingBlock = 100;
            const ulong currentBlock  = 150;
            const ulong endBlock      = 200;

            var miningPool = CreateNewMiningPool(startingBlock);

            SetupBlock(currentBlock);
            SetupMessage(MiningPool1, MiningGovernance);

            State.SetUInt64(nameof(IOpdexMiningPool.MiningDuration), duration);
            State.SetAddress(nameof(IOpdexMiningPool.MinedToken), StakingToken);
            State.SetAddress(nameof(IOpdexMiningPool.MiningGovernance), MiningGovernance);
            State.SetUInt64(nameof(IOpdexMiningPool.MiningPeriodEndBlock), endBlock);
            State.SetUInt256(nameof(IOpdexMiningPool.RewardRate), rewardRate);

            var balanceParams = new object[] { MiningPool1 };

            SetupCall(StakingToken, 0ul, nameof(IStandardToken.GetBalance), balanceParams, TransferResult.Transferred(balance));

            miningPool.NotifyRewardAmount(rewardAmount);

            miningPool.RewardRate.Should().Be(newRewardRate);
            miningPool.LastUpdateBlock.Should().Be(currentBlock);
            miningPool.MiningPeriodEndBlock.Should().Be(currentBlock + duration);

            VerifyLog(new EnableMiningLog {
                Amount = rewardAmount, RewardRate = newRewardRate, MiningPeriodEndBlock = currentBlock + duration
            }, Times.Once);
        }
Exemple #19
0
        public void NotifyRewardAmount_NotActive_Success()
        {
            const ulong block    = 100;
            const ulong duration = 100;
            const ulong expectedMiningPeriodEndBlock = block + duration;
            UInt256     rewardAmount       = 100_000;
            UInt256     expectedRewardRate = 1_000;
            UInt256     rewardRate         = 1_000;

            var miningPool = CreateNewMiningPool();

            SetupBlock(block);
            SetupMessage(MiningPool1, MiningGovernance);

            State.SetUInt64(nameof(IOpdexMiningPool.MiningDuration), duration);
            State.SetAddress(nameof(IOpdexMiningPool.MinedToken), StakingToken);
            State.SetAddress(nameof(IOpdexMiningPool.MiningGovernance), MiningGovernance);

            var balanceParams = new object[] { MiningPool1 };

            SetupCall(StakingToken, 0ul, nameof(IStandardToken.GetBalance), balanceParams, TransferResult.Transferred(rewardAmount));

            miningPool.NotifyRewardAmount(rewardAmount);

            miningPool.RewardRate.Should().Be(expectedRewardRate);
            miningPool.MiningPeriodEndBlock.Should().Be(block + duration);

            VerifyLog(new EnableMiningLog {
                Amount = rewardAmount, RewardRate = rewardRate, MiningPeriodEndBlock = expectedMiningPeriodEndBlock
            }, Times.Once);
        }
Exemple #20
0
        public void WithdrawTokens_Called_By_Owner_After_Sale_Is_Closed_Success()
        {
            var amount = 0ul;

            this.mTransactionExecutor.Setup(m => m.Create <StandardToken>(this.mContractState.Object, 0, new object[] { this.totalSupply, this.name, this.symbol }, It.IsAny <ulong>())).Returns(this.createSuccess);

            var(contract, _) = this.Create(TokenType.StandardToken);
            this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.owner, amount));
            this.mBlock.Setup(m => m.Number).Returns(5);
            this.persistentState.SetUInt64(nameof(contract.TokenBalance), 100);
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.tokenContract, 0, nameof(StandardToken.TransferTo), new object[] { this.owner, 100ul }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));

            var success = contract.WithdrawTokens();

            Assert.True(success);
            Assert.Equal(0ul, this.persistentState.GetUInt64(nameof(contract.TokenBalance)));
            this.mTransactionExecutor.Verify(m => m.Call(this.mContractState.Object, this.tokenContract, 0, nameof(StandardToken.TransferTo), new object[] { this.owner, 100ul }, 0));
        }
        public void BuyItem_Succeeds()
        {
            var seller    = PartyA;
            var buyer     = PartyB;
            var itemPrice = 1UL;

            // Setup the expected state values.
            this.mockPersistentState.Setup(s => s.GetUInt64(nameof(ItemListing.ItemPrice))).Returns(itemPrice);
            this.mockPersistentState.Setup(s => s.GetAddress(nameof(ItemListing.Seller))).Returns(seller);
            this.mockPersistentState.Setup(s => s.GetAddress(nameof(ItemListing.ParentContract))).Returns(ParentContract);

            this.mockContractState.Setup(s => s.Message.Sender).Returns(ParentContract);
            var itemListing = new ItemListing(this.mockContractState.Object, "Test", itemPrice, seller, ParentContract, PartyA, PartyB);

            // HasBalance returns true.
            this.mockInternalExecutor
            .Setup(c => c.Call(
                       It.IsAny <ISmartContractState>(),
                       It.IsAny <Address>(),
                       It.IsAny <ulong>(),
                       nameof(Bazaar.HasBalance),
                       It.IsAny <object[]>(),
                       It.IsAny <ulong>()))
            .Returns(TransferResult.Transferred(true));

            // UpdateBalance is successful.
            this.mockInternalExecutor
            .Setup(c => c.Call(
                       It.IsAny <ISmartContractState>(),
                       It.IsAny <Address>(),
                       It.IsAny <ulong>(),
                       nameof(Bazaar.UpdateBalance),
                       It.IsAny <object[]>(),
                       It.IsAny <ulong>()))
            .Returns(TransferResult.Empty());

            this.mockContractState.Setup(s => s.Message.Sender).Returns(buyer);

            itemListing.BuyItem();

            this.mockInternalExecutor
            .Verify(
                c => c.Call(
                    It.IsAny <ISmartContractState>(),
                    ParentContract,
                    0,
                    nameof(Bazaar.HasBalance),
                    It.Is <object[]>(o => (Address)o[0] == buyer && (ulong)o[1] == itemPrice),
                    0),
                Times.Once);

            this.mockInternalExecutor
            .Verify(
                c => c.Call(
                    It.IsAny <ISmartContractState>(),
                    ParentContract,
                    0,
                    nameof(Bazaar.UpdateBalance),
                    It.Is <object[]>(o => (Address)o[0] == seller && (Address)o[1] == buyer && (ulong)o[2] == itemPrice),
                    0),
                Times.Once);

            this.mockPersistentState.Verify(s => s.SetUInt32(nameof(Bazaar.State), (uint)ItemListing.StateType.ItemSold));
        }
Exemple #22
0
        public void Invest_Fails_If_TokenBalance_Is_Zero()
        {
            var amount = 1 * Satoshis;

            this.mTransactionExecutor.Setup(m => m.Create <StandardToken>(this.mContractState.Object, 0, new object[] { this.totalSupply, this.name, this.symbol }, It.IsAny <ulong>())).Returns(this.createSuccess);
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.kycContract, 0, "GetClaim", new object[] { this.investor, 3 /*shufti kyc*/ }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));

            var(contract, _) = this.Create(TokenType.StandardToken);
            this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.investor, amount));
            this.persistentState.SetUInt64(nameof(ICOContract.TokenBalance), 0);

            Assert.Throws <SmartContractAssertException>(() => contract.Invest());
        }
Exemple #23
0
        public void Invest_Fails_If_GetClaim_Call_Returns_Null()
        {
            var amount = 10ul;

            this.mTransactionExecutor.Setup(m => m.Create <StandardToken>(this.mContractState.Object, 0, new object[] { this.totalSupply, this.name, this.symbol }, It.IsAny <ulong>())).Returns(this.createSuccess);
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.mapperContract, 0, "GetSecondaryAddress", new object[] { this.investor }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(this.identity));
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.kycContract, 0, "GetClaim", new object[] { this.identity, 3 /*shufti kyc*/ }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(null));
            var(contract, _) = this.Create(TokenType.StandardToken);
            this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.investor, amount));

            Assert.Throws <SmartContractAssertException>(() => contract.Invest());
        }
Exemple #24
0
        public void Invest_Refunds_Oversold_Tokens()
        {
            this.totalSupply = 60;
            var amount = 190 * Satoshis;

            this.mTransactionExecutor.Setup(m => m.Create <StandardToken>(this.mContractState.Object, 0, new object[] { this.totalSupply, this.name, this.symbol }, It.IsAny <ulong>())).Returns(this.createSuccess);

            var(contract, _) = this.Create(TokenType.StandardToken);

            this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.investor, amount));
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.tokenContract, 0, nameof(StandardToken.TransferTo), new object[] { this.investor, this.totalSupply }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.mapperContract, 0, "GetSecondaryAddress", new object[] { this.investor }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(this.identity));
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.kycContract, 0, "GetClaim", new object[] { this.identity, 3 /*shufti kyc*/ }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));

            Assert.True(contract.Invest());

            Assert.Equal(0ul, contract.TokenBalance); // All tokens are sold
            this.mTransactionExecutor.Verify(s => s.Transfer(this.mContractState.Object, this.investor, 10 * Satoshis), Times.Once);
        }
Exemple #25
0
        public void Invest_CalledForNonFungibleToken_Success()
        {
            var amount      = 15 * Satoshis;
            var totalSupply = ulong.MaxValue;

            this.mTransactionExecutor.Setup(m => m.Create <NonFungibleToken>(this.mContractState.Object, 0, new object[] { this.name, this.symbol }, It.IsAny <ulong>())).Returns(this.createSuccess);

            var(contract, _) = this.Create(TokenType.NonFungibleToken);

            this.mContractState.Setup(m => m.Message).Returns(new Message(this.contract, this.investor, amount));

            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.tokenContract, 0, nameof(NonFungibleToken.MintAll), new object[] { this.investor, 5ul }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.mapperContract, 0, "GetSecondaryAddress", new object[] { this.investor }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(this.identity));
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.kycContract, 0, "GetClaim", new object[] { this.identity, 3 /*shufti kyc*/ }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));

            Assert.True(contract.Invest());

            Assert.Equal(totalSupply - 5ul, contract.TokenBalance);
            this.mTransactionExecutor.Verify(s => s.Transfer(It.IsAny <ISmartContractState>(), It.IsAny <Address>(), It.IsAny <ulong>()), Times.Never);

            this.mBlock.Setup(s => s.Number).Returns(4);
            this.mTransactionExecutor.Setup(m => m.Call(this.mContractState.Object, this.tokenContract, 0, nameof(NonFungibleToken.MintAll), new object[] { this.investor, 3ul }, It.IsAny <ulong>())).Returns(TransferResult.Transferred(true));

            Assert.True(contract.Invest());

            Assert.Equal(totalSupply - 8ul, contract.TokenBalance);
            this.mTransactionExecutor.Verify(s => s.Transfer(It.IsAny <ISmartContractState>(), It.IsAny <Address>(), It.IsAny <ulong>()), Times.Never);
        }
Exemple #26
0
        private void StopMining(IOpdexMiningPool miningPool, Address miner, UInt256 amount, UInt256 rewards)
        {
            SetupMessage(MiningPool1, miner);
            SetupCall(Pool1, 0, nameof(IOpdexPool.TransferTo), new object[] { miner, amount }, TransferResult.Transferred(true));
            SetupCall(StakingToken, 0, nameof(IOpdexPool.TransferTo), new object[] { miner, rewards }, TransferResult.Transferred(true));

            var currentBalance      = miningPool.GetBalance(miner);
            var expectedTotalSupply = miningPool.TotalSupply - amount;

            miningPool.StopMining(amount);
            miningPool.GetBalance(miner).Should().Be(currentBalance - amount);
            miningPool.GetMiningRewards(miner).Should().Be(UInt256.Zero);
            miningPool.TotalSupply.Should().Be(expectedTotalSupply);

            VerifyCall(Pool1, 0, nameof(IOpdexPool.TransferTo), new object[] { miner, amount }, Times.AtLeastOnce);
            VerifyCall(StakingToken, 0, nameof(IOpdexPool.TransferTo), new object[] { miner, rewards }, Times.AtLeastOnce);
            VerifyLog(new CollectMiningRewardsLog {
                Miner = miner, Amount = rewards
            }, Times.AtLeastOnce);
            VerifyLog(new MineLog {
                Miner = miner, Amount = amount, TotalSupply = expectedTotalSupply, EventType = (byte)MineEventType.StopMining
            }, Times.AtLeastOnce);
        }
Exemple #27
0
        public void NotifyRewardAmount_Throws_InvalidBalance()
        {
            const ulong duration = 100;

            var miningPool = CreateNewMiningPool();

            SetupMessage(MiningPool1, MiningGovernance);

            State.SetUInt64(nameof(IOpdexMiningPool.MiningDuration), duration);
            State.SetAddress(nameof(IOpdexMiningPool.MinedToken), StakingToken);
            State.SetAddress(nameof(IOpdexMiningPool.MiningGovernance), MiningGovernance);

            var balanceParams = new object[] { MiningPool1 };

            SetupCall(StakingToken, 0ul, nameof(IStandardToken.GetBalance), balanceParams, TransferResult.Transferred(UInt256.Zero));

            miningPool
            .Invoking(m => m.NotifyRewardAmount(100_000))
            .Should()
            .Throw <SmartContractAssertException>()
            .WithMessage("OPDEX: INVALID_BALANCE");
        }
Exemple #28
0
        public void NotifyRewardAmount_Throws_RewardTooHigh()
        {
            const ulong duration = 100;
            UInt256     balance  = 1;

            var miningPool = CreateNewMiningPool();

            SetupMessage(MiningPool1, MiningGovernance);

            State.SetUInt64(nameof(IOpdexMiningPool.MiningDuration), duration);
            State.SetAddress(nameof(IOpdexMiningPool.MinedToken), StakingToken);
            State.SetAddress(nameof(IOpdexMiningPool.MiningGovernance), MiningGovernance);

            var balanceParams = new object[] { MiningPool1 };

            SetupCall(StakingToken, 0ul, nameof(IStandardToken.GetBalance), balanceParams, TransferResult.Transferred(balance));

            miningPool
            .Invoking(m => m.NotifyRewardAmount(UInt256.MaxValue))
            .Should()
            .Throw <SmartContractAssertException>()
            .WithMessage("OPDEX: PROVIDED_REWARD_TOO_HIGH");
        }
Exemple #29
0
        public void CollectMarketFees_Success_TransferFees()
        {
            UInt256 amount = 250;

            var market = CreateNewOpdexStandardMarket(marketFeeEnabled: true);

            State.SetAddress($"{MarketStateKeys.Pool}:{Token}", Pool);

            var transferParams = new object[] { Owner, amount };

            SetupCall(Pool, 0, nameof(IOpdexLiquidityPool.TransferTo), transferParams, TransferResult.Transferred(true));

            SetupMessage(StandardMarket, Owner);

            market.CollectMarketFees(Token, amount);

            VerifyCall(Pool, 0, nameof(IOpdexLiquidityPool.TransferTo), transferParams, Times.Once);
        }
Exemple #30
0
        private void CollectMiningRewards(IOpdexMiningPool miningPool, Address miner, UInt256 rewards)
        {
            SetupMessage(MiningPool1, miner);
            SetupCall(StakingToken, 0, nameof(IOpdexPool.TransferTo), new object[] { miner, rewards }, TransferResult.Transferred(true));

            miningPool.CollectMiningRewards();
            miningPool.GetStoredReward(miner).Should().Be(UInt256.Zero);

            VerifyCall(StakingToken, 0, nameof(IOpdexPool.TransferTo), new object[] { miner, rewards }, Times.AtLeastOnce);
            VerifyLog(new CollectMiningRewardsLog {
                Miner = miner, Amount = rewards
            }, Times.AtLeastOnce);
        }