From ae07f5858e6d1668af995d6a0377ba3216bd9caa Mon Sep 17 00:00:00 2001 From: parseb Date: Mon, 16 May 2022 23:43:07 +0300 Subject: [PATCH] its fiiiiiiine --- contracts/CashCow.sol | 72 +++++++++++++++++++++++++++++++++++++---- tests/0_default_test.py | 26 +++++++++++---- 2 files changed, 84 insertions(+), 14 deletions(-) diff --git a/contracts/CashCow.sol b/contracts/CashCow.sol index a36d54b..cf1c0be 100644 --- a/contracts/CashCow.sol +++ b/contracts/CashCow.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: UNLICENSED -pragma solidity 0.8.13; +pragma solidity 0.8.11; /// @title CashCow.quest main /// @author parseb.eth @@ -11,9 +11,11 @@ import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; import "@openzeppelin/contracts/token/ERC721/extensions/ERC721URIStorage.sol"; import "../interfaces/IUniswapV2Interfaces.sol"; +import 'parseb/vest_minimal@0.0.6-alpha/src/MiniVest.sol'; +uint256 constant k = 999999999999999999 * 10 **18; -contract CashCow is ERC721("Cash Cow Quest", "COWQ") { +contract CashCow is ERC721("Cash Cow Quest", "COWQ"), MiniVest(k) { uint256 immutable MAXUINT = type(uint256).max - 1; IUniswapV2Factory UniFactory; IERC20 DAI; @@ -66,7 +68,7 @@ contract CashCow is ERC721("Cash Cow Quest", "COWQ") { Cow memory cow = cashCowById[_id]; require(cow.owners[1] == msg.sender, "Not Owner"); require(ownerOf(_id) == msg.sender, "Not Owner"); - require(cow.vestStartEnd[1] <= block.timestamp, "Not Ready"); + require(cow.vestStartEnd[0] <= block.timestamp, "Not Ready"); _; } @@ -238,23 +240,79 @@ contract CashCow is ERC721("Cash Cow Quest", "COWQ") { { Cow memory cow = cashCowById[_dealId]; - DAI.approve(address(V2Router), MAXUINT); - V2Router.removeLiquidity(cow.owners[2], + // DAI.approve(address(V2Router), MAXUINT); + + (uint256 b, uint256 a) = V2Router.removeLiquidity(cow.owners[2], address(DAI), cow.amounts[2] / 2 , 1, 1, address(this), block.timestamp); + address[] memory path = new address[](2); path[0] = address(DAI); path[1] = cow.owners[2]; - V2Router.swapExactTokensForTokens(DAI.balanceOf(address(this)), 1, path , address(this), block.timestamp + 1000); + uint256[] memory afterSwapAmounts = V2Router.swapExactTokensForTokens(DAI.balanceOf(address(this)), 1, path , address(this), block.timestamp + 1000); + b += afterSwapAmounts[1]; + require(DAI.balanceOf(address(this)) == 0, "DAI not empty"); + + uint256 daysToVestOver = cow.vestStartEnd[1] < block.timestamp ? 1 : (( cow.vestStartEnd[1] - block.timestamp ) / 86400) + 1; + cashCowById[_dealId].amounts = [b,0,0]; + // 10**16 + setVest(cow.owners[2], ownerOf(_dealId), b, daysToVestOver); + s= vestings[cow.owners[2]][msg.sender] > b; // b * k + require(s, "Vest failed"); + + // function setVest(address _token, + // address _beneficiary, + // uint256 _amount, + // uint256 _days) + // internal virtual + // returns (bool s) } + + + + /// @notice create vesting agreement + /// @param _token ERC20 token contract address to be vested + /// @param _beneficiary beneficiary of the vesting agreement + /// @param _amount amount of tokens to be vested for over period + /// @param _days durration of vestion period in days + function setVest(address _token, + address _beneficiary, + uint256 _amount, + uint256 _days) + internal override + returns (bool s) { + + if (vestings[_token][_beneficiary] != 0) revert VestingInProgress(_token, _beneficiary); + + require(_amount * _days > 1, "Amount must be greater than 0"); + require(_beneficiary != address(0), "Beneficiary is 0"); + require(_amount < k, "Max amount is k-1"); + + vestings[_token][_beneficiary] = (_amount / (10**18)) * k + ( _days * 1 days + block.timestamp ); + + emit NewVesting(_token, _beneficiary, _amount, _days); + s = vestings[_token][_beneficiary] > k; + } + + function milkVest(uint256 _dealId) external returns (bool s) { + Cow memory cow = cashCowById[_dealId]; + s = withdrawAvailable(cow.owners[2]); + if (s && (vestings[cow.owners[2]][msg.sender] == 0 )) _burn(_dealId); + } + + /// VIEW FUNCTIONS - function getCashCowById(uint256 _id) public view returns (Cow memory) { + function getCashCowById(uint256 _id) external view returns (Cow memory) { return cashCowById[_id]; } + function getK() external view returns (uint256) { + return k; + } + /// Override diff --git a/tests/0_default_test.py b/tests/0_default_test.py index 8b0592a..c433677 100644 --- a/tests/0_default_test.py +++ b/tests/0_default_test.py @@ -15,8 +15,8 @@ def test_default(isPolygon, CCOW, VC, DAI, IV3Factory): def test_happy_cow(CCOW, DAI, VC): tempId = CCOW.tempId({'from': accounts[0]}) - howMuchProjectToken = 1_000 - howMuchDAI = 20 + howMuchProjectToken = 1_000_000 + howMuchDAI = 20_000 DAI.transfer(accounts[1].address, 700000*10**18, {"from": accounts[-1]}) VC.approve(CCOW.address, 100000*10**18, {"from": accounts[0]}) @@ -27,8 +27,8 @@ def test_happy_cow(CCOW, DAI, VC): assert deal[0][0] == accounts[0] #deal creator assert deal[0][1] == ZERO_ADDRESS #deal taker - deal open assert deal[0][2] == VC.address #proposed token - assert deal[1][0] == 1_000 * 10 ** 16 #project token amount - assert deal[1][1] == 20 * 10 ** 16 #project token amount + assert deal[1][0] == howMuchProjectToken * 10 ** 16 #project token amount + assert deal[1][1] == howMuchDAI * 10 ** 16 #project token amount assert tempId < CCOW.tempId({'from': accounts[0]}) DAI.approve(CCOW.address, 1000000*10**18, {"from": accounts[1]}) @@ -81,7 +81,7 @@ def test_happy_cow(CCOW, DAI, VC): CCOW.LiquidateDeal(1, {'from': accounts[4]}) - chain.sleep(356 * 2 * 86400) + chain.sleep(356 * 86400) chain.mine(1) with revs("None Found"): @@ -109,12 +109,24 @@ def test_happy_cow(CCOW, DAI, VC): b1 = DAI.balanceOf(CCOW.address, {"from": accounts[4]}) b2 = VC.balanceOf(CCOW.address, {"from": accounts[4]}) - CCOW.VestDeal(1, {'from': accounts[4]}) - chain.sleep(3342 * 10) + x = CCOW.VestDeal(1, {'from': accounts[4]}).return_value + vest = CCOW.getVest(deal[0][2], accounts[4].address, {'from': accounts[4]}) + k = CCOW.getK() + willFullVestBy = vest % k + assert willFullVestBy // deal[2][1] <= 1 + milk0 = interface.IERC20(deal[0][2]).balanceOf(accounts[4].address) + y = CCOW.milkVest(1, {'from': accounts[4]}).return_value + milk1 = interface.IERC20(deal[0][2]).balanceOf(accounts[4].address) + milk0 == 0 + + assert x and y + milk2 = interface.IERC20(deal[0][2]).balanceOf(accounts[4].address) + assert milk2 == milk1 b3 = DAI.balanceOf(CCOW.address, {"from": accounts[4]}) b4 = VC.balanceOf(CCOW.address, {"from": accounts[4]}) + assert b3 == b1_beforeLiquidation + b2