diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..3547cd4 --- /dev/null +++ b/.env.example @@ -0,0 +1,2 @@ +MNEMONIC="Mnemonic Phrase" +INFURA_API_KEY=INFURA_API_KEY \ No newline at end of file diff --git a/contracts/3rdDeFiInterfaces/CEthInterface.sol b/contracts/3rdDeFiInterfaces/CEthInterface.sol deleted file mode 100644 index 110ca89..0000000 --- a/contracts/3rdDeFiInterfaces/CEthInterface.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -interface CEthInterface { - - function mint() external payable; - - function redeem(uint256 redeemTokens) external returns (uint256); - - function redeemUnderlying(uint256 redeemAmount) external returns (uint256); - - function borrow(uint256 borrowAmount) external returns (uint256); - - function repayBorrow(uint256 repayAmount) external returns (uint256); - - function exchangeRateStored() external view returns (uint256); - - function balanceOf(address _owner) external view returns (uint256); - - function underlying() external view returns (address); - - function claimComp(address holder) external; -} diff --git a/contracts/FairLaunch.sol b/contracts/FairLaunch.sol deleted file mode 100644 index 11bc314..0000000 --- a/contracts/FairLaunch.sol +++ /dev/null @@ -1,165 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; -import "./interfaces/ForgeInterface.sol"; -import "./Ownable.sol"; -import "./Referral.sol"; -import "./Saver.sol"; - -contract FairLaunch is Ownable, ReentrancyGuard{ - using SafeERC20 for IERC20; - using SafeMath for uint256; - - event Deposit( uint256 blockNumber, uint256 blockTime, address account, uint256 amount, uint256 accAmount,uint256 totalAmount, uint256 cap, bytes12 referralCode); - event Withdraw( uint256 blockNumber, uint256 blockTime, address account, uint256 amount, uint256 accAmount,uint256 totalAmount, uint256 cap, bytes12 referralCode); - - uint256 constant private OPEN_TIMESTAMP = 1628553600; - uint256 constant private CLOSED_TIMESTAMP = 1630022400; - - Referral private _referral; - IERC20 private _token; - ForgeInterface private _forge; - - uint256 private _count; - uint256 private _decimals; - uint256 private _cap; - uint256 private _totalAmount; - uint256 private _rewardCap; - string private _name; - - mapping( address=>bool ) _entered; - mapping( address=>uint256 ) _indexes; - - uint256 [] private _caps; - uint256 [] private _capUpdateTimestamps; - - function initialize( - address storage_, - address forge_, - address token_, - address referral_, - uint8 decimals_, - string memory name_ - ) public initializer { - - Ownable.initialize( storage_ ); - - _forge = ForgeInterface(forge_); - _token = IERC20(token_); - _referral = Referral(referral_); - _decimals = decimals_; - _totalAmount = 0; - _count = 0; - _rewardCap = 70000 * 10**18; - _name = name_; - - _token.safeApprove(forge_, 2**256 - 1); - } - - function enter( uint256 amount ) public returns(bool){ - return enter(amount, 0x0); - } - - function enter( uint256 amount, bytes12 ref ) public nonReentrant returns(bool) { - require( block.timestamp > OPEN_TIMESTAMP, "FL : Not Opened yet"); - require( _totalAmount + amount <= _cap, "FL : Amount Overflow" ); - require( _token.allowance(msg.sender, address(this)) >= amount, "FL : Allowance Error"); - - ( bool entered, uint index ) = isEntered( msg.sender ); - - address issuer = _referral.validate( ref ); - _totalAmount = _totalAmount.add(amount); - _token.safeTransferFrom(msg.sender, address(this), amount); - - if( entered ){ - _forge.addDeposit(index, amount); - }else{ - _indexes[msg.sender] = _forge.countByAccount(address(this)); - _entered[msg.sender] = true; - if( ref == 0x0 ){ - _count += 1; - _forge.craftingSaver(amount, CLOSED_TIMESTAMP, 1, 1); - }else{ - require( issuer != address(0x0), "FL : Not Registry Ref Code"); - _count += 1; - _forge.craftingSaver(amount, CLOSED_TIMESTAMP, 1, 1, ref); - } - } - ( entered, index ) = isEntered( msg.sender ); - emit Deposit(block.number, block.timestamp, msg.sender, amount, _forge.saver(address(this), index).accAmount, _totalAmount, _cap, _forge.saver(address(this), index).ref); - - return true; - } - - function exit() public nonReentrant returns(bool) { - require(_entered[msg.sender], "FL : Not Entering"); - uint index = _indexes[msg.sender]; - - _entered[msg.sender] = false; - _totalAmount = _totalAmount.sub(_forge.saver(address(this), index).accAmount); - _count -= 1; - - uint beforeBalanceOf = _token.balanceOf(address(this)); - _forge.terminateSaver(index); - uint afterBalanceOf = _token.balanceOf(address(this)); - uint repayable = afterBalanceOf.sub(beforeBalanceOf); - _token.safeTransfer(msg.sender, repayable); - - emit Withdraw(block.number, block.timestamp, msg.sender, repayable, 0, _totalAmount, _cap, _forge.saver(address(this), index).ref); - - return true; - } - - function isEntered( address account ) public view returns(bool, uint256){ - return ( _entered[account], _indexes[account] ); - } - - function setCap( uint256 cap_ ) public OnlyAdmin returns(bool){ - _cap = cap_; - _caps.push(cap_); - _capUpdateTimestamps.push(block.timestamp); - return true; - } - - function cap() public view returns(uint256){ - return _cap; - } - - function rewardCap() public view returns(uint256){ - return _rewardCap; - } - - function count() public view returns(uint256){ - return _count; - } - - function totalAmount() public view returns(uint256){ - return _totalAmount; - } - - function decimals() public view returns(uint256){ - return _decimals; - } - - function name() public view returns(string memory){ - return _name; - } - - function caps() public view returns(uint256 [] memory, uint256 [] memory){ - return ( _caps, _capUpdateTimestamps ); - } - - function withdrawable( address account ) public view returns(uint256 amount ){ - ( bool entered, uint index ) = isEntered( msg.sender ); - if( entered ){ - Saver memory saver = _forge.saver( account, index ); - amount = saver.mint.mul( 10**_decimals ).div( _forge.getExchangeRate() ); - amount = amount.mul( 99 ).div(100); - } - } - -} \ No newline at end of file diff --git a/contracts/Forge.sol b/contracts/Forge.sol index ef3f9f2..b939f72 100644 --- a/contracts/Forge.sol +++ b/contracts/Forge.sol @@ -5,513 +5,503 @@ pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; import "./interfaces/ForgeInterface.sol"; import "./interfaces/ModelInterface.sol"; import "./interfaces/PunkRewardPoolInterface.sol"; -import "./interfaces/ReferralInterface.sol"; import "./Ownable.sol"; import "./ForgeStorage.sol"; -import "./libs/Score.sol"; -import "./Referral.sol"; -contract Forge is ForgeInterface, ForgeStorage, Ownable, ERC20, ReentrancyGuard{ - using SafeMath for uint; +contract Forge is + ForgeInterface, + ForgeStorage, + Ownable, + ERC20, + ReentrancyGuard +{ + using SafeMath for uint256; using SafeERC20 for IERC20; - uint constant SECONDS_DAY = 86400; + uint256 constant SECONDS_DAY = 1 days; + uint256 constant SECONDS_YEAR = 31556952; - constructor() ERC20("PunkFinance","Forge"){} + enum Status { + NOT_YET_WITHDRAWN_OR_WITHDRAWABLE, + ALREADY_WITHDRAWN, + IS_TERMINATED, + ALL_WITHDRAWN + } + + constructor() ERC20("PunkFinance", "Forge") {} /** - * Initializing Forge's Variables, If already initialized, it will be reverted. - * - * @param storage_ deployed OnwableStroage's address - * @param variables_ deployed Variables's address - * @param name_ Forge's name - * @param symbol_ Forge's symbol - * @param model_ Address of the Model associated - * @param token_ ERC20 Token's address - * @param decimals_ ERC20 (tokens_)'s decimals - */ - function initializeForge( - address storage_, - address variables_, - string memory name_, - string memory symbol_, - address model_, - address token_, - uint8 decimals_ - ) public initializer { - - Ownable.initialize( storage_ ); - _variables = Variables( variables_ ); - - __name = name_; - __symbol = symbol_; - - _model = model_; - _token = token_; - _tokenUnit = 10**decimals_; - __decimals = decimals_; - - _count = 0; - _totalScore = 0; - - emit Initialize(); + * Initializing Forge's Variables, If already initialized, it will be reverted. + * + * @param storage_ deployed OnwableStroage's address + * @param variables_ deployed Variables's address + * @param name_ Forge's name + * @param symbol_ Forge's symbol + * @param model_ Model's address + * @param token_ ERC20 Token's address + * @param decimals_ ERC20 (tokens_)'s decimals + */ + function initializeForge( + address storage_, + address variables_, + string memory name_, + string memory symbol_, + address model_, + address token_, + uint8 decimals_ + ) public initializer { + Ownable.initialize(storage_); + _variables = Variables(variables_); + + __name = name_; + __symbol = symbol_; + __decimals = decimals_; + + _model = model_; + _token = token_; + _tokenUnit = 10**decimals_; + + _count = 0; + + emit Initialize(storage_, variables_, model_, token_, name_, symbol_); } - - /** - * Replace the model. If model_ isn't CA(ContractAddress), it will be reverted. - * - * @param model_ Address of the associated Model - */ - function setModel( address model_ ) public OnlyAdminOrGovernance returns( bool ){ - require( Address.isContract( model_), "FORGE : Model address must be the contract address."); - require( _model != model_, "FORGE : Current Model" ); - - ModelInterface( _model ).withdrawAllToForge(); - IERC20( _token ).safeTransfer( model_, IERC20( _token ).balanceOf( address( this ) ) ); - ModelInterface( model_ ).invest(); - - emit SetModel(_model, model_); + + function upgradeModel(address model_) + public + override + OnlyAdmin + returns (bool) + { + require(model_ != address(0), "FORGE : Model address is zero"); + require( + Address.isContract(model_), + "FORGE : Model address must be the contract address." + ); + require( + ModelInterface(model_).token() == _token, + "FORGE : Model has Token address is not equals" + ); + require( + ModelInterface(model_).forge() == address(this), + "FORGE : Model has Forge address is not equals this address" + ); + require(_model != model_, "FORGE : Current Model"); + + emit UpgradeModel(_model, model_, block.timestamp); _model = model_; - return true; + + return false; } /** - * Return the withdrawable amount. - * - * @param account Saver's owner address - * @param index Saver's index - * - * @return the withdrawable amount. - */ - function withdrawable( address account, uint index ) public view override returns( uint ){ - Saver memory s = saver( account, index ); - if( s.startTimestamp > block.timestamp ) return 0; - if( s.status == 2 ) return 0; - - uint diff = block.timestamp.sub( s.startTimestamp ); - uint count = diff.div( SECONDS_DAY.mul( s.interval ) ).add( 1 ); + * Return the withdrawable amount. + * + * @param account Saver's owner address + * @param index Saver's index + * + * @return the withdrawable amount. + */ + function withdrawable(address account, uint256 index) + public + view + override + returns (uint256) + { + Saver memory s = saver(account, index); + if (s.startTimestamp > block.timestamp) return 0; + if ( + s.status == uint256(Status.IS_TERMINATED) || + s.status == uint256(Status.ALL_WITHDRAWN) + ) return 0; + + uint256 diff = block.timestamp.sub(s.startTimestamp); + uint256 count = diff.div(SECONDS_DAY.mul(s.interval)).add(1); count = count < s.count ? count : s.count; - return s.mint.mul( count ).div( s.count ).sub( s.released ); + return s.mint.mul(count).div(s.count).sub(s.released); } /** - * Return the number of savers created with the account. - * - * @param account : Saver's owner account - * - * @return the number of savers created with the account. - */ - function countByAccount( address account ) public view override returns ( uint ){ - return _savers[account].length; - } - - /** - * Create Saver with ERC20 Token and set the required parameters - * - * This function only stores newly created Savers. The actual investment is operated on AddDeposit. - * - * @param amount ERC20 Amount - * @param startTimestamp When do you want to start receiving (unixTime:seconds) - * @param count How often do you want to receive. - * @param interval Number of times to receive (unit: 1 day) - */ - function craftingSaver( uint amount, uint startTimestamp, uint count, uint interval ) public override returns( bool ){ - craftingSaver(amount, startTimestamp, count, interval, 0); - return true; + * Return the number of savers created with the account. + * + * @param account : Saver's owner account + * + * @return the number of savers created with the account. + */ + function countByAccount(address account) + public + view + override + returns (uint256) + { + return _savers[account].length; } /** - * Create Saver with ERC20 Token and set the required parameters - * - * This function only stores newly created Savers. The actual investment is operated on AddDeposit. - * - * @param amount ERC20 Amount - * @param startTimestamp When do you want to start receiving (unixTime:seconds) - * @param count How often do you want to receive. - * @param interval Number of times to receive (unit: 1 day) - * @param referral Referral code issued from "Referral" Contract - */ - function craftingSaver( uint amount, uint startTimestamp, uint count, uint interval, bytes12 referral ) public override returns( bool ){ - require( amount > 0 && count > 0 && interval > 0 && startTimestamp > block.timestamp.add( 24 * 60 * 60 ), "FORGE : Invalid Parameters"); - uint index = countByAccount( msg.sender ); - - _savers[ msg.sender ].push( Saver( block.timestamp, startTimestamp, count, interval, 0, 0, 0, 0, 0, 0, block.timestamp, referral ) ); - _transactions[ msg.sender ][ index ].push( Transaction( true, block.timestamp, 0 ) ); + * Create Saver with ERC20 Token and set the required parameters + * + * This function only stores newly created Savers. The actual investment is operated on AddDeposit. + * + * @param amount ERC20 Amount + * @param startTimestamp When do you want to start receiving (unixTime:seconds) + * @param count How often do you want to receive. + * @param interval Number of times to receive (unit: 1 day) + */ + function craftingSaver( + uint256 amount, + uint256 startTimestamp, + uint256 count, + uint256 interval + ) public override onlyNormalUser returns (bool) { + require( + amount > 0 && + count > 0 && + interval > 0 && + startTimestamp > block.timestamp.add(24 * 60 * 60), + "FORGE : Invalid Parameters" + ); + uint256 index = countByAccount(msg.sender); + require(index < 10, "FORGE : Too many crafting Account"); + + _savers[msg.sender].push( + Saver( + block.timestamp, + startTimestamp, + count, + interval, + 0, + 0, + 0, + 0, + uint256(Status.NOT_YET_WITHDRAWN_OR_WITHDRAWABLE), + block.timestamp + ) + ); _count++; - - emit CraftingSaver( msg.sender, index, amount ); + + emit CraftingSaver(msg.sender, index, amount); addDeposit(index, amount); return true; } - + /** - * Add deposit to Saver - * - * It functions to operate the actual investment. - * It stores the amount deposited on Saver, the new score, the amount, and the timestamp added on _transactions[msg.sender]. - * Within 24 hours, it will be combined to the list of the latest _transactions[msg.sender]. - * - * @param index Saver's index - * @param amount ERC20 Amount - */ - function addDeposit( uint index, uint amount ) public nonReentrant override returns( bool ){ - require( saver( msg.sender, index ).startTimestamp > block.timestamp, "FORGE : Unable to deposit" ); - require( saver( msg.sender, index ).status < 2, "FORGE : Terminated Saver" ); - - uint mint = 0; - uint i = index; + * Add deposit to Saver + * + * It functions to operate the actual investment. + * + * @param index Saver's index + * @param amount ERC20 Amount + */ + function addDeposit(uint256 index, uint256 amount) + public + override + nonReentrant + onlyNormalUser + returns (bool) + { + require( + saver(msg.sender, index).status < uint256(Status.IS_TERMINATED), + "FORGE : Terminated Saver" + ); - { - // Avoid Stack Too Deep issue - i = i + 0; - mint = amount.mul( getExchangeRate() ).div( _tokenUnit ); - _mint( msg.sender, mint ); - if( _variables.reward() != address(0) ) { - approve( _variables.reward(), mint); - PunkRewardPoolInterface( _variables.reward() ).staking( address(this), mint, msg.sender ); - } - } + uint256 mint = 0; + uint256 i = index; { - // Avoid Stack Too Deep issue - i = i + 0; - uint lastIndex = transactions(msg.sender, i ).length.sub( 1 ); - if( block.timestamp.sub( transactions(msg.sender, i )[ lastIndex ].timestamp ) < SECONDS_DAY ){ - _transactions[msg.sender][ index ][ lastIndex ].amount += amount; - }else{ - _transactions[msg.sender][ index ].push( Transaction( true, block.timestamp, amount ) ); - } + mint = _exchangeToLp(amount); _savers[msg.sender][i].mint += mint; _savers[msg.sender][i].accAmount += amount; _savers[msg.sender][i].updatedTimestamp = block.timestamp; - _updateScore( msg.sender, i ); } { - IERC20( _token ).safeTransferFrom( msg.sender, _model, amount ); - ModelInterface( _model ).invest(); - emit AddDeposit( msg.sender, index, amount ); + IERC20(_token).safeTransferFrom(msg.sender, _model, amount); + ModelInterface(_model).invest(); + emit AddDeposit(msg.sender, index, amount); + + _mint(msg.sender, mint); } return true; } - + + /** + * Withdraw + * + * Enter the amount of pLP token ( Do not enter ERC20 Token's Amount ) + * Withdraw excluding service fee. + * + * @param index Saver's index + * @param hopeUnderlying Forge's LP Token Amount + */ + function withdrawUnderlying(uint256 index, uint256 hopeUnderlying) + public + override + nonReentrant + onlyNormalUser + returns (bool) + { + return withdraw(index, _exchangeToLp(hopeUnderlying)); + } + /** - * Withdraw - * - * Enter the amount of pLP token ( Do not enter ERC20 Token's Amount ) - * Withdraw excluding service fee. if saver has referral code, then discount service fee. - * - * @param index Saver's index - * @param amountPlp Forge's LP Token Amount - */ - function withdraw( uint index, uint amountPlp ) public nonReentrant override returns( bool ){ - Saver memory s = saver( msg.sender, index ); - uint withdrawablePlp = withdrawable( msg.sender, index ); - require( s.status < 2 , "FORGE : Terminated Saver"); - require( withdrawablePlp >= amountPlp, "FORGE : Insufficient Amount" ); - - uint i = index; + * Withdraw + * + * Enter the amount of pLP token ( Do not enter ERC20 Token's Amount ) + * Withdraw excluding service fee. + * + * @param index Saver's index + * @param hope Forge's LP Token Amount + */ + function withdraw(uint256 index, uint256 hope) + public + override + nonReentrant + onlyNormalUser + returns (bool) + { + Saver memory s = saver(msg.sender, index); + uint256 withdrawablePlp = withdrawable(msg.sender, index); + require( + s.status < uint256(Status.IS_TERMINATED), + "FORGE : Terminated Saver" + ); + require(withdrawablePlp >= hope, "FORGE : Insufficient Amount"); + require(balanceOf(msg.sender) >= hope, "FORGE : Insufficient Amount"); + + // TODO Confirm withdrawal of currency after use of balance. /* for Underlying ERC20 token */ + { - i = i + 0; - ( uint amountOfWithdraw, uint amountOfServiceFee, uint amountOfBuyback , uint amountOfReferral, address ref ) = _withdrawValues(msg.sender, i, amountPlp); - - _savers[msg.sender][i].status = 1; - _savers[msg.sender][i].released += amountPlp; - _savers[msg.sender][i].relAmount += amountOfWithdraw; - _savers[msg.sender][i].updatedTimestamp = block.timestamp; - if( _savers[msg.sender][i].mint == _savers[msg.sender][i].released ){ - _savers[msg.sender][i].status = 3; - _totalScore = _totalScore.sub( s.score ); - } - emit Withdraw( msg.sender, i, amountOfWithdraw ); + ( + uint256 amountOfWithdraw, + uint256 amountOfServiceFee + ) = _withdrawValues(msg.sender, index, hope, false); + + _savers[msg.sender][index].released += hope; + _savers[msg.sender][index].relAmount += amountOfWithdraw; + _savers[msg.sender][index].updatedTimestamp = block.timestamp; + _savers[msg.sender][index].status = (_savers[msg.sender][index] + .mint == _savers[msg.sender][index].released) + ? uint256(Status.ALL_WITHDRAWN) + : uint256(Status.ALREADY_WITHDRAWN); + + emit Withdraw(msg.sender, index, amountOfWithdraw); _withdrawTo(amountOfWithdraw, msg.sender); - _withdrawTo(amountOfServiceFee, _variables.opTreasury() ); - _withdrawTo(amountOfBuyback, _variables.treasury()); - /* If referral code is valid, referral code providers will be rewarded. */ - if( amountOfReferral > 0 && ref != address(0)){ - _withdrawTo( amountOfReferral, ref ); - } - } + _withdrawTo(amountOfServiceFee, _variables.treasury()); - { - // For LP Tokens - i = i+0; - uint amount = amountPlp; - uint bonus = balanceOf(address(this)).mul( amountPlp ).mul( s.score ).div( _totalScore ).div( s.mint ); - if( _variables.reward() != address(0) ) PunkRewardPoolInterface( _variables.reward() ).unstaking(address(this), amount, msg.sender ); - _burn( msg.sender, amount ); - _burn( address( this ), bonus ); + _burn(msg.sender, hope); } + return true; } - + /** - * Terminate Saver - * - * Forcibly terminate Saver and return the deposit. However, early termination fee and service fee are charged. - * - * @param index Saver's index - */ - function terminateSaver( uint index ) public nonReentrant override returns( bool ){ - require( saver( msg.sender, index ).status < 2, "FORGE : Already Terminated" ); - Saver memory s = saver( msg.sender, index ); - - uint i = index; + * Terminate Saver + * + * Forcibly terminate Saver and return the deposit. However, early termination fee and service fee are charged. + * + * @param index Saver's index + */ + function terminateSaver(uint256 index) + public + override + nonReentrant + onlyNormalUser + returns (bool) + { + Saver memory s = saver(msg.sender, index); + require( + s.status < uint256(Status.IS_TERMINATED), + "FORGE : Already Terminated or Completed" + ); - /* for Underlying ERC20 token */ - { - i = i + 0; - (uint amountOfWithdraw, uint amountOfServiceFee, uint amountOfReferral, address ref ) = _terminateValues( msg.sender, i ); - uint remain = s.mint.sub(s.released).mul( _tokenUnit ).div( getExchangeRate() ); - require( remain >= amountOfWithdraw, "FORGE : Insufficient Terminate Fee" ); - - _totalScore = _totalScore.sub( s.score ); - _savers[msg.sender][i].status = 2; - _savers[msg.sender][i].updatedTimestamp = block.timestamp; - emit Terminate( msg.sender, index, amountOfWithdraw ); - - /* the actual amount to be withdrawn. */ - _withdrawTo( amountOfWithdraw, msg.sender ); - /* service fee is charged. */ - _withdrawTo( amountOfServiceFee, _variables.opTreasury() ); - /* If referral code is valid, referral code providers will be rewarded. */ - if( amountOfReferral > 0 && ref != address(0)){ - _withdrawTo( amountOfReferral, ref ); - } - } + uint256 hope = s.mint.sub(s.released); - /* for pLP token */ { - i = i + 0; - uint lp = s.mint.sub(s.released); - uint bonus = s.mint.mul( _variables.earlyTerminateFee( address(this) ) ).div( 100 ); - if( _variables.reward() != address(0) ) PunkRewardPoolInterface( _variables.reward() ).unstaking(address(this), lp, msg.sender ); - - /* If the amount is already withdrawn and the remaining amount is less than the fee, it will be reverted. */ - _burn( msg.sender, lp ); - _mint( address( this ), bonus ); - emit Bonus( msg.sender, index, bonus ); + require(balanceOf(msg.sender) >= hope, "FORGE : Insufficient Amount"); + ( + uint256 amountOfWithdraw, + uint256 amountOfServiceFee + ) = _withdrawValues(msg.sender, index, hope, true); + + _savers[msg.sender][index].status = uint256(Status.IS_TERMINATED); + _savers[msg.sender][index].released += hope; + _savers[msg.sender][index].relAmount += amountOfWithdraw; + _savers[msg.sender][index].updatedTimestamp = block.timestamp; + + emit Terminate(msg.sender, index, amountOfWithdraw); + + /* the actual amount to be withdrawn. */ + _withdrawTo(amountOfWithdraw, msg.sender); + /* service fee is charged. */ + _withdrawTo(amountOfServiceFee, _variables.treasury()); + + _burn(msg.sender, hope); } return true; } /** - * Return the exchange rate of ERC20 Token to pLP token, utilizing the balance of the total ERC20 Token invested into the model and the total supply of pLP token. - * - * @return the exchange rate of ERC20 Token to pLP token - */ - function getExchangeRate() public view override returns( uint ){ - if( ModelInterface(_model ).underlyingBalanceWithInvestment() == 0 || totalSupply() == 0 ){ - return _tokenUnit; - }else{ - return _tokenUnit.mul( totalSupply() ).div( ModelInterface(_model ).underlyingBalanceWithInvestment() ); - } + * Return the exchange rate of ERC20 Token to pLP token, utilizing the balance of the total ERC20 Token invested into the model and the total supply of pLP token. + * + * @return the exchange rate of ERC20 Token to pLP token + */ + function exchangeRate() public view override returns (uint256) { + return + totalSupply() == 0 + ? _tokenUnit + : _tokenUnit.mul(totalVolume()).div(totalSupply()); } /** - * Return the bonus(ERC20) amount - * - * Bonus is sum of EarlyTerminationFee - * - * @return total bonus amount - */ - function getBonus() public view override returns( uint ){ - return balanceOf( address( this ) ).mul( _tokenUnit ).div( getExchangeRate( ) ); + * Return the invested amount(ERC20) + * + * @return total invested amount + */ + function totalVolume() public view override returns (uint256) { + return ModelInterface(_model).underlyingBalanceWithInvestment(); } /** - * Return the invested amount(ERC20) - * - * @return total invested amount - */ - function getTotalVolume() public view override returns( uint ){ - return ModelInterface(_model ).underlyingBalanceWithInvestment(); + * Return the associated model address. + * + * @return model address. + */ + function modelAddress() public view override returns (address) { + return _model; } - - /** - * Return the associated model address. - * - * @return model address. - */ - function modelAddress() public view override returns ( address ){ return _model; } /** - * Return the number of all created savers, including terminated Saver - * - * @return the number of all created savers - */ - function countAll() public view override returns( uint ){ return _count; } - - /** - * Return the Saver's all properties - * - * @param account Saver's index - * @param index Forge's pLP Token Amount - * - * @return model address. - */ - function saver( address account, uint index ) public view override returns( Saver memory ){ return _savers[account][index]; } - - /** - * Return deposit & withdrawn histories - * - * @param account Saver's index - * @param index Forge's pLP Token Amount - * - * @return deposit & withdrawn histories - */ - function transactions( address account, uint index ) public view override returns ( Transaction [] memory ){ return _transactions[account][index]; } - - - /** - * Change the address of Variables. - * - * this function checks the admin address through OwnableStorage - * - * @param variables_ Vaiables's address - */ - function setVariable( address variables_ ) public OnlyAdmin{ - _variables = Variables( variables_ ); + * Return the number of all created savers, including terminated Saver + * + * @return the number of all created savers + */ + function countAll() public view override returns (uint256) { + return _count; } /** - * Call a function withdrawTo from Model contract - * - * @param amount amount of withdraw - * @param account subject to be withdrawn to - */ - function _withdrawTo( uint amount, address account ) private { - if( amount != 0 ) ModelInterface( modelAddress() ).withdrawTo( amount, account ); + * Return the Saver's all properties + * + * @param account Saver's index + * @param index Forge's pLP Token Amount + * + * @return model address. + */ + function saver(address account, uint256 index) + public + view + override + returns (Saver memory) + { + return _savers[account][index]; } /** - * Update Saver's score - * - * @param account Saver's owner account - * @param index Saver's index - */ - function _updateScore( address account, uint index ) internal { - Saver memory s = saver(account, index); - uint oldScore = s.score; - uint newScore = Score.calculate( - s.createTimestamp, - s.startTimestamp, - _transactions[account][index], - s.count, - s.interval, - 1 - ); - _savers[account][index].score = newScore; - _totalScore = _totalScore.add( newScore ).sub( oldScore ); + * Change the address of Variables. + * + * this function checks the admin address through OwnableStorage + * + * @param variables_ Vaiables's address + */ + function setVariable(address variables_) public OnlyAdmin { + _variables = Variables(variables_); } /** - * Return the calculated variables needed to termiate. - * - * @param account Saver's owner account - * @param index Saver's index - * - * @return amountOfWithdraw - * @return amountOfServiceFee - * @return amountOfReferral - * @return compensation : subject to be rewarded - */ - function _terminateValues( address account, uint index ) public view returns( uint amountOfWithdraw, uint amountOfServiceFee, uint amountOfReferral, address compensation ){ - Saver memory s = saver( account, index ); - uint tf = _variables.earlyTerminateFee(address(this)); - uint sf = _variables.serviceFee(); - uint dc = _variables.discount(); - uint cm = _variables.compensation(); - - compensation = Referral(_variables.referral()).validate( s.ref ); - uint amount = s.mint.mul( _tokenUnit ).div( getExchangeRate() ); - - if( compensation == address(0) ){ - uint amountOfTermiateFee = amount.mul( tf ).div( 100 ); - amountOfServiceFee = amount.mul( sf ).div( 100 ); - amountOfWithdraw = amount.sub( amountOfServiceFee ).sub( amountOfTermiateFee ); - amountOfReferral = 0; - }else{ - uint amountOfTermiateFee = amount.mul( tf ).div( 100 ); - amountOfServiceFee = amount.mul( sf ).div( 100 ); - - uint amountOfDc = amountOfServiceFee.mul( dc ).div( 100 ); - amountOfReferral = amountOfServiceFee.mul( cm ).div( 100 ); - amountOfServiceFee = amountOfServiceFee.sub( amountOfDc ).sub( amountOfReferral ); - amountOfWithdraw = amount.sub( amountOfServiceFee ).sub( amountOfTermiateFee ); + * Call a function withdrawTo from Model contract + * + * @param amount amount of withdraw + * @param account subject to be withdrawn to + */ + function _withdrawTo(uint256 amount, address account) private { + if (amount != 0) { + ModelInterface(_model).withdrawToForge(amount); + IERC20(_token).safeTransfer(account, amount); } } /** - * Return the calculated variables needed to withdraw. - * - * @param account Saver's owner account - * @param index Saver's index - * - * @return amountOfWithdraw - * @return amountOfServiceFee - * @return amountOfBuyback - * @return amountOfReferral - * @return compensation : subject to be rewarded - */ - function _withdrawValues( address account, uint index, uint hope ) public view returns( uint amountOfWithdraw, uint amountOfServiceFee, uint amountOfBuyback ,uint amountOfReferral, address compensation ){ - Saver memory s = saver( account, index ); - - uint sf = _variables.serviceFee(); - uint dc = _variables.discount(); - uint cm = _variables.compensation(); - - compensation = Referral(_variables.referral()).validate( s.ref ); - amountOfBuyback = _calculateBuyback( account, index, hope ); - - uint amount = hope.mul( _tokenUnit ).div( getExchangeRate() ); - uint bonus = getBonus().mul( s.score ).div( _totalScore ); - - if( compensation == address(0) ){ - bonus = bonus.mul( hope ).div( s.mint ); - amount = amount.add(bonus); - amountOfServiceFee = amount.mul( sf ).div( 100 ); - amountOfWithdraw = amount.sub(amountOfServiceFee).sub(amountOfBuyback); - }else{ - bonus = bonus.mul( hope ).div( s.mint ); - amount = amount.add(bonus); - amountOfServiceFee = amount.mul( sf ).div( 100 ); - uint amountOfDc = amountOfServiceFee.mul( dc ).div( 100 ); - amountOfReferral = amountOfServiceFee.mul( cm ).div( 100 ); - amountOfServiceFee = amountOfServiceFee.sub( amountOfDc ).sub(amountOfReferral); - amountOfWithdraw = amount.sub(amountOfServiceFee).sub(amountOfBuyback); + * Return the calculated variables needed to withdraw and terminate. + * + * @param account Saver's owner account + * @param index Saver's index + * @param hope Saver's index + * @param isTerminate Saver's index + * + * @return amountOfWithdraw + * @return amountOfFee + */ + function _withdrawValues( + address account, + uint256 index, + uint256 hope, + bool isTerminate + ) public view returns (uint256 amountOfWithdraw, uint256 amountOfFee) { + Saver memory s = saver(account, index); + uint256 fm = _variables.feeMultiplier(); + + uint256 amount = _exchangeToUnderlying(hope); + uint256 successFee = _successFee(s, hope); + uint256 serviceFee = _serviceFee(s, hope) + .mul(isTerminate ? fm : 100) + .div(100); + + if (successFee.add(serviceFee) >= amount) { + amountOfWithdraw = 0; + amountOfFee = successFee.add(serviceFee); + } else { + amountOfFee = successFee.add(serviceFee); + amountOfWithdraw = amount.sub(amountOfFee); } - } - /** - * Calculate the amount to buyback. - * - * It transfers to treasury to buyback a part of profit. - * - * @param account Saver's owner account - * @param index Saver's index - */ - function _calculateBuyback( address account, uint index, uint hope ) public view returns( uint buyback ) { - Saver memory s = saver( account, index ); - uint br = _variables.buybackRate(); - uint balance = s.mint.mul( _tokenUnit ).div( getExchangeRate() ); - buyback = balance.sub( s.mint ).mul( hope ).mul (br ).div( s.mint ).div(100); + function _profit(Saver memory s) private view returns (uint256) { + uint256 allValueToUnderlying = _exchangeToUnderlying(s.mint); + uint256 accAmount = s.accAmount; + if (allValueToUnderlying > accAmount) { + allValueToUnderlying.sub(accAmount); + } + return 0; } + function _successFee(Saver memory s, uint256 hope) + private + view + returns (uint256 successFee) + { + uint256 sf = _variables.successFee(); + uint256 profit = _profit(s); + successFee = profit > 0 + ? profit.mul(hope).mul(sf).div(100).div(s.mint) + : 0; + } + function _serviceFee(Saver memory s, uint256 hope) + private + view + returns (uint256 serviceFee) + { + uint256 sf = _variables.serviceFee(); + uint256 period = block.timestamp.sub(s.createTimestamp); + uint256 amount = _exchangeToUnderlying(hope); + if (period >= SECONDS_YEAR) { + serviceFee = amount.mul(sf).div(100); + } else { + serviceFee = amount.mul(period).mul(sf).div(SECONDS_YEAR).div(100); + } + } // Override ERC20 function symbol() public view override returns (string memory) { - return symbol(); + return __symbol; } function name() public view override returns (string memory) { @@ -522,8 +512,15 @@ contract Forge is ForgeInterface, ForgeStorage, Ownable, ERC20, ReentrancyGuard{ return __decimals; } - function totalScore() public view override returns(uint256){ - return _totalScore; + function _exchangeToUnderlying(uint256 amount) + public + view + returns (uint256) + { + return amount.mul(exchangeRate()).div(_tokenUnit); } -} \ No newline at end of file + function _exchangeToLp(uint256 amount) public view returns (uint256) { + return amount.mul(_tokenUnit).div(exchangeRate()); + } +} diff --git a/contracts/ForgeProxy.sol b/contracts/ForgeProxy.sol index c935dfe..e0be130 100644 --- a/contracts/ForgeProxy.sol +++ b/contracts/ForgeProxy.sol @@ -5,65 +5,86 @@ import "@openzeppelin/contracts/utils/Address.sol"; import "@openzeppelin/contracts/proxy/Proxy.sol"; import "./OwnableStorage.sol"; -contract ForgeProxy is Proxy{ - - event Upgraded(address indexed implementation); - - bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - bytes32 private constant _OWNABLE_STORAGE_SLOT = 0xb39836d625a4efe66fcfaa81a972ba97548a953a597399c161cd7df952bcf2e8; - bytes32 private constant _INITIALIZE_SLOT = 0x5995627934808137c9bf9d6f83d56749658ca23d1b6461c2a912ee34403ccd6a; - - modifier isInitializer(){ - require( getInitialize() != 1, "Initializable: contract is already initialized"); +contract ForgeProxy is Proxy { + event Upgraded(address indexed implementation, uint256 upgradeTimestamp); + + bytes32 private constant _IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + bytes32 private constant _NEXT_IMPLEMENTATION_SLOT = + 0x386fd0873c4dae4047292a961c4d79fea20281d6344fde0002a91190c29439e0; + bytes32 private constant _NEXT_IMPLEMENTATION_TIMESTAMP_SLOT = + 0x2f4ec45a1b013d9051b3ed7cdfb2a5b3e28368f1dafac0e7898229fb9db98dca; + bytes32 private constant _OWNABLE_STORAGE_SLOT = + 0xb39836d625a4efe66fcfaa81a972ba97548a953a597399c161cd7df952bcf2e8; + bytes32 private constant _INITIALIZE_SLOT = + 0x5995627934808137c9bf9d6f83d56749658ca23d1b6461c2a912ee34403ccd6a; + + modifier isInitializer() { + require( + getInitialize() != 1, + "Initializable: contract is already initialized" + ); _; } - modifier CheckAdmin(){ - require( OwnableStorage( _storage() ).isAdmin(msg.sender), "OWNABLE: 0x0" ); + modifier OnlyAdmin() { + require(OwnableStorage(_storage()).isAdmin(msg.sender), "OWNABLE: 0x0"); _; } - function initialize( address storage_, address implAddress ) public isInitializer{ - require(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); - require(_OWNABLE_STORAGE_SLOT == bytes32(uint256(keccak256("forge.proxy.ownablestrage")) - 1)); - require(_INITIALIZE_SLOT == bytes32(uint256(keccak256("forge.proxy.initialize")) - 1)); + function initialize(address storage_, address implAddress) + public + isInitializer + { + require( + _IMPLEMENTATION_SLOT == + bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1) + ); + require( + _OWNABLE_STORAGE_SLOT == + bytes32(uint256(keccak256("forge.proxy.ownablestrage")) - 1) + ); + require( + _INITIALIZE_SLOT == + bytes32(uint256(keccak256("forge.proxy.initialize")) - 1) + ); _setImplementation(implAddress); - _setStorage( storage_ ); - _setInitialize( ); + _setStorage(storage_); + _setInitialize(); } - function _setStorage( address storage_ ) internal { + function _storage() internal view returns (address storageAddr) { bytes32 slot = _OWNABLE_STORAGE_SLOT; // solhint-disable-next-line no-inline-assembly assembly { - sstore(slot, storage_) + storageAddr := sload(slot) } } - function _storage() internal view returns( address storageAddr ){ + function _setStorage(address storage_) internal { bytes32 slot = _OWNABLE_STORAGE_SLOT; // solhint-disable-next-line no-inline-assembly assembly { - storageAddr := sload(slot) + sstore(slot, storage_) } } - function _implementation() internal view override returns (address impl) { - bytes32 slot = _IMPLEMENTATION_SLOT; - // solhint-disable-next-line no-inline-assembly - assembly { - impl := sload(slot) - } - } + function requestUpgradeTo(address newImplementation) public OnlyAdmin { + require( newImplementation != address(0), "" ); + require( Address.isContract(newImplementation), ""); - function upgradeTo(address newImplementation) public CheckAdmin { _setImplementation(newImplementation); - emit Upgraded(newImplementation); + + emit Upgraded(newImplementation, block.timestamp); } + function _setImplementation(address newImplementation) private { - require(Address.isContract(newImplementation), "ERC1967Proxy: new implementation is not a contract"); + require( + Address.isContract(newImplementation), + "ERC1967Proxy: new implementation is not a contract" + ); bytes32 slot = _IMPLEMENTATION_SLOT; @@ -73,18 +94,26 @@ contract ForgeProxy is Proxy{ } } - function _setInitialize( ) internal { + function _implementation() internal view override returns (address impl) { + bytes32 slot = _IMPLEMENTATION_SLOT; + // solhint-disable-next-line no-inline-assembly + assembly { + impl := sload(slot) + } + } + + function _setInitialize() internal { // solhint-disable-next-line no-inline-assembly assembly { sstore(_INITIALIZE_SLOT, 1) } } - function getInitialize( ) private view returns (uint256 str) { + function getInitialize() private view returns (uint256 str) { // solhint-disable-next-line no-inline-assembly assembly { - str := sload( _INITIALIZE_SLOT ) + str := sload(_INITIALIZE_SLOT) } } -} \ No newline at end of file +} diff --git a/contracts/ForgeStorage.sol b/contracts/ForgeStorage.sol index ba9dd49..326d422 100644 --- a/contracts/ForgeStorage.sol +++ b/contracts/ForgeStorage.sol @@ -8,7 +8,13 @@ import "./Variables.sol"; abstract contract ForgeStorage{ Variables internal _variables; + + uint256 internal _delayTime = 48 hours; + address internal _model; + address internal _nextUpgradeModel; + uint256 internal _nextUpgradeModelTimestamp; + address internal _token; uint internal _tokenUnit; @@ -16,15 +22,15 @@ abstract contract ForgeStorage{ string internal __symbol; uint8 internal __decimals; - - mapping( address => uint ) internal _tokensBalances; - mapping( address => Saver [] ) _savers; - mapping( address => mapping( uint => Transaction [] ) ) _transactions; // set to address uint internal _count; - uint internal _totalScore; uint256[50] private ______gap; + + modifier onlyNormalUser{ + require(msg.sender == tx.origin, "FORGE : Not Wokring this Function SmartContract"); + _; + } } \ No newline at end of file diff --git a/contracts/ModelStorage.sol b/contracts/ModelStorage.sol index 51c81a1..3edf0ec 100644 --- a/contracts/ModelStorage.sol +++ b/contracts/ModelStorage.sol @@ -2,9 +2,14 @@ pragma solidity >=0.5.0 <0.9.0; pragma experimental ABIEncoderV2; -contract ModelStorage{ +import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import "@openzeppelin/contracts/utils/Address.sol"; +import "./interfaces/ModelInterface.sol"; +import "./interfaces/ModelInterface.sol"; + +abstract contract ModelStorage is ModelInterface{ - address [] private _tokens; + address private _token; address private _forge; /** @@ -16,13 +21,12 @@ contract ModelStorage{ } /** - * @dev Add a 'token' ERC20 to be used in the model. + * @dev set a 'token' ERC20 to be used in the model. */ - function addToken( address token_ ) internal returns( bool ){ - for( uint i = 0 ; i < tokens().length ; i++ ){ - if( token( i ) == token_ ){ return false; } - } - _tokens.push( token_ ); + function setToken( address token_ ) internal returns( bool ){ + require( Address.isContract(token_), "MODEL : the address is not contract address" ); + require( IERC20(token_).totalSupply() > 0, "MODEL : the address is not ERC20 Token" ); + _token = token_; return true; } @@ -32,6 +36,7 @@ contract ModelStorage{ * IMPORTANT: 'Forge' should be non-replaceable by default. */ function setForge( address forge_ ) internal returns( bool ){ + require( Address.isContract(forge_), "MODEL : the address is not contract address" ); _forge = forge_; return true; } @@ -39,21 +44,14 @@ contract ModelStorage{ /** * @dev Returns the address of the token as 'index'. */ - function token( uint index ) public view returns( address ){ - return _tokens[index]; - } - - /** - * @dev Returns a list of addresses of tokens. - */ - function tokens() public view returns( address [] memory ){ - return _tokens; + function token() public view override returns( address ){ + return _token; } /** * @dev Returns the address of Forge. */ - function forge() public view returns( address ){ + function forge() public view override returns( address ){ return _forge; } } \ No newline at end of file diff --git a/contracts/OperatorTreasury.sol b/contracts/OperatorTreasury.sol index 48939fd..b8e2aff 100644 --- a/contracts/OperatorTreasury.sol +++ b/contracts/OperatorTreasury.sol @@ -8,6 +8,8 @@ import "./Ownable.sol"; contract OperatorTreasury is Ownable { using SafeERC20 for IERC20; + event SetTo( address beforeAddress, address afterAddress ); + address private to; constructor( address storage_ ){ @@ -24,6 +26,7 @@ contract OperatorTreasury is Ownable { } function setTo(address account) public OnlyAdmin{ + emit SetTo( to, account ); to = account; } diff --git a/contracts/Ownable.sol b/contracts/Ownable.sol index 402e84c..a24f75f 100644 --- a/contracts/Ownable.sol +++ b/contracts/Ownable.sol @@ -17,14 +17,4 @@ contract Ownable is Initializable{ _; } - modifier OnlyGovernance(){ - require( _storage.isGovernance( msg.sender ), "OWNABLE : Only Governance" ); - _; - } - - modifier OnlyAdminOrGovernance(){ - require( _storage.isAdmin(msg.sender) || _storage.isGovernance( msg.sender ), "OWNABLE : Only Admin Or Governance" ); - _; - } - } \ No newline at end of file diff --git a/contracts/OwnableStorage.sol b/contracts/OwnableStorage.sol index 03d6af5..f4b6c44 100644 --- a/contracts/OwnableStorage.sol +++ b/contracts/OwnableStorage.sol @@ -3,30 +3,14 @@ pragma solidity >=0.5.0 <0.9.0; contract OwnableStorage { - address public _admin; - address public _governance; + address timeLock; - constructor() { - _admin = msg.sender; - _governance = msg.sender; - } - - function setAdmin( address account ) public { - require( isAdmin( msg.sender ), "OWNABLE STORAGE : Only Admin"); - _admin = account; - } - - function setGovernance( address account ) public { - require( isAdmin( msg.sender ) || isGovernance( msg.sender ), "OWNABLE STORAGE : Only Admin or Gov"); - _governance = account; + constructor( address timeLock_ ) { + timeLock = timeLock_; } function isAdmin( address account ) public view returns( bool ) { - return account == _admin; - } - - function isGovernance( address account ) public view returns( bool ) { - return account == _governance; + return timeLock == account; } } \ No newline at end of file diff --git a/contracts/PunkRewardPool.sol b/contracts/PunkRewardPool.sol deleted file mode 100644 index be11856..0000000 --- a/contracts/PunkRewardPool.sol +++ /dev/null @@ -1,300 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -import "@openzeppelin/contracts/security/ReentrancyGuard.sol"; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; -import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "./Ownable.sol"; - -// Hard Work Now! For Punkers by 0xViktor... -contract PunkRewardPool is Ownable, ReentrancyGuard{ - using SafeMath for uint; - using SafeERC20 for IERC20; - - bool isStarting = false; - - uint constant MAX_WEIGHT = 500; - uint constant BLOCK_YEAR = 2102400; - - IERC20 Punk; - uint startBlock; - - address [] forges; - - mapping ( address => uint ) totalSupplies; - mapping ( address => mapping( address=>uint ) ) balances; - mapping ( address => mapping( address=>uint ) ) checkPointBlocks; - - mapping( address => uint ) weights; - uint weightSum; - - mapping( address => uint ) distributed; - uint totalDistributed; - - event Initialize(); - event Start(); - event AddForge(address forge); - event SetForge(address forge, uint weight); - event Claim(address forge, uint amount); - event Staking(address forge, uint amount, address from); - event Unstaking(address forge, uint amount, address from); - - function initializeReward( address storage_, address punk_ ) public initializer { - // Hard Work Now! For Punkers by 0xViktor... - Ownable.initialize( storage_ ); - Punk = IERC20( punk_ ); - startBlock = 0; - weightSum = 0; - totalDistributed = 0; - - emit Initialize(); - } - - function start() public OnlyAdmin{ - require(!isStarting, "PUNK_REWARD_POOL : Already Started"); - startBlock = block.number; - isStarting = true; - emit Start(); - } - - function addForge( address forge ) public OnlyAdmin { - // Hard Work Now! For Punkers by 0xViktor... - require( Address.isContract(forge), "PUNK_REWARD_POOL : Not Contract Address"); - require( !checkForge( forge ), "PUNK_REWARD_POOL: Already Exist" ); - forges.push( forge ); - weights[ forge ] = 0; - emit AddForge(forge); - } - - function setForge( address forge, uint weight ) public OnlyAdmin { - // Hard Work Now! For Punkers by 0xViktor... - require( checkForge( forge ), "PUNK_REWARD_POOL: Not Exist Forge" ); - ( uint minWeight , uint maxWeight ) = getWeightRange( forge ); - require( minWeight <= weight && weight <= maxWeight, "PUNK_REWARD_POOL: Invalid weight" ); - weights[ forge ] = weight; - - weightSum = 0; - for( uint i = 0 ; i < forges.length ; i++ ){ - weightSum += weights[ forges[ i ] ]; - } - - emit SetForge( forge, weight ); - } - - function getWeightRange( address forge ) public view returns( uint, uint ){ - // Hard Work Now! For Punkers by 0xViktor... - if( forges.length == 0 ) return ( 1, MAX_WEIGHT ); - if( forges.length == 1 ) return ( weights[ forges[ 0 ] ], weights[ forges[ 0 ] ] ); - if( weightSum == 0 ) return ( 0, MAX_WEIGHT ); - - uint highestWeight = 0; - uint excludeWeight = weightSum.sub( weights[ forge ] ); - - for( uint i = 0 ; i < forges.length ; i++ ){ - if( forges[ i ] != forge && highestWeight < weights[ forges[ i ] ] ){ - highestWeight = weights[ forges[ i ] ]; - } - } - - if( highestWeight > excludeWeight.sub( highestWeight ) ){ - return ( highestWeight.sub( excludeWeight.sub( highestWeight ) ), MAX_WEIGHT < excludeWeight ? MAX_WEIGHT : excludeWeight ); - }else{ - return ( 0, MAX_WEIGHT < excludeWeight ? MAX_WEIGHT : excludeWeight ); - } - } - - function claimPunk( ) public { - // Hard Work Now! For Punkers by 0xViktor... - claimPunk( msg.sender ); - } - - function claimPunk( address to ) public { - // Hard Work Now! For Punkers by 0xViktor... - if( isStarting ){ - for( uint i = 0 ; i < forges.length ; i++ ){ - address forge = forges[i]; - uint reward = getClaimPunk( forge, to ); - checkPointBlocks[ forge ][ to ] = block.number; - if( reward > 0 ) Punk.safeTransfer( to, reward ); - distributed[ forge ] = distributed[ forge ].add( reward ); - totalDistributed = totalDistributed.add( reward ); - emit Claim( forge, reward ); - } - } - } - - function claimPunk( address forge, address to ) public nonReentrant { - // Hard Work Now! For Punkers by 0xViktor... - if( isStarting ){ - uint reward = getClaimPunk( forge, to ); - checkPointBlocks[ forge ][ to ] = block.number; - if( reward > 0 ) Punk.safeTransfer( to, reward ); - distributed[ forge ] = distributed[ forge ].add( reward ); - totalDistributed = totalDistributed.add( reward ); - emit Claim( forge, reward ); - } - } - - function staking( address forge, uint amount ) public { - // Hard Work Now! For Punkers by 0xViktor... - staking( forge, amount, msg.sender ); - } - - function staking( address forge, uint amount, address from ) public nonReentrant { - // Hard Work Now! For Punkers by 0xViktor... - require( msg.sender == from || checkForge( msg.sender ), "REWARD POOL : NOT ALLOWD" ); - claimPunk( from ); - checkPointBlocks[ forge ][ from ] = block.number; - IERC20( forge ).safeTransferFrom( from, address( this ), amount ); - balances[ forge ][ from ] = balances[ forge ][ from ].add( amount ); - totalSupplies[ forge ] = totalSupplies[ forge ].add( amount ); - emit Staking(forge, amount, from); - } - - function unstaking( address forge, uint amount ) public { - // Hard Work Now! For Punkers by 0xViktor... - unstaking( forge, amount, msg.sender ); - } - - function unstaking( address forge, uint amount, address from ) public nonReentrant { - // Hard Work Now! For Punkers by 0xViktor... - require( msg.sender == from || checkForge( msg.sender ), "REWARD POOL : NOT ALLOWD" ); - claimPunk( from ); - checkPointBlocks[ forge ][ from ] = block.number; - balances[ forge ][ from ] = balances[ forge ][ from ].sub( amount ); - IERC20( forge ).safeTransfer( from, amount ); - totalSupplies[ forge ] = totalSupplies[ forge ].sub( amount ); - emit Unstaking(forge, amount, from); - } - - function checkForge( address forge ) public view returns( bool ){ - // Hard Work Now! For Punkers by 0xViktor... - bool check = false; - for( uint i = 0 ; i < forges.length ; i++ ){ - if( forges[ i ] == forge ){ - check = true; - break; - } - } - return check; - } - - function _calcRewards( address forge, address user, uint fromBlock, uint currentBlock ) internal view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - uint balance = balances[ forge ][ user ]; - if( balance == 0 ) return 0; - uint totalSupply = totalSupplies[ forge ]; - uint weight = weights[ forge ]; - - uint startPeriod = _getPeriodFromBlock( fromBlock ); - uint endPeriod = _getPeriodFromBlock( currentBlock ); - - if( startPeriod == endPeriod ){ - - uint during = currentBlock.sub( fromBlock ).mul( balance ).mul( weight ).mul( _perBlockRateFromPeriod( startPeriod ) ); - return during.div( weightSum ).div( totalSupply ); - - }else{ - uint denominator = weightSum.mul( totalSupply ); - - uint duringStartNumerator = _getBlockFromPeriod( startPeriod.add( 1 ) ).sub( fromBlock ); - duringStartNumerator = duringStartNumerator.mul( weight ).mul( _perBlockRateFromPeriod( startPeriod ) ).mul( balance ); - - uint duringEndNumerator = currentBlock.sub( _getBlockFromPeriod( endPeriod ) ); - duringEndNumerator = duringEndNumerator.mul( weight ).mul( _perBlockRateFromPeriod( endPeriod ) ).mul( balance ); - - uint duringMid = 0; - - for( uint i = startPeriod.add( 1 ) ; i < endPeriod ; i++ ) { - uint numerator = BLOCK_YEAR.mul( 4 ).mul( balance ).mul( weight ).mul( _perBlockRateFromPeriod( i ) ); - duringMid += numerator.div( denominator ); - } - - uint duringStartAmount = duringStartNumerator.div( denominator ); - uint duringEndAmount = duringEndNumerator.div( denominator ); - - return duringStartAmount + duringMid + duringEndAmount; - } - } - - function _getBlockFromPeriod( uint period ) internal view returns ( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return startBlock.add( period.sub( 1 ).mul( BLOCK_YEAR ).mul( 4 ) ); - } - - function _getPeriodFromBlock( uint blockNumber ) internal view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return blockNumber.sub( startBlock ).div( BLOCK_YEAR.mul( 4 ) ).add( 1 ); - } - - function _perBlockRateFromPeriod( uint period ) internal view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - uint totalDistribute = Punk.balanceOf( address( this ) ).add( totalDistributed ).div( period.mul( 2 ) ); - uint perBlock = totalDistribute.div( BLOCK_YEAR.mul( 4 ) ); - return perBlock; - } - - function getClaimPunk( address to ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - uint reward = 0; - for( uint i = 0 ; i < forges.length ; i++ ){ - reward += getClaimPunk( forges[ i ], to ); - } - return reward; - } - - function getClaimPunk( address forge, address to ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - uint checkPointBlock = checkPointBlocks[ forge ][ to ]; - if( checkPointBlock <= getStartBlock() ){ - checkPointBlock = getStartBlock(); - } - return checkPointBlock > startBlock ? _calcRewards( forge, to, checkPointBlock, block.number ) : 0; - } - - function getWeightSum() public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return weightSum; - } - - function getWeight( address forge ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return weights[ forge ]; - } - - function getTotalDistributed( ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return totalDistributed; - } - - function getDistributed( address forge ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return distributed[ forge ]; - } - - function getAllocation( ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return _perBlockRateFromPeriod( _getPeriodFromBlock( block.number ) ); - } - - function getAllocation( address forge ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return getAllocation( ).mul( weights[ forge ] ).div( weightSum ); - } - - function staked( address forge, address account ) public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return balances[ forge ][ account ]; - } - - function getTotalReward() public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return Punk.balanceOf( address( this ) ).add( totalDistributed ); - } - - function getStartBlock() public view returns( uint ){ - // Hard Work Now! For Punkers by 0xViktor... - return startBlock; - } - -} diff --git a/contracts/PunkRewardPoolProxy.sol b/contracts/PunkRewardPoolProxy.sol deleted file mode 100644 index 1298033..0000000 --- a/contracts/PunkRewardPoolProxy.sol +++ /dev/null @@ -1,95 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -import "@openzeppelin/contracts/utils/Address.sol"; -import "@openzeppelin/contracts/proxy/Proxy.sol"; -import "./OwnableStorage.sol"; - -contract PunkRewardPoolProxy is Proxy{ - - event Upgraded(address indexed implementation); - - bytes32 private constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; - bytes32 private constant _OWNABLE_STORAGE_SLOT = 0x8de9519aeedcea35f7581a1710364953511221d8b7309789ecb15ac4b1a06fc1; - bytes32 private constant _INITIALIZE_SLOT = 0xd1144699b2459fa4c652fe6a4a3ddb7d1dd632f82d755cb1d4bc09b8ef6d4b4f; - - modifier isInitializer(){ - require( getInitialize() != 1, "Initializable: contract is already initialized"); - _; - } - - modifier CheckAdmin(){ - require( OwnableStorage( _storage() ).isAdmin(msg.sender), "OWNABLE: 0x0" ); - _; - } - - function initialize( address implAddress, bytes memory initData, address storage_ ) public isInitializer{ - require(_IMPLEMENTATION_SLOT == bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)); - require(_OWNABLE_STORAGE_SLOT == bytes32(uint256(keccak256("punk.reward.proxy.ownablestrage")) - 1)); - require(_INITIALIZE_SLOT == bytes32(uint256(keccak256("punk.reward.proxy.initialize")) - 1)); - - _setImplementation(implAddress); - _setStorage( storage_ ); - _setInitialize( ); - - if(initData.length > 0) { - Address.functionDelegateCall(implAddress, initData); - } - - } - - function _setStorage( address storage_ ) internal { - bytes32 slot = _OWNABLE_STORAGE_SLOT; - // solhint-disable-next-line no-inline-assembly - assembly { - sstore(slot, storage_) - } - } - - function _storage() internal view returns( address storageAddr ){ - bytes32 slot = _OWNABLE_STORAGE_SLOT; - // solhint-disable-next-line no-inline-assembly - assembly { - storageAddr := sload(slot) - } - } - - function _implementation() internal view override returns (address impl) { - bytes32 slot = _IMPLEMENTATION_SLOT; - // solhint-disable-next-line no-inline-assembly - assembly { - impl := sload(slot) - } - } - - function upgradeTo(address newImplementation) public CheckAdmin { - _setImplementation(newImplementation); - emit Upgraded(newImplementation); - } - - function _setImplementation(address newImplementation) private { - require(Address.isContract(newImplementation), "ERC1967Proxy: new implementation is not a contract"); - - bytes32 slot = _IMPLEMENTATION_SLOT; - - // solhint-disable-next-line no-inline-assembly - assembly { - sstore(slot, newImplementation) - } - } - - function _setInitialize( ) internal { - // solhint-disable-next-line no-inline-assembly - assembly { - sstore(_INITIALIZE_SLOT, 1) - } - } - - function getInitialize( ) private view returns (uint256 str) { - // solhint-disable-next-line no-inline-assembly - assembly { - str := sload( _INITIALIZE_SLOT ) - } - } - -} \ No newline at end of file diff --git a/contracts/RecoveryFund.sol b/contracts/RecoveryFund.sol index 8987a91..698de42 100644 --- a/contracts/RecoveryFund.sol +++ b/contracts/RecoveryFund.sol @@ -1,6 +1,5 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.5.0 <0.9.0; -pragma experimental ABIEncoderV2; import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol"; import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; @@ -22,7 +21,6 @@ contract RecoveryFund is ERC20Pausable, ReentrancyGuard { _initialMint(address(0xe1cd21e5d6f4323E91dA943B0A4F1732acC7a138), 1213998517300000000000000); _initialMint(address(0xf49a12fE6a05bdFc7C0cd4FE2A19724CCFbA18d3), 898535671700000000000000); _initialMint(address(0x82dc92b01c7fF54911842956083795f60f6F64f4), 673946680643589900000000); - _initialMint(address(0x8ed32Ed24303092c016Cdb24d51e153AD88c4875), 89858957570000000000000); _initialMint(address(0xf2CcE4EcB119038dA9F4E18F82E07bb555FbAe2C), 77613054250000000000000); _initialMint(address(0x5522234194F499F1DBF2E26C6eBD802bc2Cd9A2f), 77095278220000000000000); _initialMint(address(0x896b94f4f27f12369698C302e2049cAe86936BbB), 62897497019999995000000); @@ -38,7 +36,7 @@ contract RecoveryFund is ERC20Pausable, ReentrancyGuard { _initialMint(address(0xe9017c8De5040968D9752A18d805cD2A983E558c), 32003782980000000000000); _initialMint(address(0x55d72CbcbA1Ab5C784bC52641D16c613E3b9BAD4), 31755408880000000000000); _initialMint(address(0xf76CF36f638c7bCD83f4756beDb86243D98982F9), 29253624400000000000000); - _initialMint(address(0x29227FB595D091bcA244E76201c0dd50641D96C8), 27239560830000002000000); + _initialMint(address(0x2881Be539cacB7671D32D1f2cdEb50F53F9F19b5), 27239560830000002000000); // 0x29227FB595D091bcA244E76201c0dd50641D96C8 -> 0x2881Be539cacB7671D32D1f2cdEb50F53F9F19b5 _initialMint(address(0x2572a193DA3DEf3BAeA04cB18e06A52186aC1a98), 26954824385000000000000); _initialMint(address(0x81a7E267Fd8339a01beb175f5A3d644FcF0B48Dc), 24234548190999998000000); _initialMint(address(0x67D33CF1C7c699078f86D517A5a1cd1444A1E85C), 23536011086000000000000); @@ -102,24 +100,19 @@ contract RecoveryFund is ERC20Pausable, ReentrancyGuard { _victims.push(account); } - function minRefundAmount() public view returns(uint256){ - return totalSupply().div(balanceOf(address(0x8E1D10aaeF9c0C0D337Aa47022BF0d96D21b56B9))); - } - function refund( uint256 refundAmount ) public nonReentrant returns(bool){ require( IERC20(addressOfDAI).allowance(msg.sender, address(this)) >= refundAmount, "REFUND : allowance is insufficient" ); require( IERC20(addressOfDAI).balanceOf(msg.sender) >= refundAmount, "REFUND : sender's balance is insufficient" ); - require( minRefundAmount() <= refundAmount, "REFUND : refundAmount less than minRefundAmount" ); + require( totalSupply() >= refundAmount, "REFUND : totalSupply must be greater than or equal to refund Amount." ); IERC20 DAI = IERC20(addressOfDAI); uint256 guaranteedSupply = totalSupply(); - uint256 amountToBeSent = refundAmount.sub( refundAmount.mod(minRefundAmount()) ); uint256 amountSent = 0; uint8 i = 0; _unpause(); for (i; i < _victims.length; i++) { - uint value = amountToBeSent.mul( balanceOf(_victims[i]) ).div( guaranteedSupply ); + uint value = refundAmount.mul( balanceOf(_victims[i]) ).div( guaranteedSupply ); require( value > 0, "REFUND : sent value is zero" ); _burn(_victims[i], value); DAI.safeTransferFrom(msg.sender, _victims[i], value); @@ -135,4 +128,4 @@ contract RecoveryFund is ERC20Pausable, ReentrancyGuard { return false; } -} +} \ No newline at end of file diff --git a/contracts/Referral.sol b/contracts/Referral.sol deleted file mode 100644 index e422fed..0000000 --- a/contracts/Referral.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -contract Referral { - - mapping( address=>bytes12 ) private _registers; - mapping( bytes12=>address ) private _referrals; - uint private _count; - - function issue(address account) public returns(bool){ - require( account != address(0x0), "REF : Account is Zero address" ); - require( _registers[account] == 0, "REF : Already Registry" ); - - uint salt = 0; - while( true ){ - bytes12 code = _issueReferralCode(account, salt); - if( _referrals[code] == address(0x0) ){ - _referrals[code] = account; - _registers[account] = code; - break; - } - salt++; - } - _count++; - return true; - } - - function _issueReferralCode( address sender, uint salt ) private pure returns( bytes12 ){ - return bytes12(bytes32(uint(keccak256(abi.encodePacked(sender, salt))))); - } - - function validate( bytes12 code ) public view returns( address ){ - return _referrals[code]; - } - - function referralCode( address account ) public view returns( bytes12 ){ - return _registers[account]; - } - -} \ No newline at end of file diff --git a/contracts/Saver.sol b/contracts/Saver.sol index 3ca8094..9eda5b7 100644 --- a/contracts/Saver.sol +++ b/contracts/Saver.sol @@ -2,22 +2,33 @@ pragma solidity >=0.5.0 <0.9.0; struct Saver{ + // Saver CreateTimestmap uint256 createTimestamp; + + // When do you want to start receiving (unixTime:seconds) uint256 startTimestamp; + + // How often do you want to receive. uint count; + + // Number of times to receive (unit: 1 day) uint interval; + + // Total pLP tokens issued according to the amount deposited. uint256 mint; + + // Total pLP tokens burned for withdrawal. uint256 released; + + // Total amount deposited. (underlying token) uint256 accAmount; + + // Total amount withdrawal. (underlying token) uint256 relAmount; - uint score; + + // Saver's status (WITHDRAW_NOT_YET, NOTHING, ALREADY_WITHDRAWN_OR_IS_TERMINATED, ALL_WITHDRAWN) uint status; - uint updatedTimestamp; - bytes12 ref; -} -struct Transaction{ - bool pos; - uint timestamp; - uint amount; + // Last updated time. + uint updatedTimestamp; } \ No newline at end of file diff --git a/contracts/Treasury.sol b/contracts/Treasury.sol index cdc02c1..ff60e5e 100644 --- a/contracts/Treasury.sol +++ b/contracts/Treasury.sol @@ -10,81 +10,126 @@ import "./Ownable.sol"; contract Treasury is Ownable { using SafeERC20 for IERC20; - mapping( uint256 => address ) private _tokens; + mapping(uint256 => address) private _tokens; + mapping(address => bool) private _exists; uint256 public count; address private _punk; address private _grinder; address private _uRouterV2; - - event Initialize(); - event AddAsset( address token ); - function initialize( address storage_, address grinder_, address punk_, address uRouterV2_ ) public initializer { - Ownable.initialize( storage_ ); + event Initialize( + address storageAddress, + address grinder, + address punk, + address uniswapRouterV2 + ); + event AddAsset(address token); + + function initialize( + address storage_, + address grinder_, + address punk_, + address uRouterV2_ + ) public initializer { + Ownable.initialize(storage_); _grinder = grinder_; _punk = punk_; _uRouterV2 = uRouterV2_; - emit Initialize(); + emit Initialize(storage_, grinder_, punk_, uRouterV2_); } - function addAsset( address token ) public OnlyAdminOrGovernance { - require( IERC20(token).totalSupply() > 0, "TREASURY : token is Invalid" ); - require( !existToken(token), "TREASURY : Already Registry Token" ); + function addAsset(address token) public OnlyAdmin { + require(IERC20(token).totalSupply() > 0, "TREASURY : token is Invalid"); + require(!_exists[token], "TREASURY : Already Registry Token"); _tokens[count] = token; + _exists[token] = true; count++; emit AddAsset(token); } - function buyBack() public OnlyAdminOrGovernance { + function transferToken(address token, address to, uint256 amount) + public + OnlyAdmin + { + require(IERC20(token).balanceOf(address(this)) >= amount, "TREASURY : Balance is Insufficient"); + IERC20(token).safeTransfer(to, amount); + } + + function transferEth(address to, uint256 amount) + public + OnlyAdmin + { + require(address(this).balance >= amount, "TREASURY : Eth Balance is Insufficient"); + require(payable(to).send(amount)); + } + + function buyBack(address[] memory tokens, uint256[] memory amountOutMins) + public + OnlyAdmin + { // Hard Work Now! For Punkers by 0xViktor - for( uint i = 0 ; i < count ; i++ ){ - - uint balance = IERC20( _tokens[ i ] ).balanceOf( address( this ) ); - if( balance > 0 ){ - IERC20( _tokens[ i ] ).safeApprove(address(_uRouterV2), balance); - - address[] memory path = new address[](3); - path[0] = address( _tokens[i] ); - path[1] = IUniswapV2Router(_uRouterV2).WETH(); - path[2] = address( _punk ); - - IUniswapV2Router(_uRouterV2).swapExactTokensForTokens( - balance, - 1, - path, - _grinder, - block.timestamp + ( 15 * 60 ) - ); + require( + tokens.length == amountOutMins.length, + "TREASURY : tokens length not eqauls amoutOutMins" + ); + require( + amountOutMins.length == count, + "TREASURY : amountOutMins invalid" + ); + for (uint256 i = 0; i < tokens.length; i++) { + if (_exists[tokens[i]]) { + uint256 balance = IERC20(tokens[i]).balanceOf(address(this)); + if (balance > 0) { + IERC20(tokens[i]).safeApprove(address(_uRouterV2), balance); + + address[] memory path = new address[](3); + path[0] = address(tokens[i]); + path[1] = IUniswapV2Router(_uRouterV2).WETH(); + path[2] = address(_punk); + + IUniswapV2Router(_uRouterV2).swapExactTokensForTokens( + balance, + amountOutMins[i], + path, + _grinder, + block.timestamp + (15 * 60) + ); + } } } + } + function buyBackEth(uint256 amountOutMinsEth) public OnlyAdmin { + require(amountOutMinsEth > 0, "TREASURY : amountOutMinsEth invalid"); // For SwapEthForToken - if( address(this).balance > 0 ){ + if (address(this).balance > 0) { address[] memory pathForSwapEth = new address[](2); pathForSwapEth[0] = IUniswapV2Router(_uRouterV2).WETH(); - pathForSwapEth[1] = address( _punk ); + pathForSwapEth[1] = address(_punk); - IUniswapV2Router(_uRouterV2).swapExactETHForTokens{value:address(this).balance}( - 1, + IUniswapV2Router(_uRouterV2).swapExactETHForTokens{ + value: address(this).balance + }( + amountOutMinsEth, pathForSwapEth, _grinder, - block.timestamp + ( 15 * 60 ) + block.timestamp + (15 * 60) ); } } - function existToken( address token ) public view returns(bool){ - for( uint i = 0 ; i < count ; i++ ){ - if( _tokens[i] == token ) return true; + function assets() public view returns (address[] memory) { + address[] memory assetsList = new address[](count); + for (uint256 i; i < count; i++) { + assetsList[i] = _tokens[i]; } - return false; + return assetsList; } - fallback () external payable { + fallback() external payable { payable(msg.sender).transfer(msg.value); } - - receive() external payable{} - -} \ No newline at end of file + + receive() external payable {} +} diff --git a/contracts/Variables.sol b/contracts/Variables.sol index a3eae98..8d82952 100644 --- a/contracts/Variables.sol +++ b/contracts/Variables.sol @@ -5,123 +5,81 @@ import "@openzeppelin/contracts/utils/Address.sol"; import "./Ownable.sol"; import "./Saver.sol"; -contract Variables is Ownable{ - - address private _initializer; - - uint256 private _earlyTerminateFee; - uint256 private _buybackRate; +contract Variables is Ownable { + uint256 private _successFee; uint256 private _serviceFee; - uint256 private _discount; - uint256 private _compensation; + uint256 private _feeMultiplier; address private _treasury; - address private _opTreasury; address private _reward; - address private _referral; - - mapping( address => bool ) _emergency; event Initialize(); - function initialize( address storage_) public override initializer{ + function initialize(address storage_) public override initializer { Ownable.initialize(storage_); + _successFee = 20; _serviceFee = 1; - _earlyTerminateFee = 1; - _buybackRate = 20; - _discount = 5; - _compensation = 5; + _feeMultiplier = 200; emit Initialize(); } - function setEarlyTerminateFee( uint256 earlyTerminateFee_ ) public OnlyGovernance { - require( 0 <= earlyTerminateFee_ && earlyTerminateFee_ < 2, "VARIABLES : Fees range from 0 to 2." ); - _earlyTerminateFee = earlyTerminateFee_; + function setSuccessFee(uint256 successFee_) public OnlyAdmin { + require( + 0 <= successFee_ && successFee_ <= 20, + "VARIABLES : SuccessFee range from 0 to 20." + ); + _successFee = successFee_; } - function setBuybackRate( uint256 buybackRate_ ) public OnlyGovernance { - require( 0 <= buybackRate_ && buybackRate_ <= 20, "VARIABLES : BuybackRate range from 0 to 20." ); - _buybackRate = buybackRate_; + + function setServiceFee(uint256 serviceFee_) public OnlyAdmin { + require( + 0 <= serviceFee_ && serviceFee_ <= 2, + "VARIABLES : ServiceFee range from 0 to 2." + ); + _serviceFee = serviceFee_; } - function setEmergency( address forge, bool emergency ) public OnlyAdmin { - _emergency[ forge ] = emergency; + function setFeeMultiplier(uint256 feeMultiplier_) public OnlyAdmin { + require( + 100 <= feeMultiplier_ && feeMultiplier_ <= 200, + "VARIABLES : feeMultiplier range from 100 to 200." + ); + _feeMultiplier = feeMultiplier_; } - function setTreasury( address treasury_ ) public OnlyAdmin { - require(Address.isContract(treasury_), "VARIABLES : must be the contract address."); + function setTreasury(address treasury_) public OnlyAdmin { + require( + Address.isContract(treasury_), + "VARIABLES : must be the contract address." + ); _treasury = treasury_; } - function setReward( address reward_ ) public OnlyAdmin { - require(Address.isContract(reward_), "VARIABLES : must be the contract address."); + function setReward(address reward_) public OnlyAdmin { + require( + Address.isContract(reward_), + "VARIABLES : must be the contract address." + ); _reward = reward_; } - function setOpTreasury( address opTreasury_ ) public OnlyAdmin { - require(Address.isContract(opTreasury_), "VARIABLES : must be the contract address."); - _opTreasury = opTreasury_; - } - - function setReferral( address referral_ ) public OnlyAdmin { - require(Address.isContract(referral_), "VARIABLES : must be the contract address."); - _referral = referral_; - } - - function setServiceFee( uint256 serviceFee_ ) public OnlyGovernance { - require( 0 <= serviceFee_ && serviceFee_ <= 2, "VARIABLES : ServiceFees range from 0 to 2." ); - _serviceFee = serviceFee_; - } - - function setDiscount( uint256 discount_ ) public OnlyAdmin { - require( discount_ + _compensation <= 100, "VARIABLES : discount + compensation <= 100" ); - _discount = discount_; - } - - function setCompensation( uint256 compensation_ ) public OnlyAdmin { - require( _discount + compensation_ <= 100, "VARIABLES : discount + compensation <= 100" ); - _compensation = compensation_; - } - - function earlyTerminateFee( ) public view returns( uint256 ){ - return _earlyTerminateFee; + function successFee() public view returns (uint256) { + return _successFee; } - function earlyTerminateFee( address forge ) public view returns( uint256 ){ - return isEmergency( forge ) ? 0 : _earlyTerminateFee; + function serviceFee() public view returns (uint256) { + return _serviceFee; } - function buybackRate() public view returns( uint256 ){ return _buybackRate; } - - function isEmergency( address forge ) public view returns( bool ){ - return _emergency[ forge ]; + function feeMultiplier() public view returns (uint256) { + return _feeMultiplier; } - function treasury() public view returns( address ){ + function treasury() public view returns (address) { return _treasury; } - function reward() public view returns( address ){ + function reward() public view returns (address) { return _reward; } - - function opTreasury() public view returns( address ){ - return _opTreasury; - } - - function referral() public view returns( address ){ - return _referral; - } - - function serviceFee() public view returns( uint256 ){ - return _serviceFee; - } - - function discount() public view returns( uint256 ){ - return _discount; - } - - function compensation() public view returns( uint256 ){ - return _compensation; - } - } diff --git a/contracts/governance/Timelock.sol b/contracts/governance/Timelock.sol new file mode 100644 index 0000000..f06b206 --- /dev/null +++ b/contracts/governance/Timelock.sol @@ -0,0 +1,136 @@ +// SPDX-License-Identifier: MIT + +// COPIED FROM https://github.com/compound-finance/compound-protocol/blob/master/contracts/Governance/GovernorAlpha.sol +// Copyright 2020 Compound Labs, Inc. +// Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: +// 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. +// 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. +// 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. +// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +// Ctrl+f for MOD to see all the modifications. + +// MOD: pragma solidity ^0.5.16; +pragma solidity >=0.5.0 <0.9.0; + +// MOD: import "./SafeMath.sol"; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; + +contract Timelock { + using SafeMath for uint; + + event NewAdmin(address indexed newAdmin); + event NewPendingAdmin(address indexed newPendingAdmin); + event NewDelay(uint indexed newDelay); + event CancelTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + event ExecuteTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + event QueueTransaction(bytes32 indexed txHash, address indexed target, uint value, string signature, bytes data, uint eta); + + uint public constant GRACE_PERIOD = 14 days; + uint public constant MINIMUM_DELAY = 6 hours; + uint public constant MAXIMUM_DELAY = 30 days; + + address public admin; + address public pendingAdmin; + uint public delay; + bool public admin_initialized; + + mapping (bytes32 => bool) public queuedTransactions; + + + // MOD: constructor(address admin_, uint delay_) public { + constructor(address admin_, uint delay_) { + require(delay_ >= MINIMUM_DELAY, "Timelock::constructor: Delay must exceed minimum delay."); + require(delay_ <= MAXIMUM_DELAY, "Timelock::constructor: Delay must not exceed maximum delay."); + + admin = admin_; + delay = delay_; + admin_initialized = false; + } + + // MOD: function() external payable { } + receive() external payable { } + + function setDelay(uint delay_) public { + require(msg.sender == address(this), "Timelock::setDelay: Call must come from Timelock."); + require(delay_ >= MINIMUM_DELAY, "Timelock::setDelay: Delay must exceed minimum delay."); + require(delay_ <= MAXIMUM_DELAY, "Timelock::setDelay: Delay must not exceed maximum delay."); + delay = delay_; + + emit NewDelay(delay); + } + + function acceptAdmin() public { + require(msg.sender == pendingAdmin, "Timelock::acceptAdmin: Call must come from pendingAdmin."); + admin = msg.sender; + pendingAdmin = address(0); + + emit NewAdmin(admin); + } + + function setPendingAdmin(address pendingAdmin_) public { + // allows one time setting of admin for deployment purposes + if (admin_initialized) { + require(msg.sender == address(this), "Timelock::setPendingAdmin: Call must come from Timelock."); + } else { + require(msg.sender == admin, "Timelock::setPendingAdmin: First call must come from admin."); + admin_initialized = true; + } + pendingAdmin = pendingAdmin_; + + emit NewPendingAdmin(pendingAdmin); + } + + function queueTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public returns (bytes32) { + require(msg.sender == admin, "Timelock::queueTransaction: Call must come from admin."); + require(eta >= getBlockTimestamp().add(delay), "Timelock::queueTransaction: Estimated execution block must satisfy delay."); + + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + queuedTransactions[txHash] = true; + + emit QueueTransaction(txHash, target, value, signature, data, eta); + return txHash; + } + + function cancelTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public { + require(msg.sender == admin, "Timelock::cancelTransaction: Call must come from admin."); + + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + queuedTransactions[txHash] = false; + + emit CancelTransaction(txHash, target, value, signature, data, eta); + } + + function executeTransaction(address target, uint value, string memory signature, bytes memory data, uint eta) public payable returns (bytes memory) { + require(msg.sender == admin, "Timelock::executeTransaction: Call must come from admin."); + + bytes32 txHash = keccak256(abi.encode(target, value, signature, data, eta)); + require(queuedTransactions[txHash], "Timelock::executeTransaction: Transaction hasn't been queued."); + require(getBlockTimestamp() >= eta, "Timelock::executeTransaction: Transaction hasn't surpassed time lock."); + require(getBlockTimestamp() <= eta.add(GRACE_PERIOD), "Timelock::executeTransaction: Transaction is stale."); + + queuedTransactions[txHash] = false; + + bytes memory callData; + + if (bytes(signature).length == 0) { + callData = data; + } else { + callData = abi.encodePacked(bytes4(keccak256(bytes(signature))), data); + } + + // solium-disable-next-line security/no-call-value + // MOD: (bool success, bytes memory returnData) = target.call.value(value)(callData); + (bool success, bytes memory returnData) = target.call{value:value}(callData); + require(success, "Timelock::executeTransaction: Transaction execution reverted."); + + emit ExecuteTransaction(txHash, target, value, signature, data, eta); + + return returnData; + } + + function getBlockTimestamp() internal view returns (uint) { + // solium-disable-next-line security/no-block-members + return block.timestamp; + } +} \ No newline at end of file diff --git a/contracts/interfaces/ForgeEthInterface.sol b/contracts/interfaces/ForgeEthInterface.sol deleted file mode 100644 index 3a15c53..0000000 --- a/contracts/interfaces/ForgeEthInterface.sol +++ /dev/null @@ -1,36 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../Saver.sol"; - -interface ForgeEthInterface{ - - event CraftingSaver ( address owner, uint index, uint deposit ); - event AddDeposit ( address owner, uint index, uint deposit ); - event Withdraw ( address owner, uint index, uint amount ); - event Terminate ( address owner, uint index, uint amount ); - event Bonus ( address owner, uint index, uint amount ); - event SetModel ( address from, address to ); - - function modelAddress() external view returns (address); - - function withdrawable( address account, uint index ) external view returns(uint); - function countByAccount( address account ) external view returns (uint); - - function craftingSaver( uint startTimestamp, uint count, uint interval ) external payable returns(bool); - function craftingSaver( uint startTimestamp, uint count, uint interval, bytes12 referral ) external payable returns(bool); - function addDeposit( uint index ) external payable returns(bool); - function withdraw( uint index, uint amount ) external returns(bool); - function terminateSaver( uint index ) external returns(bool); - - function countAll() external view returns(uint); - function saver( address account, uint index ) external view returns( Saver memory ); - function transactions( address account, uint index ) external view returns ( Transaction [] memory ); - - function totalScore() external view returns(uint256); - function getExchangeRate() external view returns( uint ); - function getBonus() external view returns( uint ); - function getTotalVolume( ) external view returns( uint ); - -} \ No newline at end of file diff --git a/contracts/interfaces/ForgeInterface.sol b/contracts/interfaces/ForgeInterface.sol index 1fcac9a..5a62d4f 100644 --- a/contracts/interfaces/ForgeInterface.sol +++ b/contracts/interfaces/ForgeInterface.sol @@ -6,32 +6,29 @@ import "../Saver.sol"; interface ForgeInterface{ - event Initialize(); + event Initialize( address storageAddress, address variables, address model, address token, string name, string symbol ); event CraftingSaver ( address owner, uint index, uint deposit ); event AddDeposit ( address owner, uint index, uint deposit ); event Withdraw ( address owner, uint index, uint amount ); event Terminate ( address owner, uint index, uint amount ); - event Bonus ( address owner, uint index, uint amount ); - event SetModel ( address from, address to ); + event UpgradeModel ( address from, address to, uint upgradeTimestamp ); function modelAddress() external view returns (address); + function upgradeModel(address model_) external returns(bool); function withdrawable( address account, uint index ) external view returns(uint); function countByAccount( address account ) external view returns (uint); function craftingSaver( uint amount, uint startTimestamp, uint count, uint interval ) external returns(bool); - function craftingSaver( uint amount, uint startTimestamp, uint count, uint interval, bytes12 referral ) external returns(bool); function addDeposit( uint index, uint amount ) external returns(bool); - function withdraw( uint index, uint amount ) external returns(bool); + function withdrawUnderlying( uint index, uint hopeUnderlying ) external returns(bool); + function withdraw( uint index, uint hope ) external returns(bool); function terminateSaver( uint index ) external returns(bool); function countAll() external view returns(uint); function saver( address account, uint index ) external view returns( Saver memory ); - function transactions( address account, uint index ) external view returns ( Transaction [] memory ); - function totalScore() external view returns(uint256); - function getExchangeRate() external view returns( uint ); - function getBonus() external view returns( uint ); - function getTotalVolume( ) external view returns( uint ); + function exchangeRate() external view returns( uint ); + function totalVolume( ) external view returns( uint ); } \ No newline at end of file diff --git a/contracts/interfaces/ModelInterface.sol b/contracts/interfaces/ModelInterface.sol index b5131c6..da7bcad 100644 --- a/contracts/interfaces/ModelInterface.sol +++ b/contracts/interfaces/ModelInterface.sol @@ -41,13 +41,8 @@ interface ModelInterface{ */ function withdrawToForge( uint256 amount ) external; - /** - * @dev After withdrawing 'amount', send it to 'to'. - * - * IMPORTANT: Must use the "OnlyForge" Modifier from "ModelStorage.sol". - * - * Emits a {Withdraw} event. - */ - function withdrawTo( uint256 amount, address to ) external; + function forge() external view returns( address ); + + function token() external view returns( address ); } diff --git a/contracts/interfaces/ReferralInterface.sol b/contracts/interfaces/ReferralInterface.sol deleted file mode 100644 index 0b48a18..0000000 --- a/contracts/interfaces/ReferralInterface.sol +++ /dev/null @@ -1,7 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -interface ReferralInterface{ - function validate( bytes12 code ) external view returns( address ); - function referralCode( address account ) external view returns( bytes12 ); -} \ No newline at end of file diff --git a/contracts/libs/CommitmentWeight.sol b/contracts/libs/CommitmentWeight.sol deleted file mode 100644 index 1f1336f..0000000 --- a/contracts/libs/CommitmentWeight.sol +++ /dev/null @@ -1,40 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; - -library CommitmentWeight { - - uint constant DECIMALS = 8; - int constant ONE = int(10**DECIMALS); - - function calculate( uint day ) external pure returns (uint){ - int x = int(day) * ONE; - int c = 3650 * ONE; - - int numerator = div( div( x, c ) - ONE, sqrt( ( div( pow( x, 2 ), 13322500 * ONE ) - div( x, 1825 * ONE ) + ONE + ONE ) ) ) + div( ONE, sqrt( 2 * ONE ) ); - int denominator = ( ONE + div( ONE, sqrt( 2 * ONE ) ) ); - - return uint( ONE + div( numerator, denominator ) ); - } - - function div( int a, int b ) internal pure returns ( int ){ - return ( a * int(ONE) / b ); - } - - function sqrt( int a ) internal pure returns ( int ){ - int s = a * int(ONE); - if( s < 0 ) s = s * -1; - uint k = uint(s); - uint z = (k + 1) / 2; - uint y = k; - while (z < y) { - y = z; - z = (k / z + z) / 2; - } - return int(y); - } - - function pow( int a, int b ) internal pure returns ( int ){ - return int(uint(a) ** uint(b) / uint(ONE)); - } - -} \ No newline at end of file diff --git a/contracts/libs/Score.sol b/contracts/libs/Score.sol deleted file mode 100644 index c3e22e3..0000000 --- a/contracts/libs/Score.sol +++ /dev/null @@ -1,101 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; -import "./CommitmentWeight.sol"; -import "../Saver.sol"; - -library Score { - using SafeMath for uint; - - uint constant SECONDS_OF_DAY = 24 * 60 * 60; - - function _getTimes( uint createTimestamp, uint startTimestamp, uint count, uint interval ) pure private returns( uint deposit, uint withdraw, uint timeline, uint max ){ - deposit = startTimestamp.sub( createTimestamp ); - withdraw = SECONDS_OF_DAY.mul( count ).mul( interval ); - timeline = deposit + withdraw; - max = SECONDS_OF_DAY.mul( 365 ).mul( 30 ); - } - - function _getDepositTransactions( uint createTimestamp, uint deposit, Transaction [] memory transactions ) private pure returns( uint depositCount, uint [] memory xAxis, uint [] memory yAxis ){ - depositCount = 0; - yAxis = new uint [] ( transactions.length ); - xAxis = new uint [] ( transactions.length + 1 ); - - for( uint i = 0 ; i < transactions.length ; i++ ){ - if( transactions[i].pos ) { - yAxis[ depositCount ] = i == 0 ? transactions[ i ].amount : transactions[ i ].amount.add( yAxis[ i - 1 ] ); - xAxis[ depositCount ] = transactions[ i ].timestamp.sub( createTimestamp ); - depositCount++; - } - } - xAxis[ depositCount ] = deposit; - - uint tempX = 0; - for( uint i = 1 ; i <= depositCount ; i++ ){ - tempX = tempX + xAxis[ i - 1 ]; - xAxis[ i ] = xAxis[ i ].sub( tempX ); - } - } - - function calculate( uint createTimestamp, uint startTimestamp, Transaction [] memory transactions, uint count, uint interval, uint decimals ) public pure returns ( uint ){ - - ( uint deposit, uint withdraw, uint timeline, uint max ) = _getTimes(createTimestamp, startTimestamp, count, interval); - ( uint depositCount, uint [] memory xAxis, uint [] memory yAxis ) = _getDepositTransactions( createTimestamp, deposit, transactions ); - - uint cw = CommitmentWeight.calculate( timeline.div( SECONDS_OF_DAY ) ); - - if( max <= deposit ){ - - uint accX = 0; - for( uint i = 0 ; i < depositCount ; i++ ){ - accX = accX.add( xAxis[ i + 1 ] ); - if( accX > max ){ - xAxis[ i + 1 ] = max.sub( accX.sub( xAxis[ i + 1 ] ) ); - depositCount = i + 1; - break; - } - } - - uint beforeWithdraw = 0; - for( uint i = 0 ; i < depositCount ; i++ ){ - beforeWithdraw = beforeWithdraw.add( yAxis[ i ].mul( xAxis[ i + 1 ] ) ); - } - - uint afterWithdraw = 0; - - return beforeWithdraw.add( afterWithdraw ).div( SECONDS_OF_DAY ).mul( cw ).div( 10 ** decimals ); - - }else if( max <= timeline ){ - - uint beforeWithdraw = 0; - for( uint i = 0 ; i < depositCount ; i++ ){ - beforeWithdraw = beforeWithdraw.add( yAxis[ i ].mul( xAxis[ i + 1 ] ) ); - } - - uint afterWithdraw = 0; - if( withdraw > 0 ){ - uint tempY = yAxis[ depositCount - 1 ].mul( timeline.sub( max ) ).div( withdraw ); - afterWithdraw = yAxis[ depositCount - 1 ].mul( withdraw ).div( 2 ); - afterWithdraw = afterWithdraw.sub( tempY.mul( timeline.sub( max ) ).div( 2 ) ); - } - - return beforeWithdraw.add( afterWithdraw ).div( SECONDS_OF_DAY ).mul( cw ).div( 10 ** decimals ); - - }else { - - uint beforeWithdraw = 0; - for( uint i = 0 ; i < depositCount ; i++ ){ - beforeWithdraw = beforeWithdraw.add( yAxis[ i ].mul( xAxis[ i + 1 ] ) ); - } - - uint afterWithdraw = yAxis[ depositCount - 1 ].mul( withdraw ).div( 2 ); - - return beforeWithdraw.add( afterWithdraw ).div( SECONDS_OF_DAY ).mul( cw ).div( 10 ** decimals ); - - } - - } - -} diff --git a/contracts/3rdDeFiInterfaces/IUniswapV2Factory.sol b/contracts/mock/IUniswapV2FactoryMock.sol similarity index 95% rename from contracts/3rdDeFiInterfaces/IUniswapV2Factory.sol rename to contracts/mock/IUniswapV2FactoryMock.sol index eec69eb..fef21be 100644 --- a/contracts/3rdDeFiInterfaces/IUniswapV2Factory.sol +++ b/contracts/mock/IUniswapV2FactoryMock.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity >=0.5.0; -interface IUniswapV2Factory { +interface IUniswapV2FactoryMock { event PairCreated(address indexed token0, address indexed token1, address pair, uint); function feeTo() external view returns (address); diff --git a/contracts/mock/RecoveryFundMock.sol b/contracts/mock/RecoveryFundMock.sol deleted file mode 100644 index 1f3dd36..0000000 --- a/contracts/mock/RecoveryFundMock.sol +++ /dev/null @@ -1,11 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; -import "../RecoveryFund.sol"; - -contract RecoveryFundMock is RecoveryFund { - using SafeERC20 for IERC20; - constructor() RecoveryFund() {} -} diff --git a/contracts/mock/ScoreMock.sol b/contracts/mock/ScoreMock.sol deleted file mode 100644 index f6d0fa9..0000000 --- a/contracts/mock/ScoreMock.sol +++ /dev/null @@ -1,23 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity >=0.5.0 <0.9.0; -pragma experimental ABIEncoderV2; - -import "../libs/Score.sol"; -import "../Saver.sol"; - -contract ScoreMock { - constructor() { - - } - - function scoreCalculation( - uint createTimestamp, - uint startTimestamp, - Transaction [] memory transactions, - uint count, - uint interval, - uint decimals - ) external pure returns (uint score) { - score = Score.calculate(createTimestamp, startTimestamp, transactions, count, interval, decimals); - } -} \ No newline at end of file diff --git a/contracts/models/CompoundModel.sol b/contracts/models/CompoundModel.sol index 9e6ec81..635657e 100644 --- a/contracts/models/CompoundModel.sol +++ b/contracts/models/CompoundModel.sol @@ -17,7 +17,7 @@ contract CompoundModel is ModelInterface, ModelStorage, Initializable{ using SafeMath for uint; event Swap( uint compAmount, uint underlying ); - event Initialize(); + event Initialize( address forge, address model ); address creator; @@ -43,18 +43,18 @@ contract CompoundModel is ModelInterface, ModelStorage, Initializable{ address comptroller_, address uRouterV2_ ) public initializer onlyCreator { - addToken( token_ ); + setToken( token_ ); setForge( forge_ ); _cToken = cToken_; _comp = comp_; _comptroller = comptroller_; _uRouterV2 = uRouterV2_; - emit Initialize(); + emit Initialize( forge_, address(this) ); } function underlyingBalanceInModel() public override view returns ( uint256 ){ - return IERC20( token( 0 ) ).balanceOf( address( this ) ); + return IERC20( token() ).balanceOf( address( this ) ); } function underlyingBalanceWithInvestment() public override view returns ( uint256 ){ @@ -64,7 +64,7 @@ contract CompoundModel is ModelInterface, ModelStorage, Initializable{ function invest() public override { // Hard Work Now! For Punkers by 0xViktor - IERC20( token( 0 ) ).safeApprove( _cToken, underlyingBalanceInModel() ); + IERC20( token() ).safeApprove( _cToken, underlyingBalanceInModel() ); emit Invest( underlyingBalanceInModel(), block.timestamp ); CTokenInterface( _cToken ).mint( underlyingBalanceInModel() ); } @@ -86,17 +86,8 @@ contract CompoundModel is ModelInterface, ModelStorage, Initializable{ } function withdrawToForge( uint256 amount ) public OnlyForge override{ - withdrawTo( amount, forge() ); - } - - function withdrawTo( uint256 amount, address to ) public OnlyForge override{ - // Hard Work Now! For Punkers by 0xViktor - uint oldBalance = IERC20( token(0) ).balanceOf( address( this ) ); CTokenInterface( _cToken ).redeemUnderlying( amount ); - uint newBalance = IERC20( token(0) ).balanceOf( address( this ) ); - require(newBalance.sub( oldBalance ) > 0, "MODEL : REDEEM BALANCE IS ZERO"); - IERC20( token( 0 ) ).safeTransfer( to, newBalance.sub( oldBalance ) ); - + IERC20( token() ).safeTransfer( forge(), amount ); emit Withdraw( amount, forge(), block.timestamp); } @@ -119,7 +110,7 @@ contract CompoundModel is ModelInterface, ModelStorage, Initializable{ address[] memory path = new address[](3); path[0] = address(_comp); path[1] = IUniswapV2Router( _uRouterV2 ).WETH(); - path[2] = address( token( 0 ) ); + path[2] = address( token() ); IUniswapV2Router(_uRouterV2).swapExactTokensForTokens( balance, diff --git a/test/shared/errors.ts b/test/shared/errors.ts index 93ca986..da4d63c 100644 --- a/test/shared/errors.ts +++ b/test/shared/errors.ts @@ -1,3 +1,2 @@ export enum ForgeErrors { - NotContract = "function call to a non-contract account", } \ No newline at end of file diff --git a/test/shared/fixtures.ts b/test/shared/fixtures.ts index 97a3e6b..4016a15 100644 --- a/test/shared/fixtures.ts +++ b/test/shared/fixtures.ts @@ -1,8 +1,8 @@ -import { Signer } from "@ethersproject/abstract-signer" import { Contract, Wallet } from "ethers"; -import { artifacts, ethers, waffle } from "hardhat" +import { artifacts, ethers } from "hardhat" import { Tokens, UniswapAddresses } from "./mockInfo"; +let timelock:Contract let storage:Contract let punkMock:Contract @@ -14,53 +14,30 @@ export async function unitPunkMockFixtures([,,,,,owner] : Wallet[]): Promise { - const CommitmentWeight = await ethers.getContractFactory("CommitmentWeight") - const commietmentWeight = await CommitmentWeight.deploy() - await commietmentWeight.deployed() - - const Score = await ethers.getContractFactory("Score", { - libraries: { - CommitmentWeight: commietmentWeight.address - } - }); - const score = await Score.deploy() - await score.deployed(); - - return score +export async function unitFixtureTimelock([,,,,,owner] : Wallet[]): Promise { + const Timelock = await ethers.getContractFactory("Timelock"); + const _timelock = await Timelock.connect(owner).deploy( owner.address, 172800) + await _timelock.deployed() + timelock = _timelock + return timelock } export async function unitFixtureForge(): Promise { - const score = await libraryFixtures(); - const Forge = await ethers.getContractFactory("Forge", { - libraries: { - Score: score.address, - } - }); + const Forge = await ethers.getContractFactory("Forge"); const forge = await Forge.deploy() await forge.deployed(); return forge; } export async function unitFixtureForge2nd(): Promise { - const score = await libraryFixtures(); - const Forge = await ethers.getContractFactory("Forge", { - libraries: { - Score: score.address, - } - }); + const Forge = await ethers.getContractFactory("Forge"); const forge = await Forge.deploy() await forge.deployed(); return forge; } export async function unitFixtureForge3rd(): Promise { - const score = await libraryFixtures(); - const Forge = await ethers.getContractFactory("Forge", { - libraries: { - Score: score.address, - } - }); + const Forge = await ethers.getContractFactory("Forge"); const forge = await Forge.deploy() await forge.deployed(); return forge; @@ -81,57 +58,39 @@ export async function unitFixtureCompoundModel(): Promise { return compoundModel } +export async function unitFixtureCompoundModelToReplaced(): Promise { + const CompoundModel = await ethers.getContractFactory("CompoundModel") + const compoundModel = await CompoundModel.deploy() + await compoundModel.deployed() + return compoundModel +} + export async function unitFixtureUniswapV2(): Promise { const IUniswapV2Router = await artifacts.readArtifact("IUniswapV2Router"); const uniswapRouter = await ethers.getContractAt(IUniswapV2Router.abi, UniswapAddresses.UniswapV2Router02); return uniswapRouter } -export async function unitFixtureUniswapFactoryV2(): Promise { - const IUniswapV2Factory = await artifacts.readArtifact("IUniswapV2Factory"); - const uniswapFactory = await ethers.getContractAt(IUniswapV2Factory.abi, UniswapAddresses.UniswapFactoryV2); - return uniswapFactory -} - export async function unitFixtureDaiToken(): Promise { const IDaiToken = await artifacts.readArtifact("IERC20") const daiToken = await ethers.getContractAt(IDaiToken.abi, Tokens.Dai) return daiToken } -export async function unitFixtureRecoveryFund(): Promise { - const RecoveryFundMock = await ethers.getContractFactory("RecoveryFundMock") - const recoveryFundMock = await RecoveryFundMock.deploy() +export async function unitFixtureRecoveryFund([,,,,,owner] : Wallet[]): Promise { + const RecoveryFundMock = await ethers.getContractFactory("RecoveryFund") + const recoveryFundMock = await RecoveryFundMock.connect(owner).deploy() return recoveryFundMock } export async function unitFixtureOwnableStorage([,,,,,owner] : Wallet[]): Promise { const OwnableStorage = await ethers.getContractFactory("OwnableStorage") - const ownableStorage = await OwnableStorage.connect(owner).deploy() + const ownableStorage = await OwnableStorage.connect(owner).deploy(timelock.address) await ownableStorage.deployed() storage = ownableStorage; return ownableStorage } -export async function unitFixtureScoreMock(): Promise { - const score = await libraryFixtures(); - const ScoreMock = await ethers.getContractFactory("ScoreMock", { - libraries: { - Score: score.address, - } - }); - const scoreMock = await ScoreMock.deploy() - - return scoreMock -} - -export async function unitFixtureReferral(): Promise { - const Referral = await ethers.getContractFactory("Referral") - const referral = await Referral.deploy() - await referral.deployed() - return referral; -} - export async function unitFixtureTreasury(): Promise { const Treasury = await ethers.getContractFactory("Treasury") const treasury = await Treasury.deploy() @@ -153,16 +112,15 @@ export async function unitFixtureGrinder(): Promise { return grinder; } -export async function unitFixturePunkRewardPool(): Promise { - const PunkRewardPool = await ethers.getContractFactory("PunkRewardPool") - const punkRewardPool = await PunkRewardPool.deploy() - await punkRewardPool.deployed() - return punkRewardPool; -} - export async function unitFixtureFairLaunch(): Promise { const FairLaunch = await ethers.getContractFactory("FairLaunch") const fairLaunch = await FairLaunch.deploy() await fairLaunch.deployed() return fairLaunch; } + +export async function unitFixtureUniswapFactoryV2(): Promise { + const IUniswapV2Factory = await artifacts.readArtifact("IUniswapV2FactoryMock"); + const uniswapFactory = await ethers.getContractAt(IUniswapV2Factory.abi, UniswapAddresses.UniswapFactoryV2); + return uniswapFactory +} \ No newline at end of file diff --git a/test/shared/utils.ts b/test/shared/utils.ts index c752e46..f21fd1a 100644 --- a/test/shared/utils.ts +++ b/test/shared/utils.ts @@ -1,5 +1,10 @@ +import { ParamType } from "@ethersproject/abi"; import { ethers } from "hardhat"; export function ethToWei(amount: string): string { return ethers.BigNumber.from(ethers.utils.parseEther(amount).toString()).toString() +} + +export function abiEncode( types: ReadonlyArray, values: ReadonlyArray ):string{ + return ethers.utils.defaultAbiCoder.encode(types, values) } \ No newline at end of file diff --git a/test/unit/CompoundModel/initialize.behavior.ts b/test/unit/CompoundModel/initialize.behavior.ts index 1b5dbba..f517c29 100644 --- a/test/unit/CompoundModel/initialize.behavior.ts +++ b/test/unit/CompoundModel/initialize.behavior.ts @@ -4,8 +4,9 @@ import { Tokens, CompoundAddresses, UniswapAddresses } from "../../shared/mockIn export function initialBehavior(): void { context("Initailize", function() { - it('should Success initialize', async function() { + it('should Success initialize 1', async function() { const compoundModel = this.contracts.compoundModel + await expect(compoundModel.initialize( this.contracts.forge.address, Tokens.Dai, @@ -16,6 +17,18 @@ export function initialBehavior(): void { )).emit( compoundModel, "Initialize" ) }) + it('should Success initialize 2', async function() { + const compoundModelToReplaced = this.contracts.compoundModelToReplaced + await expect(compoundModelToReplaced.initialize( + this.contracts.forge.address, + Tokens.Dai, + CompoundAddresses.cDai, + CompoundAddresses.COMP, + CompoundAddresses.Comptroller, + UniswapAddresses.UniswapV2Router02 + )).emit( compoundModelToReplaced, "Initialize" ) + }) + it('should revert Already initialized', async function() { const compoundModel = this.contracts.compoundModel await expect(compoundModel.initialize( diff --git a/test/unit/CompoundModel/setup.behavior.ts b/test/unit/CompoundModel/setup.behavior.ts index 48f25c8..2de1c81 100644 --- a/test/unit/CompoundModel/setup.behavior.ts +++ b/test/unit/CompoundModel/setup.behavior.ts @@ -1,43 +1,8 @@ import { expect } from "chai"; -import { ethers } from "hardhat"; -import { Tokens, CompoundAddresses } from "../../shared/mockInfo"; -import { ethToWei } from "../../shared/utils"; export function setUpBehavior(): void { context("SetUp", function() { - it('should Success transfer and invest', async function() { - // const compoundModel = this.contracts.compoundModel - - // const daiContract = this.contracts.daiContract - // const uniswapV2Router = this.contracts.uniswapV2Router - // const accountDai = this.signers.accountDai - - // const blockNumber = await ethers.provider.getBlockNumber() - // const blockInfo = await ethers.provider.getBlock(blockNumber) - - // const swapResult = await uniswapV2Router.connect(accountDai).swapExactETHForTokens( - // ethToWei("10"), - // [Tokens.WETH, Tokens.Dai], - // accountDai.address, - // blockInfo.timestamp + 25*60*60, - // {value: ethToWei("10"), gasLimit: '1300000'} - // ) - // await swapResult.wait() - - // console.log( "balanceOf", ( await daiContract.balanceOf( accountDai.address ) ).toString() ) - // await expect( compoundModel.withdrawTo( forge.address, 100 ) ).to.be.reverted - - // const CDAI = await ethers.getContractAt("CTokenInterface", CompoundAddresses.cDai ); - // console.log("CDAI", CDAI) - }) - - it('should Revert withdrawTo', async function() { - const compoundModel = this.contracts.compoundModel - const forge = this.contracts.forge - await expect( compoundModel.withdrawTo( forge.address, 100 ) ).to.be.reverted - }) - it('should Revert withdrawToForge', async function() { const compoundModel = this.contracts.compoundModel await expect( compoundModel.withdrawToForge( 100 ) ).to.be.reverted diff --git a/test/unit/Forge/initialize.behavior.ts b/test/unit/Forge/initialize.behavior.ts index d407f7c..c56e026 100644 --- a/test/unit/Forge/initialize.behavior.ts +++ b/test/unit/Forge/initialize.behavior.ts @@ -1,5 +1,8 @@ import { Tokens } from "../../shared/mockInfo" import { expect } from "chai"; +import { ethers, network } from "hardhat"; +import { keccak256 } from "@ethersproject/keccak256"; +import { abiEncode } from "../../shared/utils"; export function initialBehavior(): void { context("Initailize", function() { @@ -24,18 +27,126 @@ export function initialBehavior(): void { it('should Revert Forge Initialize', async function() { const ownableStorage = this.contracts.ownableStorage; const variables = this.contracts.variables; - const compoundModel = this.contracts.compoundModel; await expect(this.contracts.forge.connect(this.signers.owner).initializeForge( ownableStorage.address, variables.address, "Punk-Forge-DAI-0", "pDAI", - compoundModel.address, Tokens.Dai, 18 )).to.be.reverted }) + it('should Revert Forge upgradeModel Not Admin', async function() { + const forge = this.contracts.forge; + const compoundModel = this.contracts.compoundModel; + const account = this.signers.account1; + await expect(forge.connect(account).upgradeModel(compoundModel.address)).to.be.reverted + }) + + let eta = 0; + it('should Revert Forge upgradeModel address zero', async function() { + const forge = this.contracts.forge; + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber() + const blockInfo = await ethers.provider.getBlock(blockNumber) + eta = blockInfo.timestamp + 49 * 60 * 60 + + const data = abiEncode(['address'],["0x0000000000000000000000000000000000000000"] ); + const txHash = keccak256(abiEncode( ['address', 'uint', 'string', 'bytes', 'uint'], [forge.address, 0, "upgradeModel(address)", data, eta] )) + + await timelock.queueTransaction( + forge.address, + 0, + "upgradeModel(address)", + data, + eta + ) + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true) + + await network.provider.send("evm_increaseTime", [49*60*60]); + await network.provider.send("evm_mine") + + await expect(timelock.executeTransaction( + forge.address, + 0, + "upgradeModel(address)", + data, + eta + )).to.be.reverted + }) + + it('should Revert Forge setModel address EOA', async function() { + const account = this.signers.owner; + + const forge = this.contracts.forge; + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber() + const blockInfo = await ethers.provider.getBlock(blockNumber) + eta = blockInfo.timestamp + 49 * 60 * 60 + + const data = abiEncode(['address'],[account.address] ); + const txHash = keccak256(abiEncode( ['address', 'uint', 'string', 'bytes', 'uint'], [forge.address, 0, "upgradeModel(address)", data, eta] )) + + await timelock.queueTransaction( + forge.address, + 0, + "upgradeModel(address)", + data, + eta + ) + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true) + + await network.provider.send("evm_increaseTime", [49*60*60]); + await network.provider.send("evm_mine") + + await expect(timelock.executeTransaction( + forge.address, + 0, + "upgradeModel(address)", + data, + eta + )).to.be.reverted + }) + + it('should Success Forge setModel', async function() { + const model = this.contracts.compoundModelToReplaced; + const forge = this.contracts.forge; + const timelock = this.contracts.timelock; + + const blockNumber = await ethers.provider.getBlockNumber() + const blockInfo = await ethers.provider.getBlock(blockNumber) + eta = blockInfo.timestamp + 49 * 60 * 60 + + const data = abiEncode(['address'],[model.address] ); + const txHash = keccak256(abiEncode( ['address', 'uint', 'string', 'bytes', 'uint'], [forge.address, 0, "upgradeModel(address)", data, eta] )) + + await timelock.queueTransaction( + forge.address, + 0, + "upgradeModel(address)", + data, + eta + ) + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true) + + await network.provider.send("evm_increaseTime", [49*60*60]); + await network.provider.send("evm_mine") + + await timelock.executeTransaction( + forge.address, + 0, + "upgradeModel(address)", + data, + eta + ) + + await expect( await forge.modelAddress() ).to.be.eq(model.address) + }) + }) } \ No newline at end of file diff --git a/test/unit/Forge/saver.behavior.ts b/test/unit/Forge/saver.behavior.ts index 38c8e94..4bb911d 100644 --- a/test/unit/Forge/saver.behavior.ts +++ b/test/unit/Forge/saver.behavior.ts @@ -1,4 +1,5 @@ import { expect } from "chai" +import { BigNumber } from "ethers"; import { ethers, network } from "hardhat"; import { Tokens } from "../../shared/mockInfo"; import { ethToWei } from '../../shared/utils' @@ -27,51 +28,48 @@ export function saverBehavior(): void { const blockNumber = await ethers.provider.getBlockNumber() const blockInfo = await ethers.provider.getBlock(blockNumber) const startTimestamp = blockInfo.timestamp + 25 *60 * 60 - await expect(this.contracts.forge['craftingSaver(uint256,uint256,uint256,uint256)'](100, startTimestamp, 1, 1)).to.be.reverted + const forge = this.contracts.forge; + + await expect(forge.craftingSaver(100, startTimestamp, 1, 2)).to.be.reverted }) it('should Revert due to startTimestamp', async function() { const blockNumber = await ethers.provider.getBlockNumber() const blockInfo = await ethers.provider.getBlock(blockNumber) - await expect(this.contracts.forge['craftingSaver(uint256,uint256,uint256,uint256)'](100, blockInfo.timestamp, 1, 1)).to.be.reverted + const forge = this.contracts.forge; + + await expect(forge.craftingSaver(100, blockInfo.timestamp, 1, 2)).to.be.reverted }) it('should Success craftingSaver', async function () { const blockNumber = await ethers.provider.getBlockNumber() const blockInfo = await ethers.provider.getBlock(blockNumber) const account = this.signers.accountDai - const forgeDai = this.contracts.forge - const daiContract = this.contracts.daiContract; - + const forge = this.contracts.forge + const daiContract = this.contracts.daiContract const startTimestamp = blockInfo.timestamp + 25 *60 * 60 - const saverIndex = await forgeDai.connect(account).countByAccount(account.address) + const saverIndex = await forge.connect(account).countByAccount(account.address) const balance = await daiContract.balanceOf( account.address ); - - await daiContract.connect(account).approve(forgeDai.address, ethToWei("100000")) - await expect(forgeDai - .connect(account)['craftingSaver(uint256,uint256,uint256,uint256)'](balance.div(3).toString(), startTimestamp, 1, 1)) - .to.emit(forgeDai, 'CraftingSaver') - .withArgs(account.address, saverIndex, balance.div(3).toString()) - + + await daiContract.connect(account).approve(forge.address, ethToWei("100000")) + await expect(forge + .connect(account).craftingSaver( ethToWei("1") , startTimestamp, 2, 4)) + .to.emit(forge, 'CraftingSaver') + .withArgs(account.address, saverIndex, ethToWei("1") ) + }) + it('should Success addDeposit', async function() { - const prevTransactionCount = (await this.contracts.forge.transactions(this.signers.accountDai.address, 0)).length; - await expect(this.contracts.forge.connect(this.signers.accountDai).addDeposit(0, 1000000)).to.emit(this.contracts.forge, 'AddDeposit').withArgs(this.signers.accountDai.address, 0, 1000000) - let afterTransactionCount = (await this.contracts.forge.transactions(this.signers.accountDai.address, 0)).length - await expect(afterTransactionCount).to.be.eq(prevTransactionCount, "Transaction is not added"); + const account = this.signers.accountDai + const forge = this.contracts.forge + const daiContract = this.contracts.daiContract; + const balance = await daiContract.balanceOf( account.address ); - // increase time 86400 secs - await network.provider.send("evm_increaseTime", [86400]); - await network.provider.send("evm_mine") - await expect(this.contracts.forge.connect(this.signers.accountDai).addDeposit(0, 1000000)) - .to.emit(this.contracts.forge, 'AddDeposit') - .withArgs(this.signers.accountDai.address, 0, 1000000) - - afterTransactionCount = (await this.contracts.forge.transactions(this.signers.accountDai.address, 0)).length - - await expect(afterTransactionCount).to.be.eq(prevTransactionCount + 1, "Transaction is not added"); + const saver = await forge.saver(account.address, 0); + // await expect(forge.connect(account).addDeposit(0, balance.div(3).toString())).to.emit(forge, 'AddDeposit').withArgs(account.address, 0, balance.div(3).toString()) + await expect(forge.connect(account).addDeposit(0, ethToWei("1"))).to.emit(forge, 'AddDeposit').withArgs(account.address, 0, ethToWei("1")) }) it('should Revert withdraw Not yet', async function() { @@ -81,16 +79,21 @@ export function saverBehavior(): void { }) it('should Success withdraw', async function() { - await network.provider.send("evm_increaseTime", [86400]); + await network.provider.send("evm_increaseTime", [106400]); await network.provider.send("evm_mine") const forge = this.contracts.forge; const account = this.signers.accountDai const withdrawable = await forge.connect(account).withdrawable(account.address, 0); - await expect(forge.connect(account).withdraw(0, 100000000000000)).emit(forge, "Withdraw") + await expect(forge.connect(account).withdraw(0, withdrawable.toString())).emit(forge, "Withdraw") }) it('should Success terminateSaver', async function() { + + const forge = this.contracts.forge; + const account = this.signers.accountDai + var saver = await forge.saver(account.address, 0); + await this.contracts.forge.connect(this.signers.accountDai).terminateSaver(0) await expect(this.contracts.forge.connect(this.signers.accountDai).terminateSaver(0)).to.be.reverted await expect(this.contracts.forge.connect(this.signers.accountDai).withdraw(0, 100)).to.be.reverted diff --git a/test/unit/OwnableStorage/setup.behavior.ts b/test/unit/OwnableStorage/setup.behavior.ts index ae15d0a..cf83823 100644 --- a/test/unit/OwnableStorage/setup.behavior.ts +++ b/test/unit/OwnableStorage/setup.behavior.ts @@ -3,55 +3,10 @@ import { expect } from "chai"; export function setUpBehavior(): void { context("SetUp", function() { - it('should Revert setAdmin Address Not Admin', async function() { + it('should Check Admin Addres is Timelock', async function() { + const timelock = this.contracts.timelock const ownableStorage = this.contracts.ownableStorage - const gov = this.signers.gov - await expect( ownableStorage.connect(gov).setAdmin(gov.address) ).to.be.reverted - }) - - it('should Success setAdmin', async function() { - const ownableStorage = this.contracts.ownableStorage - const owner = this.signers.owner - const gov = this.signers.gov - await ownableStorage.connect(owner).setAdmin( gov.address ); - await expect( await ownableStorage.isAdmin( gov.address ) ).to.be.eq( true ) - }) - - it('should Revert setAdmin by Governance', async function() { - const ownableStorage = this.contracts.ownableStorage - const owner = this.signers.gov - const gov = this.signers.owner - await expect( ownableStorage.connect(gov).setAdmin(owner.address) ).to.be.reverted - }) - - it('should Revert setGovernance Address Not Admin', async function() { - const ownableStorage = this.contracts.ownableStorage - const account2 = this.signers.account2 - await expect( ownableStorage.connect(account2).setGovernance(account2.address) ).to.be.reverted - }) - - it('should Success setGovernance by Admin', async function() { - const ownableStorage = this.contracts.ownableStorage - const owner = this.signers.gov - const gov = this.signers.owner - await ownableStorage.connect(owner).setGovernance( gov.address ); - await expect( await ownableStorage.isGovernance( gov.address ) ).to.be.eq( true ) - }) - - it('should Revert setGovernance by Gov', async function() { - const ownableStorage = this.contracts.ownableStorage - const owner = this.signers.gov - const gov = this.signers.owner - await ownableStorage.connect(gov).setGovernance( owner.address ); - await expect( await ownableStorage.isGovernance( owner.address ) ).to.be.eq( true ) - }) - - after(async function(){ - const ownableStorage = this.contracts.ownableStorage - const owner = this.signers.owner - const gov = this.signers.gov - await ownableStorage.connect(gov).setAdmin(owner.address); - await ownableStorage.connect(owner).setGovernance(gov.address); + await expect(await ownableStorage.isAdmin(timelock.address)).to.be.eq(true) }) }) diff --git a/test/unit/PunkRewardPool/PunkRewardPool.ts b/test/unit/PunkRewardPool/PunkRewardPool.ts deleted file mode 100644 index 251162f..0000000 --- a/test/unit/PunkRewardPool/PunkRewardPool.ts +++ /dev/null @@ -1,9 +0,0 @@ -import { initialBehavior } from "./initialize.behavior" -import { setUpBehavior } from "./setup.behavior" - -export function unitTestPunkRewardPool(): void { - describe("PunkRewardPool", function() { - initialBehavior() - setUpBehavior() - }) -} \ No newline at end of file diff --git a/test/unit/PunkRewardPool/initialize.behavior.ts b/test/unit/PunkRewardPool/initialize.behavior.ts deleted file mode 100644 index 099f3fa..0000000 --- a/test/unit/PunkRewardPool/initialize.behavior.ts +++ /dev/null @@ -1,35 +0,0 @@ -import { expect } from "chai"; -import { BigNumber } from "ethers"; -import { ethToWei } from "../../shared/utils" - -export function initialBehavior(): void { - context("Initailize", function() { - - it('should Success RewardPool Initialize', async function() { - const ownableStorage = this.contracts.ownableStorage; - const rewardPool = this.contracts.rewardPool; - const punkMock = this.contracts.punkMock; - const owner = this.signers.owner; - - await expect(rewardPool.connect(owner).initializeReward(ownableStorage.address, punkMock.address)).emit(rewardPool, "Initialize") - }) - - it('should Revert Already initialized', async function() { - const ownableStorage = this.contracts.ownableStorage; - const rewardPool = this.contracts.rewardPool; - const punkMock = this.contracts.punkMock; - const owner = this.signers.owner; - await expect(rewardPool.connect(owner).initializeReward(ownableStorage.address, punkMock.address)).to.be.reverted - }) - - it('should Success Transfer Punk For RewardPool', async function() { - const punkMock = this.contracts.punkMock - const rewardPool = this.contracts.rewardPool - const owner = this.signers.owner - await punkMock.connect(owner).transfer( rewardPool.address, ethToWei("10500000") ); - await expect( await punkMock.balanceOf(rewardPool.address) ).eq(BigNumber.from(ethToWei("10500000"))) - await expect( await rewardPool.getTotalReward() ).eq(BigNumber.from(ethToWei("10500000"))) - }) - - }) -} \ No newline at end of file diff --git a/test/unit/PunkRewardPool/setup.behavior.ts b/test/unit/PunkRewardPool/setup.behavior.ts deleted file mode 100644 index 8af8b3e..0000000 --- a/test/unit/PunkRewardPool/setup.behavior.ts +++ /dev/null @@ -1,150 +0,0 @@ -import { expect } from "chai"; -import { BigNumber } from "ethers"; -import { ethers } from "hardhat"; - -export function setUpBehavior(): void { - context("SetUp", function() { - - it('should Revert addForge Not Admin', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const account1 = this.signers.account1 - await expect( rewardPool.connect(account1).addForge( forge.address ) ).to.be.reverted - }) - - it('should Revert addForge address Gov', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const gov = this.signers.gov - await expect( rewardPool.connect(gov).addForge( forge.address ) ).to.be.reverted - }) - - it('should Revert addForge Not Contract Address', async function() { - const rewardPool = this.contracts.rewardPool - const owner = this.signers.owner - await expect( rewardPool.connect(owner).addForge( owner.address ) ).to.be.reverted - }) - - it('should Success addForge 3 Items', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const forge2nd = this.contracts.forge2 - const forge3rd = this.contracts.forge3 - const owner = this.signers.owner - - await expect( rewardPool.connect(owner).addForge( forge.address ) ).emit(rewardPool, "AddForge").withArgs(forge.address) - await expect( rewardPool.connect(owner).addForge( forge2nd.address ) ).emit(rewardPool, "AddForge").withArgs(forge2nd.address) - await expect( rewardPool.connect(owner).addForge( forge3rd.address ) ).emit(rewardPool, "AddForge").withArgs(forge3rd.address) - - await expect( await rewardPool.checkForge( forge.address ) ).eq(true) - await expect( await rewardPool.checkForge( forge2nd.address ) ).eq(true) - await expect( await rewardPool.checkForge( forge3rd.address ) ).eq(true) - }) - - it('should Revert addForge Already Exist', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const owner = this.signers.owner - await expect( rewardPool.connect(owner).addForge( forge.address ) ).to.be.reverted - }) - - it('should Revert setForge Overflow Max Value', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const owner = this.signers.owner - const range:BigNumber[] = await rewardPool.getWeightRange(forge.address) - const weight = range[range.length-1].toNumber() + 1 - await expect( rewardPool.connect(owner).setForge( forge.address, weight ) ).be.to.reverted - }) - - it('should Check weightRange Forge Counts 0', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const range:BigNumber[] = await rewardPool.getWeightRange(forge.address) - // Only 0 : 500 - await expect( range[0].toNumber() ).eq( 0 ) - await expect( range[1].toNumber() ).eq( 500 ) - }) - - it('should Success setForge', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const owner = this.signers.owner - const weight = 10 - await expect( rewardPool.connect(owner).setForge( forge.address, weight ) ).emit(rewardPool, "SetForge").withArgs(forge.address, weight) - await expect( await rewardPool.getWeight(forge.address) ).equal(weight) - }) - - it('should Check weightRange Forge Counts 1', async function() { - const rewardPool = this.contracts.rewardPool - const forge2nd = this.contracts.forge2 - const range:BigNumber[] = await rewardPool.getWeightRange(forge2nd.address) - // Only 10 : 10 - await expect( range[0].toNumber() ).eq( 10 ) - await expect( range[1].toNumber() ).eq( 10 ) - }) - - it('should Success setForge 2nd', async function() { - const rewardPool = this.contracts.rewardPool - const forge2nd = this.contracts.forge2 - const owner = this.signers.owner - const weight = 10 - - await expect( rewardPool.connect(owner).setForge( forge2nd.address, weight ) ).emit(rewardPool, "SetForge").withArgs(forge2nd.address, weight) - await expect( await rewardPool.getWeight(forge2nd.address) ).equal(weight) - }) - - it('should Check weightRange Forge Counts 2', async function() { - const rewardPool = this.contracts.rewardPool - const forge3rd = this.contracts.forge3 - const range:BigNumber[] = await rewardPool.getWeightRange(forge3rd.address) - // Only 0 : 20 - await expect( range[0].toNumber() ).eq( 0 ) - await expect( range[1].toNumber() ).eq( 20 ) - }) - - it('should Success setForge 3nd', async function() { - const rewardPool = this.contracts.rewardPool - const forge3rd = this.contracts.forge3 - const owner = this.signers.owner - const weight = 10 - await expect( rewardPool.connect(owner).setForge( forge3rd.address, weight ) ).emit(rewardPool, "SetForge").withArgs(forge3rd.address, weight) - await expect( await rewardPool.getWeight(forge3rd.address) ).equal(weight) - }) - - it('should Check getWeightSum', async function() { - const rewardPool = this.contracts.rewardPool - const forge = this.contracts.forge - const forge2nd = this.contracts.forge2 - const forge3rd = this.contracts.forge3 - - const forgeWeight = await rewardPool.getWeight( forge.address ) - const forge2ndWeight = await rewardPool.getWeight( forge2nd.address ) - const forge3rdWeight = await rewardPool.getWeight( forge3rd.address ) - - await expect( await rewardPool.getWeightSum() ).eq( Number(forgeWeight) + Number(forge2ndWeight) + Number(forge3rdWeight) ) - }) - - it('should Revert start Not Admin', async function() { - const rewardPool = this.contracts.rewardPool - const account1 = this.signers.account1 - await expect( rewardPool.connect(account1).start()).to.be.reverted - }) - - it('should Success start', async function() { - const rewardPool = this.contracts.rewardPool - const owner = this.signers.owner - await expect( rewardPool.connect(owner).start()).emit(rewardPool,"Start") - const blockNumber = await ethers.provider.getBlockNumber() - await expect( (await rewardPool.getStartBlock()).toNumber()).eq(blockNumber) - }) - - it('should Revert start already started', async function() { - const rewardPool = this.contracts.rewardPool - const owner = this.signers.owner - await expect( rewardPool.connect(owner).start()).to.be.reverted - }) - - }) - -} \ No newline at end of file diff --git a/test/unit/RecoveryFund/RecoveryFund.ts b/test/unit/RecoveryFund/RecoveryFund.ts index 2ae78f0..3b66c2a 100644 --- a/test/unit/RecoveryFund/RecoveryFund.ts +++ b/test/unit/RecoveryFund/RecoveryFund.ts @@ -4,9 +4,9 @@ import { setUpBehavior } from "./setup.behavior" export function unitTestRecoveryFund(): void { - describe("RecoveryFundMock", function() { + describe("RecoveryFund", function() { initialBehavior() setUpBehavior() }) -} \ No newline at end of file +} diff --git a/test/unit/RecoveryFund/initialize.behavior.ts b/test/unit/RecoveryFund/initialize.behavior.ts index 518290f..fcaec88 100644 --- a/test/unit/RecoveryFund/initialize.behavior.ts +++ b/test/unit/RecoveryFund/initialize.behavior.ts @@ -8,7 +8,7 @@ export function initialBehavior(): void { context("Initailize", function() { before(async function(){ - const daiContract = this.contracts.daiContract + const recoveryFundMock = this.contracts.recoveryFundMock; const uniswapV2Router = this.contracts.uniswapV2Router const accountDai = this.signers.accountDai @@ -18,7 +18,7 @@ export function initialBehavior(): void { const swapResult = await uniswapV2Router.connect(accountDai).swapExactETHForTokens( 1, [Tokens.WETH, Tokens.Dai], - accountDai.address, + recoveryFundMock.address, blockInfo.timestamp + 25*60*60, {value: ethToWei("700"), gasLimit: '2600000'} ) @@ -27,15 +27,15 @@ export function initialBehavior(): void { it('should Check total refund', async function() { const recoveryFundMock = this.contracts.recoveryFundMock; - await expect( await recoveryFundMock.totalRefund() ).eq(BigNumber.from("4041503630429289895300000")) + await expect( await recoveryFundMock.totalRefund() ).eq(BigNumber.from("3951644672859289895300000")) }) it('should Check peUSD balances', async function(){ const recoveryFundMock = this.contracts.recoveryFundMock; + await expect( await recoveryFundMock.balanceOf("0xe1cd21e5d6f4323E91dA943B0A4F1732acC7a138")).eq( BigNumber.from("1213998517300000000000000")); await expect( await recoveryFundMock.balanceOf("0xf49a12fE6a05bdFc7C0cd4FE2A19724CCFbA18d3")).eq( BigNumber.from("898535671700000000000000")); await expect( await recoveryFundMock.balanceOf("0x82dc92b01c7fF54911842956083795f60f6F64f4")).eq( BigNumber.from("673946680643589900000000")); - await expect( await recoveryFundMock.balanceOf("0x8ed32Ed24303092c016Cdb24d51e153AD88c4875")).eq( BigNumber.from("89858957570000000000000")); await expect( await recoveryFundMock.balanceOf("0xf2CcE4EcB119038dA9F4E18F82E07bb555FbAe2C")).eq( BigNumber.from("77613054250000000000000")); await expect( await recoveryFundMock.balanceOf("0x5522234194F499F1DBF2E26C6eBD802bc2Cd9A2f")).eq( BigNumber.from("77095278220000000000000")); await expect( await recoveryFundMock.balanceOf("0x896b94f4f27f12369698C302e2049cAe86936BbB")).eq( BigNumber.from("62897497019999995000000")); @@ -51,7 +51,7 @@ export function initialBehavior(): void { await expect( await recoveryFundMock.balanceOf("0xe9017c8De5040968D9752A18d805cD2A983E558c")).eq( BigNumber.from("32003782980000000000000")); await expect( await recoveryFundMock.balanceOf("0x55d72CbcbA1Ab5C784bC52641D16c613E3b9BAD4")).eq( BigNumber.from("31755408880000000000000")); await expect( await recoveryFundMock.balanceOf("0xf76CF36f638c7bCD83f4756beDb86243D98982F9")).eq( BigNumber.from("29253624400000000000000")); - await expect( await recoveryFundMock.balanceOf("0x29227FB595D091bcA244E76201c0dd50641D96C8")).eq( BigNumber.from("27239560830000002000000")); + await expect( await recoveryFundMock.balanceOf("0x2881Be539cacB7671D32D1f2cdEb50F53F9F19b5")).eq( BigNumber.from("27239560830000002000000")); await expect( await recoveryFundMock.balanceOf("0x2572a193DA3DEf3BAeA04cB18e06A52186aC1a98")).eq( BigNumber.from("26954824385000000000000")); await expect( await recoveryFundMock.balanceOf("0x81a7E267Fd8339a01beb175f5A3d644FcF0B48Dc")).eq( BigNumber.from("24234548190999998000000")); await expect( await recoveryFundMock.balanceOf("0x67D33CF1C7c699078f86D517A5a1cd1444A1E85C")).eq( BigNumber.from("23536011086000000000000")); @@ -108,5 +108,7 @@ export function initialBehavior(): void { }) + + }) } \ No newline at end of file diff --git a/test/unit/RecoveryFund/setup.behavior.ts b/test/unit/RecoveryFund/setup.behavior.ts index 66d6c1d..4fbb055 100644 --- a/test/unit/RecoveryFund/setup.behavior.ts +++ b/test/unit/RecoveryFund/setup.behavior.ts @@ -1,6 +1,5 @@ import { expect } from "chai"; -import { BigNumber, Contract } from "ethers"; -import { ethers } from "hardhat"; +import { BigNumber } from "ethers"; export function setUpBehavior(): void { context("SetUp", function() { @@ -29,19 +28,15 @@ export function setUpBehavior(): void { let balance = (await daiContract.balanceOf(accountDai.address)).toString() const beforeTotalSupply = (await recoveryFundMock.totalSupply()).toString() - const minRefundAmount = (await recoveryFundMock.minRefundAmount()).toString() - - balance = BigNumber.from(balance).sub(BigNumber.from(balance).mod(minRefundAmount)) await daiContract.approve( recoveryFundMock.address, balance ) - const refundTx = (await recoveryFundMock.connect(accountDai).refund(balance)).toString(); - + await recoveryFundMock.connect(accountDai).refund(balance); const refunded = (await recoveryFundMock.refunded()).toString(); + await expect(await recoveryFundMock.totalSupply()).eq( BigNumber.from(beforeTotalSupply).sub(refunded) ) await expect( await recoveryFundMock.balanceOf("0xe1cd21e5d6f4323E91dA943B0A4F1732acC7a138")).eq( BigNumber.from("1213998517300000000000000").sub(BigNumber.from("1213998517300000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0xf49a12fE6a05bdFc7C0cd4FE2A19724CCFbA18d3")).eq( BigNumber.from("898535671700000000000000").sub(BigNumber.from("898535671700000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x82dc92b01c7fF54911842956083795f60f6F64f4")).eq( BigNumber.from("673946680643589900000000").sub(BigNumber.from("673946680643589900000000").mul(balance).div(beforeTotalSupply))); - await expect( await recoveryFundMock.balanceOf("0x8ed32Ed24303092c016Cdb24d51e153AD88c4875")).eq( BigNumber.from("89858957570000000000000").sub(BigNumber.from("89858957570000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0xf2CcE4EcB119038dA9F4E18F82E07bb555FbAe2C")).eq( BigNumber.from("77613054250000000000000").sub(BigNumber.from("77613054250000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x5522234194F499F1DBF2E26C6eBD802bc2Cd9A2f")).eq( BigNumber.from("77095278220000000000000").sub(BigNumber.from("77095278220000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x896b94f4f27f12369698C302e2049cAe86936BbB")).eq( BigNumber.from("62897497019999995000000").sub(BigNumber.from("62897497019999995000000").mul(balance).div(beforeTotalSupply))); @@ -57,7 +52,7 @@ export function setUpBehavior(): void { await expect( await recoveryFundMock.balanceOf("0xe9017c8De5040968D9752A18d805cD2A983E558c")).eq( BigNumber.from("32003782980000000000000").sub(BigNumber.from("32003782980000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x55d72CbcbA1Ab5C784bC52641D16c613E3b9BAD4")).eq( BigNumber.from("31755408880000000000000").sub(BigNumber.from("31755408880000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0xf76CF36f638c7bCD83f4756beDb86243D98982F9")).eq( BigNumber.from("29253624400000000000000").sub(BigNumber.from("29253624400000000000000").mul(balance).div(beforeTotalSupply))); - await expect( await recoveryFundMock.balanceOf("0x29227FB595D091bcA244E76201c0dd50641D96C8")).eq( BigNumber.from("27239560830000002000000").sub(BigNumber.from("27239560830000002000000").mul(balance).div(beforeTotalSupply))); + await expect( await recoveryFundMock.balanceOf("0x2881Be539cacB7671D32D1f2cdEb50F53F9F19b5")).eq( BigNumber.from("27239560830000002000000").sub(BigNumber.from("27239560830000002000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x2572a193DA3DEf3BAeA04cB18e06A52186aC1a98")).eq( BigNumber.from("26954824385000000000000").sub(BigNumber.from("26954824385000000000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x81a7E267Fd8339a01beb175f5A3d644FcF0B48Dc")).eq( BigNumber.from("24234548190999998000000").sub(BigNumber.from("24234548190999998000000").mul(balance).div(beforeTotalSupply))); await expect( await recoveryFundMock.balanceOf("0x67D33CF1C7c699078f86D517A5a1cd1444A1E85C")).eq( BigNumber.from("23536011086000000000000").sub(BigNumber.from("23536011086000000000000").mul(balance).div(beforeTotalSupply))); diff --git a/test/unit/Referral/Referral.ts b/test/unit/Referral/Referral.ts deleted file mode 100644 index 5f5fb8c..0000000 --- a/test/unit/Referral/Referral.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { setUpBehavior } from "./setup.behavior" - -export function unitTestReferral(): void { - describe("Referral", function() { - setUpBehavior() - }) - -} \ No newline at end of file diff --git a/test/unit/Referral/setup.behavior.ts b/test/unit/Referral/setup.behavior.ts deleted file mode 100644 index 4eb1dde..0000000 --- a/test/unit/Referral/setup.behavior.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { expect } from "chai"; - -export function setUpBehavior(): void { - context("SetUp", function() { - - it('should Success Issue ReferralCode & Revert Already Issue', async function() { - const referral = this.contracts.referral - const account1 = this.signers.account1 - await referral.issue(account1.address); - await expect( referral.issue(account1.address) ).to.be.reverted - }) - - it('should Check & Validate', async function() { - const referral = this.contracts.referral - const account1 = this.signers.account1 - const address = await referral.referralCode( account1.address ); - await expect( await referral.validate( address ) ).to.be.eq( account1.address ) - }) - - }) - -} \ No newline at end of file diff --git a/test/unit/Score/Score.ts b/test/unit/Score/Score.ts deleted file mode 100644 index 8ffcc6f..0000000 --- a/test/unit/Score/Score.ts +++ /dev/null @@ -1,48 +0,0 @@ -import { unitFixtureScoreMock } from "../../shared/fixtures" -import { ScoreMock } from '../../../typechain' -import { expect } from "chai" -export function unitTestScore(): void { - describe("Score", function() { - before(async function() { - const scoreMock: ScoreMock = await this.loadFixture(unitFixtureScoreMock) - this.contracts.scoreMock = scoreMock; - }) - - context("Score model test", function() { - it("Calculate score correctly", async function() { - const createTimestamp = 1622520000 // 2021-06-01 00:00:00 - const startTimestamp = 1638334800 // 2021-12-01 00:00:00 - const count = 1; - const interval = 1; - const transactions = [ - { - timestamp:1622520000, - amount:100000, - pos: true, - }, - { - timestamp:1622520000, - amount:100000, - pos: true, - }, - { - timestamp:1622520000, - amount:100000, - pos: true, - } - ]; - - const scoreResult = await this.contracts.scoreMock.scoreCalculation( - createTimestamp, - startTimestamp, - transactions, - count, - interval, - 8 - ) - - await expect(scoreResult).to.be.equal(55659665) - }) - }) - }) -} \ No newline at end of file diff --git a/test/unit/Treasury/Treasury.ts b/test/unit/Treasury/Treasury.ts index 3231cca..42dc896 100644 --- a/test/unit/Treasury/Treasury.ts +++ b/test/unit/Treasury/Treasury.ts @@ -4,9 +4,7 @@ import { setUpBehavior } from "./setup.behavior" export function unitTestTreasury(): void { describe("Treasury", function() { - initialBehavior() - setUpBehavior() }) diff --git a/test/unit/Treasury/setup.behavior.ts b/test/unit/Treasury/setup.behavior.ts index e01455b..0cae722 100644 --- a/test/unit/Treasury/setup.behavior.ts +++ b/test/unit/Treasury/setup.behavior.ts @@ -1,48 +1,125 @@ -import { Tokens } from "../../shared/mockInfo" +import { Tokens } from "../../shared/mockInfo"; import { expect } from "chai"; -import { ethers } from "hardhat"; +import { ethers, network } from "hardhat"; +import { abiEncode, ethToWei } from "../../shared/utils"; export function setUpBehavior(): void { - context("SetUp", function() { - - it('should Revert addAsset Address Not AdminOrGovernance', async function() { - const treasury = this.contracts.treasury - const account1 = this.signers.account1 - await expect( treasury.connect(account1).addAsset(Tokens.Dai) ).to.be.reverted - }) - - it('should Success addAsset', async function() { - const treasury = this.contracts.treasury - const owner = this.signers.owner - await expect(treasury.connect(owner).addAsset(Tokens.Dai)).emit(treasury, "AddAsset").withArgs(Tokens.Dai); - }) - - it('should Revert addAsset Already Registry Token', async function() { - const treasury = this.contracts.treasury - const owner = this.signers.owner - await expect(treasury.connect(owner).addAsset(Tokens.Dai)).to.be.reverted - }) - - it('should Revert addAsset Buyback Test', async function() { - const treasury = this.contracts.treasury - const owner = this.signers.owner - await treasury.connect(owner).buyBack() - }) + context("SetUp", function () { + + before(async function(){ + const recoveryFundMock = this.contracts.recoveryFundMock; + const uniswapV2Router = this.contracts.uniswapV2Router + const accountDai = this.signers.accountDai - // it('should Revert addAsset Buyback Test', async function() { - // const treasury = this.contracts.treasury - // const owner = this.signers.owner - // const DAI = this.contracts.daiContract - // const swapResult = await this.contracts.uniswapV2Router.connect(this.signers.owner).swapExactETHForTokens( - // 10000000000, - // [Tokens.WETH, Tokens.Dai], - // treasury.address, - // Math.round(Date.now() / 1000) + 100000000000000, - // {value: "100000000000000000000", gasLimit: '2300000'} - // ) - // await swapResult.wait() - // await treasury.connect(owner).buyBack() - // }) + const blockNumber = await ethers.provider.getBlockNumber() + const blockInfo = await ethers.provider.getBlock(blockNumber) + const swapResult = await uniswapV2Router.connect(accountDai).swapExactETHForTokens( + 1, + [Tokens.WETH, Tokens.Dai], + recoveryFundMock.address, + blockInfo.timestamp + 25*60*60, + {value: ethToWei("700"), gasLimit: '2600000'} + ) + await swapResult.wait() }) -} \ No newline at end of file + + it("should Revert addAsset Address Not Admin", async function () { + const treasury = this.contracts.treasury; + const account1 = this.signers.account1; + await expect( + treasury.connect(account1).addAsset(Tokens.Dai) + ).to.be.reverted; + }); + + it("should Success addAsset", async function () { + const treasury = this.contracts.treasury; + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + + const data = abiEncode(["address"], [Tokens.Dai]); + await timelock.queueTransaction( + treasury.address, + 0, + "addAsset(address)", + data, + eta + ); + + await network.provider.send("evm_increaseTime", [49 * 60 * 60]); + await network.provider.send("evm_mine"); + + await expect(timelock.executeTransaction( + treasury.address, + 0, + "addAsset(address)", + data, + eta + )).emit(treasury, "AddAsset").withArgs(Tokens.Dai); + }); + + it("should Revert addAsset Already Registry Token", async function () { + const treasury = this.contracts.treasury; + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + + const data = abiEncode(["address"], [Tokens.Dai]); + await timelock.queueTransaction( + treasury.address, + 0, + "addAsset(address)", + data, + eta + ); + + await network.provider.send("evm_increaseTime", [49 * 60 * 60]); + await network.provider.send("evm_mine"); + + await expect(timelock.executeTransaction( + treasury.address, + 0, + "addAsset(address)", + data, + eta + )).to.be.reverted; + }); + + it("should Revert addAsset Buyback Test", async function () { + const treasury = this.contracts.treasury; + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + + const daiContract = this.contracts.daiContract; + const accountDai = this.signers.accountDai + + await daiContract.connect(accountDai).transfer(treasury.address, ethToWei("10")); + + const data = abiEncode(["address[]", "uint256[]"], [[accountDai.address],[1]]); + await timelock.queueTransaction( + treasury.address, + 0, + "buyBack(address[],uint256[])", + data, + eta + ); + + await network.provider.send("evm_increaseTime", [49 * 60 * 60 + 20]); + await network.provider.send("evm_mine"); + + await timelock.executeTransaction( + treasury.address, + 0, + "buyBack(address[],uint256[])", + data, + eta + ) + + }); + }); +} diff --git a/test/unit/Variables/setup.behavior.ts b/test/unit/Variables/setup.behavior.ts index 17779e0..a7e4c5b 100644 --- a/test/unit/Variables/setup.behavior.ts +++ b/test/unit/Variables/setup.behavior.ts @@ -1,250 +1,356 @@ +import { keccak256 } from "@ethersproject/keccak256"; import { expect } from "chai"; +import { ethers, network } from "hardhat"; +import { abiEncode } from "../../shared/utils"; export function setUpBehavior(): void { - context("SetUp", function() { - - it('should Revert setReferral Address Not Admin', async function() { - const variables = this.contracts.variables - const referral = this.contracts.referral - const account1 = this.signers.account1 - await expect( variables.connect(account1).setReferral(referral.address) ).to.be.reverted - }) - - it('should Revert setReferral Address Not Contract', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const account1 = this.signers.account1 - await expect( variables.connect(owner).setReferral(account1) ).to.be.reverted - }) - - it('should Success setReferral Address', async function() { - const variables = this.contracts.variables - const referral = this.contracts.referral - const owner = this.signers.owner - await variables.connect(owner).setReferral(referral.address); - await expect( await variables.referral() ).to.be.eq( referral.address ) - }) - - it('should Revert setRewardPool Address Not Admin', async function() { - const variables = this.contracts.variables - const rewardPool = this.contracts.rewardPool - const account1 = this.signers.account1 - await expect( variables.connect(account1).setReward(rewardPool.address) ).to.be.reverted - }) - - it('should Revert setRewardPool Address Not Contract', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const account1 = this.signers.account1 - await expect( variables.connect(owner).setReward(account1) ).to.be.reverted - }) - - it('should Success setRewardPool Address', async function() { - const variables = this.contracts.variables - const rewardPool = this.contracts.rewardPool - const owner = this.signers.owner - await variables.connect(owner).setReward(rewardPool.address); - await expect( await variables.reward() ).to.be.eq( rewardPool.address ) - }) - - it('should Revert setTreasury Address Not Admin', async function() { - const variables = this.contracts.variables - const treasury = this.contracts.treasury - const account1 = this.signers.account1 - await expect( variables.connect(account1).setTreasury(treasury.address) ).to.be.reverted - }) - - it('should Revert setTreasury Address Not Contract', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const account1 = this.signers.account1 - await expect( variables.connect(owner).setTreasury(account1) ).to.be.reverted - }) - - it('should Success setTreasury Address', async function() { - const variables = this.contracts.variables - const treasury = this.contracts.treasury - const owner = this.signers.owner - await variables.connect(owner).setTreasury(treasury.address); - await expect( await variables.treasury() ).to.be.eq( treasury.address ) - }) - - it('should Revert setOperatorTreasury Address Not Admin', async function() { - const variables = this.contracts.variables - const opTreasury = this.contracts.opTreasury - const account1 = this.signers.account1 - await expect( variables.connect(account1).setOpTreasury(opTreasury.address) ).to.be.reverted - }) - - it('should Revert setOperatorTreasury Address Not Contract', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const account1 = this.signers.account1 - await expect( variables.connect(owner).setOpTreasury(account1) ).to.be.reverted - }) - - it('should Success setOperatorTreasury Address', async function() { - const variables = this.contracts.variables - const opTreasury = this.contracts.opTreasury - const owner = this.signers.owner - await variables.connect(owner).setOpTreasury(opTreasury.address); - await expect( await variables.opTreasury() ).to.be.eq( opTreasury.address ) - }) - - it('should Revert setEarlyTerminateFee Address Not Gov and Admin', async function() { - const variables = this.contracts.variables - const account1 = this.signers.account1 - await expect( variables.connect(account1).setEarlyTerminateFee(1) ).to.be.reverted - }) - - it('should Revert setEarlyTerminateFee Address Admin', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - await expect( variables.connect(owner).setEarlyTerminateFee(1) ).to.be.reverted - }) - - it('should Success setEarlyTerminateFee', async function() { - const variables = this.contracts.variables - const gov = this.signers.gov - const fee = 1 - await variables.connect(gov).setEarlyTerminateFee(fee); - await expect( await variables['earlyTerminateFee()']() ).to.be.eq( fee ) - }) - - it('should Revert setEarlyTerminateFee Overflow Valeus', async function() { - const variables = this.contracts.variables - const gov = this.signers.gov - await expect( variables.connect(gov).setEarlyTerminateFee(10) ).to.be.reverted - }) - - it('should Revert setBuybackRate Address Not Gov and Admin', async function() { - const variables = this.contracts.variables - const account1 = this.signers.account1 - await expect( variables.connect(account1).setBuybackRate(20) ).to.be.reverted - }) - - it('should Revert setBuybackRate Address Admin', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - await expect( variables.connect(owner).setBuybackRate(20) ).to.be.reverted - }) - - it('should Success setBuybackRate', async function() { - const variables = this.contracts.variables - const gov = this.signers.gov - await variables.connect(gov).setBuybackRate(20); - await expect( await variables.buybackRate() ).to.be.eq( 20 ) - }) - - it('should Revert setBuybackRate Overflow Valeus', async function() { - const variables = this.contracts.variables - const gov = this.signers.gov - await expect( variables.connect(gov).setBuybackRate(21) ).to.be.reverted - }) - - it('should Revert setServiceFee Address Not Gov and Admin', async function() { - const variables = this.contracts.variables - const account1 = this.signers.account1 - await expect( variables.connect(account1).setServiceFee(1) ).to.be.reverted - }) - - it('should Revert setServiceFee Address Admin', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - await expect( variables.connect(owner).setServiceFee(1) ).to.be.reverted - }) - - it('should Success setServiceFee', async function() { - const variables = this.contracts.variables - const gov = this.signers.gov - await variables.connect(gov).setServiceFee(1); - await expect( await variables.serviceFee() ).to.be.eq( 1 ) - }) - - it('should Revert setServiceFee Overflow Valeus', async function() { - const variables = this.contracts.variables - const gov = this.signers.gov - await expect( variables.connect(gov).setServiceFee(3) ).to.be.reverted - }) - - it('should Revert setDiscount Address Not Admin', async function() { - const variables = this.contracts.variables - const account1 = this.signers.account1 - await expect( variables.connect(account1).setDiscount(20) ).to.be.reverted - }) - - it('should Success setDiscount Overflow Valeus', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const compensation = await variables.compensation() - await expect( variables.connect(owner).setDiscount( 101 - compensation ) ).to.be.reverted - }) - - it('should Success setDiscount', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const setUpPoint = 5; - await expect( variables.connect(owner).setDiscount( setUpPoint ) ) - const discount = await variables.discount(); - await expect( discount ).eq( setUpPoint ) - }) - - it('should Revert setCompensation Address Not Admin', async function() { - const variables = this.contracts.variables - const account1 = this.signers.account1 - await expect( variables.connect(account1).setCompensation(20) ).to.be.reverted - }) - - it('should Success setCompensation Overflow Valeus', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const discount = await variables.discount() - await expect( variables.connect(owner).setCompensation( 101 - discount ) ).to.be.reverted - }) - - it('should Success setCompensation', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner - const setUpPoint = 5; - await expect( variables.connect(owner).setCompensation( setUpPoint ) ) - const compensation = await variables.compensation(); - await expect( compensation ).eq( setUpPoint ) - }) - - it('should Revert setEmergency Address Not Admin', async function() { - const variables = this.contracts.variables - const account1 = this.signers.account1 - const forge = this.contracts.forge; - await expect( variables.connect(account1).setEmergency(forge.address) ).to.be.reverted - }) - - it('should Success setEmergency for True', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner; - const forge = this.contracts.forge; - let ealryTerminateFee = await variables['earlyTerminateFee()'](); - if( ealryTerminateFee == 0 ){ - await variables.connect(owner).setEarlyTerminateFee( 1 ) - ealryTerminateFee = await variables['earlyTerminateFee()'](); - } - await variables.connect(owner).setEmergency( forge.address, true ); - const emergencyEalryTerminateFee = await variables['earlyTerminateFee(address)']( forge.address ); - await expect( emergencyEalryTerminateFee + ealryTerminateFee ).to.be.eq( ealryTerminateFee ) - }) - - it('should Success setEmergency for False', async function() { - const variables = this.contracts.variables - const owner = this.signers.owner; - const forge = this.contracts.forge; - let ealryTerminateFee = await variables['earlyTerminateFee()'](); - if( ealryTerminateFee == 0 ){ - await variables.connect(owner).setEarlyTerminateFee( 1 ) - ealryTerminateFee = await variables['earlyTerminateFee()'](); - } - await variables.connect(owner).setEmergency( forge.address, false ); - const emergencyEalryTerminateFee = await variables['earlyTerminateFee(address)']( forge.address ); - await expect( emergencyEalryTerminateFee ).to.be.eq( ealryTerminateFee ) - }) - - }) -} \ No newline at end of file + context("SetUp", function () { + // let etaSetReward = 0; + + // it("should Success addQueue setReward Address", async function () { + // const variables = this.contracts.variables; + // const rewardPool = this.contracts.rewardPool; + // const timelock = this.contracts.timelock; + // const blockNumber = await ethers.provider.getBlockNumber() + // const blockInfo = await ethers.provider.getBlock(blockNumber) + // const eta = blockInfo.timestamp + 49 * 60 * 60 + // etaSetReward = eta; + + // const data = abiEncode(['address'],[rewardPool.address] ); + // const txHash = keccak256(abiEncode( ['address', 'uint', 'string', 'bytes', 'uint'], [variables.address, 0, "setReward(address)", data, etaSetReward] )) + + // await timelock.queueTransaction( + // variables.address, + // 0, + // "setReward(address)", + // data, + // etaSetReward + // ) + + // await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true) + // }); + + // it("should Revert executeTx setReward", async function () { + // const variables = this.contracts.variables; + // const rewardPool = this.contracts.rewardPool; + // const timelock = this.contracts.timelock; + // const data = abiEncode(['address'],[rewardPool.address] ); + + // await expect(timelock.executeTransaction( + // variables.address, + // 0, + // "setReward(address)", + // data, + // etaSetReward + // )).to.be.reverted + // }); + + // it("should Success executeTx setReward", async function () { + // const variables = this.contracts.variables; + // const rewardPool = this.contracts.rewardPool; + // const timelock = this.contracts.timelock; + // const data = abiEncode(['address'],[rewardPool.address] ); + + // await network.provider.send("evm_increaseTime", [49*60*60]); + // await network.provider.send("evm_mine") + + // // await expect().to.be.reverted + // timelock.executeTransaction( + // variables.address, + // 0, + // "setReward(address)", + // data, + // etaSetReward + // ) + + // await expect( await variables.reward() ).to.be.eq(rewardPool.address) + // }); + + let etaSetSuccessFee = 0; + + it("should Success addQueue setSuccessFee", async function () { + const variables = this.contracts.variables; + + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + etaSetSuccessFee = eta; + + const data = abiEncode(["uint256"], [10]); + const txHash = keccak256( + abiEncode( + ["address", "uint", "string", "bytes", "uint"], + [ + variables.address, + 0, + "setSuccessFee(uint256)", + data, + etaSetSuccessFee, + ] + ) + ); + + await timelock.queueTransaction( + variables.address, + 0, + "setSuccessFee(uint256)", + data, + etaSetSuccessFee + ); + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true); + }); + + it("should Revert executeTx setSuccessFee", async function () { + const variables = this.contracts.variables; + + const timelock = this.contracts.timelock; + const data = abiEncode(["uint256"], [10]); + + await expect( + timelock.executeTransaction( + variables.address, + 0, + "setSuccessFee(uint256)", + data, + etaSetSuccessFee + ) + ).to.be.reverted; + }); + + it("should Success executeTx setSuccessFee", async function () { + const variables = this.contracts.variables; + const timelock = this.contracts.timelock; + + const data = abiEncode(["uint256"], [10]); + await network.provider.send("evm_increaseTime", [49 * 60 * 60]); + await network.provider.send("evm_mine"); + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + + timelock.executeTransaction( + variables.address, + 0, + "setSuccessFee(uint256)", + data, + etaSetSuccessFee + ); + + await expect(await variables.successFee()).to.be.eq(10); + }); + + let etaSetServiceFee = 0; + + it("should Success addQueue setServiceFee", async function () { + const variables = this.contracts.variables; + + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + etaSetServiceFee = eta; + + const data = abiEncode(["uint256"], [1]); + const txHash = keccak256( + abiEncode( + ["address", "uint", "string", "bytes", "uint"], + [ + variables.address, + 0, + "setServiceFee(uint256)", + data, + etaSetServiceFee, + ] + ) + ); + + await timelock.queueTransaction( + variables.address, + 0, + "setServiceFee(uint256)", + data, + etaSetServiceFee + ); + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true); + }); + + it("should Revert executeTx setServiceFee", async function () { + const variables = this.contracts.variables; + + const timelock = this.contracts.timelock; + const data = abiEncode(["uint256"], [1]); + + await expect( + timelock.executeTransaction( + variables.address, + 0, + "setServiceFee(uint256)", + data, + etaSetServiceFee + ) + ).to.be.reverted; + }); + + it("should Success executeTx setServiceFee", async function () { + const variables = this.contracts.variables; + const timelock = this.contracts.timelock; + + const data = abiEncode(["uint256"], [1]); + await network.provider.send("evm_increaseTime", [49 * 60 * 60]); + await network.provider.send("evm_mine"); + + timelock.executeTransaction( + variables.address, + 0, + "setServiceFee(uint256)", + data, + etaSetServiceFee + ); + + await expect(await variables.serviceFee()).to.be.eq(1); + }); + + let etaSetFeeMultiplier = 0; + + it("should Success addQueue setFeeMultiplier", async function () { + const variables = this.contracts.variables; + + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + etaSetFeeMultiplier = eta; + + const data = abiEncode(["uint256"], [150]); + const txHash = keccak256( + abiEncode( + ["address", "uint", "string", "bytes", "uint"], + [ + variables.address, + 0, + "setFeeMultiplier(uint256)", + data, + etaSetFeeMultiplier, + ] + ) + ); + + await timelock.queueTransaction( + variables.address, + 0, + "setFeeMultiplier(uint256)", + data, + etaSetFeeMultiplier + ); + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true); + }); + + it("should Revert executeTx setFeeMultiplier", async function () { + const variables = this.contracts.variables; + + const timelock = this.contracts.timelock; + const data = abiEncode(["uint256"], [150]); + + await expect( + timelock.executeTransaction( + variables.address, + 0, + "setFeeMultiplier(uint256)", + data, + etaSetFeeMultiplier + ) + ).to.be.reverted; + }); + + it("should Success executeTx setFeeMultiplier", async function () { + const variables = this.contracts.variables; + const timelock = this.contracts.timelock; + + const data = abiEncode(["uint256"], [150]); + await network.provider.send("evm_increaseTime", [49 * 60 * 60]); + await network.provider.send("evm_mine"); + + timelock.executeTransaction( + variables.address, + 0, + "setFeeMultiplier(uint256)", + data, + etaSetFeeMultiplier + ); + + await expect(await variables.feeMultiplier()).to.be.eq(150); + }); + + let etaSetTreasury = 0; + + it("should Success addQueue setTreasury", async function () { + const variables = this.contracts.variables; + const treasury = this.contracts.treasury; + + const timelock = this.contracts.timelock; + const blockNumber = await ethers.provider.getBlockNumber(); + const blockInfo = await ethers.provider.getBlock(blockNumber); + const eta = blockInfo.timestamp + 49 * 60 * 60; + etaSetTreasury = eta; + + const data = abiEncode(["address"], [treasury.address]); + const txHash = keccak256( + abiEncode( + ["address", "uint", "string", "bytes", "uint"], + [variables.address, 0, "setTreasury(address)", data, etaSetTreasury] + ) + ); + + await timelock.queueTransaction( + variables.address, + 0, + "setTreasury(address)", + data, + etaSetTreasury + ); + + await expect(await timelock.queuedTransactions(txHash)).to.be.eq(true); + }); + + it("should Revert executeTx setTreasury", async function () { + const variables = this.contracts.variables; + const treasury = this.contracts.treasury; + + const timelock = this.contracts.timelock; + const data = abiEncode(["address"], [treasury.address]); + + await expect( + timelock.executeTransaction( + variables.address, + 0, + "setTreasury(address)", + data, + etaSetTreasury + ) + ).to.be.reverted; + }); + + it("should Success executeTx setTreasury", async function () { + const variables = this.contracts.variables; + const timelock = this.contracts.timelock; + const treasury = this.contracts.treasury; + + const data = abiEncode(["address"], [treasury.address]); + await network.provider.send("evm_increaseTime", [49 * 60 * 60]); + await network.provider.send("evm_mine"); + + timelock.executeTransaction( + variables.address, + 0, + "setTreasury(address)", + data, + etaSetTreasury + ); + + await expect(await variables.treasury()).to.be.eq(treasury.address); + }); + }); +} diff --git a/test/unit/before.behavior.ts b/test/unit/before.behavior.ts index 031ae52..26152be 100644 --- a/test/unit/before.behavior.ts +++ b/test/unit/before.behavior.ts @@ -1,28 +1,47 @@ -import { unitPunkMockFixtures, unitFixtureCompoundModel, unitFixtureDaiToken, unitFixtureForge,unitFixtureForge2nd, unitFixtureForge3rd, unitFixtureOwnableStorage, unitFixtureUniswapV2, unitFixtureUniswapFactoryV2, unitFixtureVariables, unitFixtureReferral, unitFixturePunkRewardPool, unitFixtureTreasury, unitFixtureOpTreasury, unitFixtureRecoveryFund } from "../shared/fixtures" +import { + unitPunkMockFixtures, + unitFixtureTimelock, + unitFixtureCompoundModel, + unitFixtureDaiToken, + unitFixtureForge, + unitFixtureForge2nd, + unitFixtureForge3rd, + unitFixtureOwnableStorage, + unitFixtureUniswapV2, + unitFixtureVariables, + unitFixtureTreasury, + unitFixtureOpTreasury, + unitFixtureRecoveryFund, + unitFixtureUniswapFactoryV2, + unitFixtureCompoundModelToReplaced, +} from "../shared/fixtures"; export function beforeBehavior(): void { - before(async function() { - this.contracts = { - punkMock:await this.loadFixture(unitPunkMockFixtures), - ownableStorage:await this.loadFixture(unitFixtureOwnableStorage), - variables:await this.loadFixture(unitFixtureVariables), - forge:await this.loadFixture(unitFixtureForge), - forge2:await this.loadFixture(unitFixtureForge2nd), - forge3:await this.loadFixture(unitFixtureForge3rd), - compoundModel:await this.loadFixture(unitFixtureCompoundModel), - compoundModel2:await this.loadFixture(unitFixtureCompoundModel), - compoundModel3:await this.loadFixture(unitFixtureCompoundModel), - uniswapV2Router:await this.loadFixture(unitFixtureUniswapV2), - uniswapV2Factory:await this.loadFixture(unitFixtureUniswapFactoryV2), - daiContract:await this.loadFixture(unitFixtureDaiToken), - referral:await this.loadFixture(unitFixtureReferral), - rewardPool:await this.loadFixture(unitFixturePunkRewardPool), - treasury:await this.loadFixture(unitFixtureTreasury), - opTreasury:await this.loadFixture(unitFixtureOpTreasury), - grinder:await this.loadFixture(unitFixtureOpTreasury), - recoveryFundMock:await this.loadFixture(unitFixtureRecoveryFund), - } + before(async function () { + this.contracts = { + punkMock: await this.loadFixture(unitPunkMockFixtures), + timelock: await this.loadFixture(unitFixtureTimelock), + ownableStorage: await this.loadFixture(unitFixtureOwnableStorage), + variables: await this.loadFixture(unitFixtureVariables), + forge: await this.loadFixture(unitFixtureForge), + forge2: await this.loadFixture(unitFixtureForge2nd), + forge3: await this.loadFixture(unitFixtureForge3rd), + compoundModelToReplaced: await this.loadFixture(unitFixtureCompoundModelToReplaced), + compoundModel: await this.loadFixture(unitFixtureCompoundModel), + compoundModel2: await this.loadFixture(unitFixtureCompoundModel), + compoundModel3: await this.loadFixture(unitFixtureCompoundModel), + uniswapV2Router: await this.loadFixture(unitFixtureUniswapV2), + daiContract: await this.loadFixture(unitFixtureDaiToken), + treasury: await this.loadFixture(unitFixtureTreasury), + opTreasury: await this.loadFixture(unitFixtureOpTreasury), + grinder: await this.loadFixture(unitFixtureOpTreasury), + recoveryFundMock: await this.loadFixture(unitFixtureRecoveryFund), + uniswapV2Factory:await this.loadFixture(unitFixtureUniswapFactoryV2) + }; - await this.contracts.uniswapV2Factory.createPair( this.contracts.punkMock.address, await this.contracts.uniswapV2Router.WETH() ) - }) -} \ No newline at end of file + await this.contracts.uniswapV2Factory.createPair( + this.contracts.punkMock.address, + await this.contracts.uniswapV2Router.WETH() + ); + }); +} diff --git a/test/unit/index.ts b/test/unit/index.ts index 4e8da22..b220843 100644 --- a/test/unit/index.ts +++ b/test/unit/index.ts @@ -1,46 +1,30 @@ import { solidity } from "ethereum-waffle"; -import { baseContext } from "../shared/contexts" - -import { beforeBehavior } from "./before.behavior" - -import { unitTestOwnableStorage } from "./OwnableStorage/OwnableStorage" -import { unitTestVariables } from "./Variables/Variables" -import { unitTestReferral } from "./Referral/Referral" -import { unitTestTreasury } from "./Treasury/Treasury" - -import { unitTestPunkRewardPool } from "./PunkRewardPool/PunkRewardPool" -import { unitTestCompoundModel } from "./CompoundModel/CompoundModel" - -import { unitTestRecoveryFund } from "./RecoveryFund/RecoveryFund" - -import { unitTestForge } from "./Forge/Forge" -import { unitTestScore } from "./Score/Score" - -import {use} from 'chai'; +import { baseContext } from "../shared/contexts"; +import { beforeBehavior } from "./before.behavior"; +import { use } from "chai"; +import { unitTestOwnableStorage } from "./OwnableStorage/OwnableStorage"; +import { unitTestVariables } from "./Variables/Variables"; +import { unitTestTreasury } from "./Treasury/Treasury"; +import { unitTestCompoundModel } from "./CompoundModel/CompoundModel"; +import { unitTestRecoveryFund } from "./RecoveryFund/RecoveryFund"; +import { unitTestForge } from "./Forge/Forge"; use(solidity); -baseContext("Unit Tests", async function() { - - beforeBehavior(); - - unitTestRecoveryFund(); - - unitTestOwnableStorage(); - - unitTestVariables(); - - unitTestReferral(); +baseContext("Unit Tests", async function () { + beforeBehavior(); - unitTestTreasury(); + unitTestOwnableStorage(); - unitTestPunkRewardPool(); + unitTestVariables(); - unitTestCompoundModel(); + unitTestTreasury(); - unitTestForge(); + unitTestCompoundModel(); - unitTestScore(); + unitTestForge(); -}) \ No newline at end of file + unitTestRecoveryFund(); + +}); diff --git a/types/index.ts b/types/index.ts index 86431df..f4fbcc7 100644 --- a/types/index.ts +++ b/types/index.ts @@ -1,11 +1,9 @@ import { SignerWithAddress } from "@nomiclabs/hardhat-ethers/dist/src/signer-with-address"; import { Forge } from '../typechain/Forge' -import { ForgeEth } from '../typechain/ForgeEth' export interface Contracts { forge: Forge; - forgeEth: ForgeEth, } export interface Signers {