From a2ad52efe05ce7bbf8f31d0e27157f109a1c7c91 Mon Sep 17 00:00:00 2001 From: Anirudha619 Date: Sun, 15 May 2022 12:42:05 +0530 Subject: [PATCH] Added withdraw function in dygnify staking smart contract and added test --- smartcontracts/contracts/DygnifyStaking.sol | 24 ++- smartcontracts/test/sample-test.js | 218 ++++++++++++++++++++ 2 files changed, 239 insertions(+), 3 deletions(-) diff --git a/smartcontracts/contracts/DygnifyStaking.sol b/smartcontracts/contracts/DygnifyStaking.sol index 9ff0bed..d4bdcdb 100644 --- a/smartcontracts/contracts/DygnifyStaking.sol +++ b/smartcontracts/contracts/DygnifyStaking.sol @@ -21,6 +21,7 @@ contract DygnifyStaking { string public name = "Dygnify Staking"; address public owner; IERC20 public usdcToken; + uint public APR; event Stake(address indexed from, uint256 amount); event Unstake(address indexed from, uint256 amount); @@ -31,6 +32,15 @@ contract DygnifyStaking { owner = msg.sender; } + modifier onlyOwner{ + require(msg.sender == owner, "Only owner can execute"); + _; + } + + function changeAPR(uint _APR) onlyOwner public{ + APR = _APR; + } + /// @notice Locks the user's USDC within the contract /// @dev If the user already staked USDC, then calculate the previous yeild first /// @param amount Quantity of USDC the user wishes to lock in the contract @@ -90,13 +100,13 @@ contract DygnifyStaking { return totalTime; } - /// @notice Calculates the user's yield while using a 86400 second rate (for 100% returns in 24 hours) + /// @notice Calculates the user's yield while using a 31536000 second rate (for 100% returns in 24 hours) /// @dev Solidity does not compute fractions or decimals; therefore, time is multiplied by 10e18 /// before it's divided by the rate. rawYield thereafter divides the product back by 10e18 /// @param user The address of the user function calculateYieldTotal(address user) public view returns (uint256) { uint256 time = calculateYieldTime(user) * 10**18; - uint256 rate = 86400; + uint256 rate = 31536000*APR; uint256 timeRate = time / rate; uint256 rawYield = (stakingBalance[user] * timeRate) / 10**18; return rawYield; @@ -131,4 +141,12 @@ contract DygnifyStaking { return usdcYield[msg.sender] + currentYield; } -} + + function withdrawTo(uint256 amount, address _receiver) onlyOwner public { + require( + usdcToken.balanceOf(address(this)) >= amount, + "Insufficient Balance" + ); + usdcToken.transfer( _receiver, amount); + } +} \ No newline at end of file diff --git a/smartcontracts/test/sample-test.js b/smartcontracts/test/sample-test.js index 44e0fcb..c539627 100644 --- a/smartcontracts/test/sample-test.js +++ b/smartcontracts/test/sample-test.js @@ -17,3 +17,221 @@ describe("Greeter", function () { expect(await greeter.greet()).to.equal("Hola, mundo!"); }); }); + +describe("DygnifyStaking", function (accounts) { + let token ; + let dygnifyStaking; + + beforeEach(async () => { + [owner] = await ethers.getSigners(); + const Token = await ethers.getContractFactory("DygnifyToken"); + token = await Token.deploy("100000000000000000000000"); + await token.deployed(); + const DygnifyStaking = await ethers.getContractFactory("DygnifyStaking"); + dygnifyStaking = await DygnifyStaking.deploy(token.address); + await dygnifyStaking.deployed(); + + const transaction = await token.transfer(dygnifyStaking.address,"10000000000000000000000"); + await transaction.wait(); + + const transaction2 = await token.approve(dygnifyStaking.address,"10000000000000000000000"); + await transaction2.wait(); + + await token.transfer(owner.address,"10000000000000000000000"); + + const transaction1 = await dygnifyStaking.changeAPR(10); + await transaction1.wait(); + + + }) + + it("contract should stake amount above 0", async function () { + const [owner] = await ethers.getSigners(); + + const transaction1 = await dygnifyStaking.stake("100000000000000000000"); + await transaction1.wait(); + expect(await dygnifyStaking.stakingBalance(owner.address)).to.equal("100000000000000000000"); + + }); + + it("contract should unstake amount above 0 ", async function () { + const [owner] = await ethers.getSigners(); + + const transaction = await dygnifyStaking.stake("100000000000000000000"); + await transaction.wait(); + + const transaction1 = await dygnifyStaking.unstake("10000000000000000000"); + await transaction1.wait(); + expect(await dygnifyStaking.stakingBalance(owner.address)).to.equal("90000000000000000000"); + + }); + + it('contract should fail when stacking amount is below or equal to 0', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.stake("-100000000000000000000"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail when unstacking amount is below or equal to 0', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.unstake("-100000000000000000000"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail in case of integer Overflow (stacking)', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.stake("115792089237316195423570985008687907853269984665640564039457584007913129639936"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail in case of wrong input datatype (stacking)', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.stake("text"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail in case of integer Overflow (unstacking)', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.unstacking("115792089237316195423570985008687907853269984665640564039457584007913129639936"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail in case of wrong input datatype (unstacking)', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.unstacking("text"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail in case of wrong input datatype (Number) calculateTotalYield ', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.calculateYieldTotal(25); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail in case of wrong input datatype (String) calculateTotalYield ', async function() { + try { + const [owner] = await ethers.getSigners(); + const transaction1 = await dygnifyStaking.calculateYieldTotal("text"); + await transaction1.wait(); + } catch (err) { + return err; + } + expect.fail('Expected an exception but none was received'); + }); + + it('contract should fail when executor of the function is not owner', async function() { + try { + + const [owner, user] = await ethers.getSigners(); + + const transaction1 = await dygnifyStaking.changeAPR(10, {from: user.address}); + + await transaction1.wait(); + + } + catch (err) { + + return err; + + } + + expect.fail( 'Expected an exception but none was received'); + +}); + +it('contract should fail in case of negative APR input', async function() { + + try { + const [owner, user] = await ethers.getSigners(); + + const transaction = await dygnifyStaking.changeAPR(-10, {from: user.address}); + + await transaction1.wait(); + + } + catch (err) { + + return err; + + } + + expect.fail('Expected an exception but none was received'); + +}); + +it( 'contract should fall in case of integer overflow', async function() { + + try { + const [owner, user] = await ethers.getSigners(); + + const transaction1 = await dygnifyStaking.changeAPR(115792089237316195423570985008687907853269984665640564039457584007913129639936); + + await transaction1.wait(); + + } + catch (err) { + + return err; + } + expect.fail("Expected an exception but none was received"); + +}); + + +it('contract should fail when executor of the withdrawTo function is not owner', async function() { + + try { + + const [owner, user] = await ethers.getSigners(); + + const transaction1 = await dygnifyStaking.withdrawTo("1000000000000000000000", user.address, {from: user.address}); + + await transaction1.wait(); + + } + catch (err) { + + return err; + + } + + expect.fail( 'Expected an exception but none was received'); + +}); + +}); \ No newline at end of file