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); }
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)); }
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"); }
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); }
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); }
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)); }
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); }
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); }
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)); }
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()); }
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()); }
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); }
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); }
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); }
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"); }
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"); }
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); }
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); }