diff --git a/contracts/interfaces/IAddressHolder.sol b/contracts/interfaces/IAddressHolder.sol index 153fef78..ec525cbe 100644 --- a/contracts/interfaces/IAddressHolder.sol +++ b/contracts/interfaces/IAddressHolder.sol @@ -5,12 +5,12 @@ pragma solidity ^0.8.0; interface IAddressHolder { event StateChainGatewayUpdated(address oldStateChainGateway, address newStateChainGateway); event StakingAddressesUpdated( - address oldStFLIP, address oldStMinter, address oldStBurner, - address newStFLIP, + address oldStFLIP, address newStMinter, - address newStBurner + address newStBurner, + address newStFLIP ); event GovernorTransferred(address oldGovernor, address newGovernor); diff --git a/contracts/utils/TokenVestingNoStaking.sol b/contracts/utils/TokenVestingNoStaking.sol index 71c997eb..eb343b21 100644 --- a/contracts/utils/TokenVestingNoStaking.sol +++ b/contracts/utils/TokenVestingNoStaking.sol @@ -14,8 +14,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; * * The vesting schedule is time-based (i.e. using block timestamps as opposed to e.g. block numbers), and * is therefore sensitive to timestamp manipulation (which is something miners can do, to a certain degree). - * Therefore, it is recommended to avoid using short time durations (less than a minute). Typical vesting - * schemes, with a cliff period of a year and a duration of four years, are safe to use. + * Therefore, it is recommended to avoid using short time durations (less than a minute). * */ contract TokenVestingNoStaking is ITokenVestingNoStaking, Shared { @@ -51,7 +50,7 @@ contract TokenVestingNoStaking is ITokenVestingNoStaking, Shared { bool transferableBeneficiary_ ) nzAddr(beneficiary_) { require(cliff_ <= end_, "Vesting: cliff_ after end_"); - require(end_ > block.timestamp, "Vesting: final time is before current time"); + require(block.timestamp < cliff_, "Vesting: cliff before current time"); beneficiary = beneficiary_; revoker = revoker_; diff --git a/contracts/utils/TokenVestingStaking.sol b/contracts/utils/TokenVestingStaking.sol index 01867d36..b5b4db60 100644 --- a/contracts/utils/TokenVestingStaking.sol +++ b/contracts/utils/TokenVestingStaking.sol @@ -22,8 +22,7 @@ import "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; * * The vesting schedule is time-based (i.e. using block timestamps as opposed to e.g. block numbers), and * is therefore sensitive to timestamp manipulation (which is something miners can do, to a certain degree). - * Therefore, it is recommended to avoid using short time durations (less than a minute). Typical vesting - * schemes, with a cliff period of a year and a duration of four years, are safe to use. + * Therefore, it is recommended to avoid using short time durations (less than a minute). * */ contract TokenVestingStaking is ITokenVestingStaking, Shared { @@ -36,6 +35,7 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { address private revoker; // Durations and timestamps are expressed in UNIX time, the same units as block.timestamp. + uint256 public immutable start; uint256 public immutable end; // solhint-disable-next-line var-name-mixedcase @@ -55,6 +55,7 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { /** * @param beneficiary_ address of the beneficiary to whom vested tokens are transferred * @param revoker_ the person with the power to revoke the vesting. Address(0) means it is not revocable. + * @param start_ the unix time when the beneficiary can start staking the tokens. * @param end_ the unix time of the end of the vesting period, everything withdrawable after * @param transferableBeneficiary_ whether the beneficiary address can be transferred * @param addressHolder_ the contract holding the reference address to the ScGateway for staking @@ -63,15 +64,18 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { constructor( address beneficiary_, address revoker_, + uint256 start_, uint256 end_, bool transferableBeneficiary_, IAddressHolder addressHolder_, IERC20 flip_ ) nzAddr(beneficiary_) nzAddr(address(addressHolder_)) nzAddr(address(flip_)) { - require(end_ > block.timestamp, "Vesting: final time is before current time"); + require(start_ <= end_, "Vesting: start_ after end_"); + require(block.timestamp < start_, "Vesting: start before current time"); beneficiary = beneficiary_; revoker = revoker_; + start = start_; end = end_; transferableBeneficiary = transferableBeneficiary_; addressHolder = addressHolder_; @@ -90,7 +94,10 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { * @param nodeID the nodeID to fund. * @param amount the amount of FLIP out of the current funds in this contract. */ - function fundStateChainAccount(bytes32 nodeID, uint256 amount) external override onlyBeneficiary notRevoked { + function fundStateChainAccount( + bytes32 nodeID, + uint256 amount + ) external override onlyBeneficiary notRevoked afterStart { address stateChainGateway = addressHolder.getStateChainGateway(); FLIP.approve(stateChainGateway, amount); @@ -102,7 +109,7 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { * It is expected that an amount of stFLIP will be minted to this contract. * @param amount the amount of FLIP to stake to the staking provider. */ - function stakeToStProvider(uint256 amount) external override onlyBeneficiary notRevoked { + function stakeToStProvider(uint256 amount) external override onlyBeneficiary notRevoked afterStart { address stMinter = addressHolder.getStakingAddress(); FLIP.approve(stMinter, amount); @@ -156,7 +163,7 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { /** * @notice Allows the revoker to revoke the vesting and stop the beneficiary from releasing any - * tokens if the vesting period has not bene completed. Any staked tokens at the time of + * tokens if the vesting period has not been completed. Any staked tokens at the time of * revoking can be retrieved by the revoker upon unstaking via `retrieveRevokedFunds`. * @param token ERC20 token which is being vested. */ @@ -254,4 +261,9 @@ contract TokenVestingStaking is ITokenVestingStaking, Shared { require(!revoked, "Vesting: token revoked"); _; } + + modifier afterStart() { + require(block.timestamp >= start, "Vesting: not started"); + _; + } } diff --git a/scripts/deploy_tokenVestings.py b/scripts/deploy_tokenVestings.py index b499b738..25186995 100644 --- a/scripts/deploy_tokenVestings.py +++ b/scripts/deploy_tokenVestings.py @@ -1,6 +1,7 @@ import sys import os import csv +import time sys.path.append(os.path.abspath("tests")) from consts import * @@ -22,6 +23,7 @@ network, web3, ) +from datetime import datetime _project = project.get_loaded_projects()[0] IAirdropContract = _project.interface.IAirdrop @@ -31,6 +33,7 @@ # parameters. The rest of the lines should be the values for each parameter. It should contain the # parameters described in the order dictionary below but it can have others, which will be ignored. VESTING_INFO_FILE = os.environ["VESTING_INFO_FILE"] +DEPLOYMENT_INFO_FILE = os.environ["DEPLOYMENT_INFO_FILE"] columns = [ "Full name/Company Name", "Email Address", @@ -44,9 +47,13 @@ ] options_lockup_type = ["Option A", "Option B", "Airdrop"] -# TODO: Ensure vesting schedule is correct. Leaving cliff to 1 day for safety -vesting_time_cliff = DAY -vesting_time_end = vesting_time_cliff + YEAR +# TODO: Ensure vesting schedule is correct, currently set to 1 year +vesting_period = YEAR +# Vesting schedule +noStaking_cliff = int(os.environ["STAKING_CLIFF_TIMESTAMP"]) +noStaking_end = noStaking_cliff + vesting_period +staking_start = int(os.environ["NO_STAKING_START_TIMESTAMP"]) +staking_end = staking_start + vesting_period AUTONOMY_SEED = os.environ["SEED"] @@ -60,7 +67,8 @@ def main(): - # TODO: Assumption that revoker and Address Holder's governor are the same + revoker_address = os.environ["REVOKER_ADDRESS"] + # AddressHolder governor governor = os.environ["GOV_KEY"] sc_gateway_address = os.environ["SC_GATEWAY_ADDRESS"] flip_address = os.environ["FLIP_ADDRESS"] @@ -75,203 +83,294 @@ def main(): number_noStaking = 0 flip_total_E18 = 0 - with open(VESTING_INFO_FILE, newline="") as csvfile: - reader = csv.reader(csvfile, delimiter=",", quotechar='"') - - # Check the first row - parameter names - first_row = next(reader) - for position, parameter_name in enumerate(columns): - assert ( - first_row[position] == parameter_name - ), f"Incorrect parameter name: expected {parameter_name}, but got {first_row[position]}" + if not os.path.isfile(DEPLOYMENT_INFO_FILE): + prompt_user_continue_or_break("Starting deployment from scratch", True) + + with open(VESTING_INFO_FILE, newline="") as csvfile: + reader = csv.reader(csvfile, delimiter=",", quotechar='"') + + # Check the first row - parameter names + first_row = next(reader) + for position, parameter_name in enumerate(columns): + assert ( + first_row[position] == parameter_name + ), f"Incorrect parameter name: expected {parameter_name}, but got {first_row[position]}" + + # Read the rest of the rows + for row in reader: + assert len(row) == len( + columns + ), f"Incorrect number of parameters: expected {len(columns)}, but got {len(row)}" + + # Check beneficiary + beneficiary = row[columns.index("Beneficiary Wallet Address")] + + if beneficiary == "": + print(f"Skipping row with no beneficiary {row}") + continue + + assert web3.isAddress( + beneficiary + ), f"Incorrect beneficiary address {beneficiary}, {row}" + + # Check lockup type + lockup_type = row[columns.index("Final Choice Lock up Schedule")] + + if lockup_type == options_lockup_type[0]: + number_staking += 1 + elif lockup_type == options_lockup_type[1]: + number_noStaking += 1 + elif lockup_type == options_lockup_type[2]: + # Skip the ones marked as Airdrop + print(f"Skipping row marked as Airdrop {row}") + continue + else: + raise Exception(f"Incorrect lockup type parameter {lockup_type}") + + # Check transferability + transferable = row[ + columns.index("Address transfer enabled in smart contract?") + ] + + if transferable in ["yes", "Yes"]: + transferable = True + elif transferable in ["no", "No"]: + transferable = False + elif transferable in ["", "No answer", "No Answer", "no answer"]: + # For unknwons and undetermined, we default to False + transferable = False + else: + raise Exception( + f"Incorrect transferability parameter {transferable}" + ) + + # Check revokability + revokable = row[columns.index("Yeet Function?")] + + if revokable == "Enabled": + revoker = revoker_address + elif revokable == "Disabled": + revoker = ZERO_ADDR + elif revokable == "": + # For undetermined default to disabled + revoker = ZERO_ADDR + else: + raise Exception(f"Incorrect revokability parameter {revokable}") + + # Check amount + amount = int(row[columns.index("# tokens")].replace(",", "")) + amount_E18 = amount * E_18 + + vesting_list.append( + [beneficiary, amount_E18, lockup_type, transferable, revoker] + ) + + flip_total_E18 += amount_E18 + + print("Deployer balance: ", flip.balanceOf(DEPLOYER) // E_18) + assert flip_total_E18 <= flip.balanceOf( + DEPLOYER + ), "Not enough FLIP tokens to fund the vestings" + expected_final_balance = flip.balanceOf(DEPLOYER) - flip_total_E18 + + # For live deployment, add a confirmation step to allow the user to verify the row. + print(f"DEPLOYER = {DEPLOYER}") + print(f"FLIP = {flip_address}") + print(f"REVOKER = {revoker_address}") + print(f"AddressHolder GOVERNOR = {governor}") + + print(f"SC_GATEWAY_ADDRESS = {sc_gateway_address}") + print(f"ST_MINTER_ADDRESS = {stMinter_address}") + print(f"ST_BURNER_ADDRESS = {stBurner_address}") + print(f"ST_FLIP_ADDRESS = {stFlip_address}") + + print(f"Number of staking vesting contracts = {number_staking}") + print(f"Number of non-staking vesting contracts = {number_noStaking}") + print(f"Total number of contracts = {number_staking+number_noStaking}") + print(f"Total amount of FLIP to vest = {flip_total_E18//E_18:,}") + print(f"Initial deployer's FLIP balance = {flip.balanceOf(DEPLOYER):,}") + print( + f"Initial deployer's FLIP balance // E_18 = {flip.balanceOf(DEPLOYER)//E_18:,}" + ) + print(f"Final deployer's FLIP balance = {expected_final_balance:,}") + print( + f"Final deployer's FLIP balance // E_18 = {expected_final_balance // E_18:,}" + ) - # Read the rest of the rows - for row in reader: - assert len(row) == len( - columns - ), f"Incorrect number of parameters: expected {len(columns)}, but got {len(row)}" + # Calculate final vesting times + current_time = chain.time() + assert staking_start > current_time + assert staking_end > current_time + assert noStaking_cliff > current_time + assert noStaking_end > current_time + relative_staking_start = staking_start - current_time + relative_staking_end = staking_end - current_time + relative_noStaking_cliff = noStaking_cliff - current_time + relative_noStaking_end = noStaking_end - current_time - # Check that all rows are valid - lockup_type = row[columns.index("Final Choice Lock up Schedule")] + print(f"Current date = {datetime.fromtimestamp(current_time)} ({current_time})") - if lockup_type == options_lockup_type[0]: - number_staking += 1 - elif lockup_type == options_lockup_type[1]: - number_noStaking += 1 - elif lockup_type == options_lockup_type[2]: - # Skip the ones marked as Airdrop - continue - else: - raise Exception(f"Incorrect lockup type parameter {lockup_type}") - - beneficiary = row[columns.index("Beneficiary Wallet Address")] - amount = int(row[columns.index("# tokens")].replace(",", "")) - transferable = row[ - columns.index("Address transfer enabled in smart contract?") - ] - revokable = row[columns.index("Yeet Function?")] - - assert web3.isAddress( - beneficiary - ), f"Incorrect beneficiary address {beneficiary}" - - if transferable in ["yes", "Yes"]: - transferable = True - elif transferable in ["no", "No"]: - transferable = False - else: - raise Exception(f"Incorrect transferability parameter {transferable}") + print("Staking vesting parameters") + print( + f" - Staking starts in {relative_staking_start//YEAR} year(s), {(relative_staking_start % YEAR)//MONTH} month(s), {((relative_staking_start % YEAR)%MONTH)//DAY} day(s) and {(((relative_staking_start % YEAR)%MONTH)%DAY)//HOUR} hour(s)" + ) + print( + f" - Staking start date = {datetime.fromtimestamp(staking_start)} ({staking_start})" + ) - if revokable == "Enabled": - revoker = governor - elif revokable == "Disabled": - revoker = ZERO_ADDR - else: - raise Exception(f"Incorrect revokability parameter {revokable}") + print( + f" - Staking ends in {relative_staking_end//YEAR} year(s), {(relative_staking_end % YEAR)//MONTH} month(s) and {((relative_staking_end % YEAR)%MONTH)//DAY} day(s)" + ) + print( + f" - Staking end date = {datetime.fromtimestamp(staking_end)} ({staking_end})" + ) - amount_E18 = amount * E_18 + print("Non-Staking vesting parameters") + print( + f" - Cliff in {relative_noStaking_cliff//YEAR} year(s), {(relative_noStaking_cliff % YEAR)//MONTH} month(s) and {((relative_noStaking_cliff % YEAR)%MONTH)//DAY} day(s) and {(((relative_noStaking_cliff % YEAR)%MONTH)%DAY)//HOUR} hour(s)" + ) + print( + f" - Cliff date = {datetime.fromtimestamp(noStaking_cliff)} ({noStaking_cliff})" + ) - vesting_list.append( - [beneficiary, amount_E18, lockup_type, transferable, revoker] - ) + print( + f" - End in {relative_noStaking_end//YEAR} year(s), {(relative_noStaking_end % YEAR)//MONTH} month(s) and {((relative_noStaking_end % YEAR)%MONTH)//DAY} day(s)" + ) + print( + f" - End date = {datetime.fromtimestamp(noStaking_end)} ({noStaking_end})" + ) - flip_total_E18 += amount_E18 - - # Vesting schedule - current_time = chain.time() - cliff = current_time + vesting_time_cliff - end = current_time + vesting_time_end - - print("Deployer balance: ", flip.balanceOf(DEPLOYER) // E_18) - assert flip_total_E18 <= flip.balanceOf( - DEPLOYER - ), "Not enough FLIP tokens to fund the vestings" - final_balance = (flip.balanceOf(DEPLOYER) - flip_total_E18) // E_18 - - # For live deployment, add a confirmation step to allow the user to verify the row. - print(f"DEPLOYER = {DEPLOYER}") - print(f"FLIP = {flip_address}") - print(f"GOVERNOR & REVOKER = {governor}") - - print(f"SC_GATEWAY_ADDRESS = {sc_gateway_address}") - print(f"ST_MINTER_ADDRESS = {stMinter_address}") - print(f"ST_BURNER_ADDRESS = {stBurner_address}") - print(f"ST_FLIP_ADDRESS = {stFlip_address}") - - print(f"Number of staking vesting contracts = {number_staking}") - print(f"Number of non-staking vesting contracts = {number_noStaking}") - print(f"Total number of contracts = {number_staking+number_noStaking}") - print( - f"Vesting cliff (only for non-staking) = {vesting_time_cliff//YEAR} years, {(vesting_time_cliff % YEAR)//MONTH} months and {((vesting_time_cliff % YEAR)%MONTH)//DAY} days" - ) - print( - f"Vesting end (staking & non-staking) = {vesting_time_end//YEAR} years, {(vesting_time_end % YEAR)//MONTH} months and {((vesting_time_end % YEAR)%MONTH)//DAY} days" - ) - print(f"Total amount of FLIP to vest = {flip_total_E18//E_18:,}") - print(f"Initial deployer's FLIP balance = {flip.balanceOf(DEPLOYER)//E_18:,}") - print(f"Final deployer's FLIP balance = {final_balance:,}") + prompt_user_continue_or_break("Deployment with the parameter above", True) - prompt_user_continue_or_break("Deployment with the parameter above", True) + if chain.id == 1: + prompt_user_continue_or_break( + "\n[WARNING] You are about to deploy to the mainnet", + False, + ) - if chain.id == 1: - prompt_user_continue_or_break( - "\n[WARNING] You are about to deploy to the mainnet", - False, + # Deploying the address Holder + addressHolder = deploy_addressHolder( + DEPLOYER, + AddressHolder, + governor, + sc_gateway_address, + stMinter_address, + stBurner_address, + stFlip_address, ) - # Deploying the address Holder - addressHolder = deploy_addressHolder( - DEPLOYER, - AddressHolder, - governor, - sc_gateway_address, - stMinter_address, - stBurner_address, - stFlip_address, - ) - - # Deploy all the vesting contracts - for vesting in vesting_list: - ( - beneficiary, - amount_E18, - lockup_type, - transferable_beneficiary, - revoker, - ) = vesting - - if lockup_type == options_lockup_type[0]: + # AddressHolder deployment will already wait for several confirmations + print("Address holder deployed at: ", addressHolder.address) - tv = deploy_tokenVestingStaking( - DEPLOYER, - TokenVestingStaking, + # Deploy all the vesting contracts + for vesting in vesting_list: + ( beneficiary, - revoker, - end, + amount_E18, + lockup_type, transferable_beneficiary, - addressHolder.address, - flip, - ) + revoker, + ) = vesting - elif lockup_type == options_lockup_type[1]: - tv = deploy_tokenVestingNoStaking( - DEPLOYER, - TokenVestingNoStaking, + if lockup_type == options_lockup_type[0]: + + tv = deploy_tokenVestingStaking( + DEPLOYER, + TokenVestingStaking, + beneficiary, + revoker, + staking_start, + staking_end, + transferable_beneficiary, + addressHolder.address, + flip, + ) + + elif lockup_type == options_lockup_type[1]: + tv = deploy_tokenVestingNoStaking( + DEPLOYER, + TokenVestingNoStaking, + beneficiary, + revoker, + noStaking_cliff, + noStaking_end, + transferable_beneficiary, + ) + else: + raise Exception( + f"Incorrect lockup type parameter {lockup_type}. Should have been dropped earlier" + ) + vesting.append(tv) + + # Wait to make sure all contracts are deployed and we don't get a failure when doing checks + if chain.id not in [eth_localnet, arb_localnet, hardhat]: + print("Waiting for a short time for safety...") + time.sleep(12) + + print("Checking all the transaction receipts...") + for vesting in vesting_list: + web3.eth.wait_for_transaction_receipt(vesting[5].tx.txid) + + # Write the data to a CSV file + print(f"Storing deployment info in {DEPLOYMENT_INFO_FILE}") + with open(DEPLOYMENT_INFO_FILE, "w", newline="") as csvfile: + writer = csv.writer(csvfile) + writer.writerows(vesting_list) + + print("Verifying correct deployment of vesting contracts...") + for vesting in vesting_list: + ( beneficiary, - revoker, - cliff, - end, + amount_E18, + lockup_type, transferable_beneficiary, - ) - else: - raise Exception( - f"Incorrect lockup type parameter {lockup_type}. Should have been dropped earlier" - ) - vesting.append(tv) - - # Wait to make sure all contracts are deployed and we don't get a failure when doing checks - print("Waiting for all the transaction receipts...") - for vesting in vesting_list: - web3.eth.wait_for_transaction_receipt(vesting[-1].tx.txid) + revoker, + tv, + ) = vesting - print("Verifying correct deployment of vesting contracts...") - for vesting in vesting_list: - ( - beneficiary, - amount_E18, - lockup_type, - transferable_beneficiary, - revoker, - tv, - ) = vesting + if lockup_type == options_lockup_type[0]: + assert ( + tv.addressHolder() == addressHolder.address + ), "Address holder not set correctly" + assert tv.FLIP() == flip.address, "FLIP not set correctly" + assert tv.start() == staking_start, "Staking end not set correctly" + assert tv.end() == staking_end, "NoStaking end not set correctly" - if lockup_type == options_lockup_type[0]: - assert ( - tv.addressHolder() == addressHolder.address - ), "Address holder not set correctly" - assert tv.FLIP() == flip.address, "FLIP not set correctly" - else: - assert tv.cliff() == cliff, "Cliff not set correctly" + else: + assert ( + tv.cliff() == noStaking_cliff + ), "NoStaking Cliff not set correctly" + assert tv.end() == noStaking_end, "NoStaking end not set correctly" - assert tv.getBeneficiary() == beneficiary, "Beneficiary not set correctly" - assert tv.getRevoker() == revoker, "Revoker not set correctly" + assert tv.getBeneficiary() == beneficiary, "Beneficiary not set correctly" + assert tv.getRevoker() == revoker, "Revoker not set correctly" - assert ( - tv.transferableBeneficiary() == transferable_beneficiary - ), "Transferability not set correctly" - assert tv.end() == end, "End not set correctly" + assert ( + tv.transferableBeneficiary() == transferable_beneficiary + ), "Transferability not set correctly" prompt_user_continue_or_break( "Deployment of contracts finalized. Proceeding with token airdrop", True ) + vesting_list = [] + with open(DEPLOYMENT_INFO_FILE, "r") as csvfile: + reader = csv.reader(csvfile) + for row in reader: + # Format values appropriately + row[1] = int(row[1]) + row[3] = True if row[3] == "True" else False + vesting_list.append(row) + # Multisend using wenTokens optimized airdrop tool - vesting_addresses = [vesting[-1].address for vesting in vesting_list] + vesting_addresses = [vesting[5] for vesting in vesting_list] vesting_amounts_E18 = [vesting[1] for vesting in vesting_list] assert len(vesting_addresses) == len(vesting_amounts_E18) + if "expected_final_balance" not in locals(): + expected_final_balance = flip.balanceOf(DEPLOYER) - sum(vesting_amounts_E18) + total_amount_E18 = sum(vesting_amounts_E18) - assert total_amount_E18 == flip_total_E18 # Same address in mainnet and test networks airdrop_contract = IAirdropContract(address_wenTokens) @@ -298,20 +397,20 @@ def main(): lockup_type, transferable_beneficiary, revoker, - tv, + tv_address, ) = vesting assert ( - flip.balanceOf(tv.address) == amount_E18 + flip.balanceOf(tv_address) == amount_E18 ), "Tokens not transferred correctly" print( - f"- {str(i):>3}: Lockup type {lockup_type}, contract with beneficiary {beneficiary}, amount {str(amount_E18//E_18):>8} FLIP, transferability {str(transferable_beneficiary):<5}, revoker {str(revoker):<5}, deployed at {tv.address}" + f"- {str(i):>3}: Lockup type {lockup_type}, contract with beneficiary {beneficiary}, amount {str(amount_E18//E_18):>8} FLIP, transferability {str(transferable_beneficiary):<5}, revoker {str(revoker):<5}, deployed at {tv_address}" ) print("\nšŸ˜ŽšŸ˜Ž Vesting contracts deployed successfully! šŸ˜ŽšŸ˜Ž\n") + assert expected_final_balance == flip.balanceOf(DEPLOYER), "Incorrect final balance" - assert final_balance == flip.balanceOf(DEPLOYER) // E_18, "Incorrect final balance" - - print(f"Final deployer's FLIP balance = {final_balance:,}") + print(f"Final deployer's FLIP balance = {expected_final_balance}") + print(f"Final deployer's FLIP balance // E_18 = {expected_final_balance // E_18}") def release(): @@ -331,7 +430,7 @@ def fund(): def updateStakingAddresses(): - addressHolder_address = os.environ["ADDERSS_HOLDER_ADDRESS"] + addressHolder_address = os.environ["ADDRESS_HOLDER_ADDRESS"] stMinter_address = os.environ["ST_MINTER_ADDRESS"] stBurner_address = os.environ["ST_BURNER_ADDRESS"] stFlip_address = os.environ["ST_FLIP_ADDRESS"] @@ -344,7 +443,7 @@ def updateStakingAddresses(): def updateStateChainGateway(): - addressHolder_address = os.environ["ADDERSS_HOLDER_ADDRESS"] + addressHolder_address = os.environ["ADDRESS_HOLDER_ADDRESS"] address_holder = AddressHolder.at(f"0x{cleanHexStr(addressHolder_address)}") sc_gateway_address = os.environ["SC_GATEWAY_ADDRESS"] @@ -366,3 +465,13 @@ def unstake_from_stProvider(): tx = token_vesting.unstakeFromStProvider(1 * 10**18, {"from": DEPLOYER}) tx.info() + + +def revoke(): + token_vesting_address = os.environ["TOKEN_VESTING_ADDRESS"] + flip_address = os.environ["FLIP_ADDRESS"] + + token_vesting = TokenVestingStaking.at(f"0x{cleanHexStr(token_vesting_address)}") + + tx = token_vesting.revoke(flip_address, {"from": DEPLOYER}) + tx.info() diff --git a/tests/conftest.py b/tests/conftest.py index 65273e44..6a3c77f2 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -177,12 +177,10 @@ def addressHolder(cf, addrs, AddressHolder, mockStProvider): @pytest.fixture(scope="module") def tokenVestingNoStaking(addrs, cf, TokenVestingNoStaking): - # This was hardcoded to a timestamp, but ganache uses real-time when we run # the tests, so we should use relative values instead of absolute ones - start = getChainTime() - cliff = start + QUARTER_YEAR - end = start + QUARTER_YEAR + YEAR + cliff = getChainTime() + QUARTER_YEAR + end = cliff + YEAR total = MAX_TEST_FUND @@ -204,9 +202,8 @@ def tokenVestingNoStaking(addrs, cf, TokenVestingNoStaking): @pytest.fixture(scope="module") def tokenVestingStaking(addrs, cf, TokenVestingStaking, addressHolder): - # This was hardcoded to a timestamp, but ganache uses real-time when we run - # the tests, so we should use relative values instead of absolute ones - start = getChainTime() + # Add small delay to ensure start > current timestamp + start = getChainTime() + 10 end = start + QUARTER_YEAR + YEAR total = MAX_TEST_FUND @@ -219,12 +216,17 @@ def tokenVestingStaking(addrs, cf, TokenVestingStaking, addressHolder): TokenVestingStaking, addrs.BENEFICIARY, addrs.REVOKER, + start, end, BENEF_TRANSF, addressHolder, cf.flip, ) - return tv, end, total + + # Wait for the staking period to start + chain.sleep(10) + + return tv, start, end, total # Deploy CFReceiver Mock contracts for testing purposes diff --git a/tests/consts.py b/tests/consts.py index aa6396f1..a4392210 100644 --- a/tests/consts.py +++ b/tests/consts.py @@ -155,7 +155,10 @@ def syncNonce(keyManager): REV_MSG_NOT_BENEFICIARY = "Vesting: not the beneficiary" REV_MSG_BENEF_NOT_TRANSF = "Vesting: beneficiary not transferrable" REV_MSG_CLIFF_AFTER_END = "Vesting: cliff_ after end_" -REV_MSG_INVALID_FINAL_TIME = "Vesting: final time is before current time" +REV_MSG_START_AFTER_END = "Vesting: start_ after end_" +REV_MSG_INVALID_CLIFF_TIME = "Vesting: cliff before current time" +REV_MSG_INVALID_START_TIME = "Vesting: start before current time" +REV_MSG_NOT_STARTED = "Vesting: not started" REV_MSG_TOKEN_REVOKED = "Vesting: token revoked" REV_MSG_SCGREF_REV_GOV = "AddrHolder: not the governor" diff --git a/tests/deploy.py b/tests/deploy.py index dafe0bca..9517d959 100644 --- a/tests/deploy.py +++ b/tests/deploy.py @@ -298,6 +298,7 @@ def deploy_tokenVestingStaking( TokenVestingStaking, beneficiary, revoker, + start, end, transferableBeneficiary, addressHolder_address, @@ -306,6 +307,7 @@ def deploy_tokenVestingStaking( tokenVestingStaking = TokenVestingStaking.deploy( beneficiary, revoker, + start, end, transferableBeneficiary, addressHolder_address, @@ -322,4 +324,4 @@ def deploy_tokenVestingStaking( # nor localnets/devnets - that is with hardhat (including forks), with id 31337, and geth image, with id 10997. def transaction_params(): network.priority_fee("1 gwei") - return 1 if chain.id in [hardhat, eth_localnet, arb_localnet] else 4 + return 1 if chain.id in [hardhat, eth_localnet, arb_localnet] else 3 diff --git a/tests/shared_tests_tokenVesting.py b/tests/shared_tests_tokenVesting.py index 1247e2c5..a268f041 100644 --- a/tests/shared_tests_tokenVesting.py +++ b/tests/shared_tests_tokenVesting.py @@ -11,9 +11,11 @@ def release_revert(tv, cf, address): tv.release(cf.flip, {"from": address}) -def check_state_staking(stateChainGateway, addressHolder, tv, *args): +def check_state_staking(stateChainGateway, addressHolder, tv, start, *args): assert tv.addressHolder() == addressHolder assert addressHolder.getStateChainGateway() == stateChainGateway + assert tv.start() == start + check_state(tv, *args) diff --git a/tests/token_vesting/addressHolder/test_addressHolder.py b/tests/token_vesting/addressHolder/test_addressHolder.py index 018d379d..596b0a18 100644 --- a/tests/token_vesting/addressHolder/test_addressHolder.py +++ b/tests/token_vesting/addressHolder/test_addressHolder.py @@ -67,13 +67,13 @@ def test_reference_updateReference(addrs, cf, addressHolder): def test_reference_release(addrs, cf, tokenVestingStaking, addressHolder): - tv, _, _ = tokenVestingStaking + tv, _, end, _ = tokenVestingStaking assert cf.flip.balanceOf(addrs.BENEFICIARY) == 0 tv.fundStateChainAccount(JUNK_INT, MAX_TEST_FUND, {"from": addrs.BENEFICIARY}) - chain.sleep(YEAR + QUARTER_YEAR) + chain.sleep(end) # Update the refernce to a wrong contract addressHolder.updateStateChainGateway(NON_ZERO_ADDR, {"from": addrs.DEPLOYER}) diff --git a/tests/token_vesting/addressHolder/test_staking_upgradedGateway.py b/tests/token_vesting/addressHolder/test_staking_upgradedGateway.py index f8107527..543de2db 100644 --- a/tests/token_vesting/addressHolder/test_staking_upgradedGateway.py +++ b/tests/token_vesting/addressHolder/test_staking_upgradedGateway.py @@ -5,7 +5,7 @@ def test_stake_upgrade_failure(addrs, cf, tokenVestingStaking, addressHolder): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking tx = tv.fundStateChainAccount(JUNK_HEX, MIN_FUNDING, {"from": addrs.BENEFICIARY}) @@ -35,7 +35,7 @@ def test_stake_upgrade( FLIP, DeployerStateChainGateway, ): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking tx = tv.fundStateChainAccount(JUNK_HEX, MIN_FUNDING, {"from": addrs.BENEFICIARY}) diff --git a/tests/token_vesting/constructor/test_tokenVesting_constructor.py b/tests/token_vesting/constructor/test_tokenVesting_constructor.py index e525de6d..cd4951d7 100644 --- a/tests/token_vesting/constructor/test_tokenVesting_constructor.py +++ b/tests/token_vesting/constructor/test_tokenVesting_constructor.py @@ -1,11 +1,10 @@ from consts import * -import time from brownie import reverts from shared_tests_tokenVesting import * -start = time.time() +start = getChainTime() cliff = start + int(YEAR / 2) -end = start + YEAR +end = cliff + YEAR def test_tokenVesting_constructor_cliff( @@ -35,6 +34,7 @@ def test_tokenVesting_constructor_cliff( TokenVestingStaking, addrs.BENEFICIARY, addrs.REVOKER, + cliff, end, BENEF_NON_TRANSF, addressHolder, @@ -44,6 +44,7 @@ def test_tokenVesting_constructor_cliff( cf.stateChainGateway, addressHolder, tv, + cliff, addrs.BENEFICIARY, addrs.REVOKER, addrs.REVOKER != ZERO_ADDR, @@ -69,6 +70,7 @@ def test_tokenVesting_constructor_noRevoker( addrs.BENEFICIARY, ZERO_ADDR, end, + end, BENEF_TRANSF, addressHolder, NON_ZERO_ADDR, @@ -92,6 +94,7 @@ def test_tokenVesting_constructor_rev_beneficiary( TokenVestingStaking, ZERO_ADDR, addrs.REVOKER, + cliff, end, BENEF_TRANSF, addressHolder, @@ -103,6 +106,7 @@ def test_tokenVesting_constructor_rev_beneficiary( TokenVestingStaking, NON_ZERO_ADDR, addrs.REVOKER, + cliff, end, BENEF_TRANSF, addressHolder, @@ -110,7 +114,9 @@ def test_tokenVesting_constructor_rev_beneficiary( ) -def test_tokenVesting_constructor_rev_end_0(addrs, TokenVestingNoStaking): +def test_tokenVesting_constructor_rev_end_0( + addrs, TokenVestingNoStaking, TokenVestingStaking +): with reverts(REV_MSG_CLIFF_AFTER_END): addrs.DEPLOYER.deploy( TokenVestingNoStaking, @@ -121,9 +127,32 @@ def test_tokenVesting_constructor_rev_end_0(addrs, TokenVestingNoStaking): BENEF_NON_TRANSF, ) + with reverts(REV_MSG_START_AFTER_END): + addrs.DEPLOYER.deploy( + TokenVestingStaking, + NON_ZERO_ADDR, + addrs.REVOKER, + getChainTime(), + getChainTime() - 1, + BENEF_TRANSF, + NON_ZERO_ADDR, + NON_ZERO_ADDR, + ) + with reverts(REV_MSG_NZ_ADDR): + addrs.DEPLOYER.deploy( + TokenVestingStaking, + NON_ZERO_ADDR, + addrs.REVOKER, + cliff, + 0, + BENEF_TRANSF, + NON_ZERO_ADDR, + ZERO_ADDR, + ) + def test_tokenVesting_constructor_rev_cliff_not_before_end( - addrs, TokenVestingNoStaking + addrs, TokenVestingNoStaking, TokenVestingStaking ): with reverts(REV_MSG_CLIFF_AFTER_END): addrs.DEPLOYER.deploy( @@ -135,9 +164,23 @@ def test_tokenVesting_constructor_rev_cliff_not_before_end( BENEF_TRANSF, ) + with reverts(REV_MSG_START_AFTER_END): + addrs.DEPLOYER.deploy( + TokenVestingStaking, + NON_ZERO_ADDR, + addrs.REVOKER, + cliff, + cliff - 1, + BENEF_TRANSF, + NON_ZERO_ADDR, + NON_ZERO_ADDR, + ) + -def test_tokenVesting_constructor_rev_end_before_now(addrs, TokenVestingNoStaking): - with reverts(REV_MSG_INVALID_FINAL_TIME): +def test_tokenVesting_constructor_rev_cliff_before_now( + addrs, TokenVestingNoStaking, TokenVestingStaking +): + with reverts(REV_MSG_INVALID_CLIFF_TIME): addrs.DEPLOYER.deploy( TokenVestingNoStaking, addrs.BENEFICIARY, @@ -147,6 +190,18 @@ def test_tokenVesting_constructor_rev_end_before_now(addrs, TokenVestingNoStakin BENEF_TRANSF, ) + with reverts(REV_MSG_INVALID_START_TIME): + addrs.DEPLOYER.deploy( + TokenVestingStaking, + NON_ZERO_ADDR, + addrs.REVOKER, + cliff - (YEAR * 2), + end - (YEAR * 2), + BENEF_TRANSF, + NON_ZERO_ADDR, + NON_ZERO_ADDR, + ) + def test_tokenVesting_constructor_rev_stateChainGateway(addrs, TokenVestingStaking): with reverts(REV_MSG_NZ_ADDR): @@ -154,6 +209,7 @@ def test_tokenVesting_constructor_rev_stateChainGateway(addrs, TokenVestingStaki TokenVestingStaking, addrs.BENEFICIARY, addrs.REVOKER, + start + 10, end, BENEF_NON_TRANSF, ZERO_ADDR, @@ -162,16 +218,40 @@ def test_tokenVesting_constructor_rev_stateChainGateway(addrs, TokenVestingStaki def test_tokenVesting_constructor_rev_eoa(addrs, TokenVestingStaking): - tv = addrs.DEPLOYER.deploy( TokenVestingStaking, addrs.BENEFICIARY, addrs.REVOKER, + start + 100, end, BENEF_NON_TRANSF, NON_ZERO_ADDR, NON_ZERO_ADDR, ) + chain.sleep(100) # Reference contract is an eoa with reverts("Transaction reverted without a reason string"): tv.fundStateChainAccount(JUNK_INT, 1, {"from": addrs.BENEFICIARY}) + + +def test_tokenVesting_constructor_rev_not_started( + addrs, TokenVestingStaking, addressHolder, cf +): + tv = addrs.DEPLOYER.deploy( + TokenVestingStaking, + addrs.BENEFICIARY, + addrs.REVOKER, + start + 100, + end, + BENEF_NON_TRANSF, + addressHolder, + cf.flip, + ) + + # Reference contract is an eoa + with reverts(REV_MSG_NOT_STARTED): + tv.fundStateChainAccount(JUNK_INT, 1, {"from": addrs.BENEFICIARY}) + + # Reference contract is an eoa + with reverts(REV_MSG_NOT_STARTED): + tv.stakeToStProvider(1, {"from": addrs.BENEFICIARY}) diff --git a/tests/token_vesting/funding/test_funding.py b/tests/token_vesting/funding/test_funding.py index 45011a3e..2b142f97 100644 --- a/tests/token_vesting/funding/test_funding.py +++ b/tests/token_vesting/funding/test_funding.py @@ -10,7 +10,7 @@ ) def test_fundStateChainAccount(addrs, tokenVestingStaking, st_nodeID, st_amount, cf): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking st_nodeID = web3.toHex(st_nodeID) @@ -30,8 +30,8 @@ def test_fundStateChainAccount(addrs, tokenVestingStaking, st_nodeID, st_amount, assert tx.events["Funded"][0].values() == (st_nodeID, st_amount, tv) -def test_fund_rev_beneficiary(a, addrs, tokenVestingStaking): - tv, _, _ = tokenVestingStaking +def test_fund_rev_not_beneficiary(a, addrs, tokenVestingStaking): + tv, _, _, _ = tokenVestingStaking for ad in a: if ad != addrs.BENEFICIARY: @@ -39,13 +39,14 @@ def test_fund_rev_beneficiary(a, addrs, tokenVestingStaking): tv.fundStateChainAccount(5, 10, {"from": ad}) -def test_fund_rev_beneficiary(addrs, TokenVestingStaking, addressHolder, cf): +def test_fund_rev_flip_addr(addrs, TokenVestingStaking, addressHolder, cf): tv = addrs.DEPLOYER.deploy( TokenVestingStaking, addrs.BENEFICIARY, addrs.REVOKER, - time.time() + YEAR, + getChainTime() + 2, + getChainTime() + YEAR, BENEF_NON_TRANSF, addressHolder, NON_ZERO_ADDR, diff --git a/tests/token_vesting/release/test_release_staking.py b/tests/token_vesting/release/test_release_staking.py index 7512ecc4..8481b4a4 100644 --- a/tests/token_vesting/release/test_release_staking.py +++ b/tests/token_vesting/release/test_release_staking.py @@ -5,14 +5,14 @@ def test_release_rev_no_tokens(addrs, cf, tokenVestingStaking): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking release_revert(tv, cf, addrs.BENEFICIARY) @given(st_sleepTime=strategy("uint256", max_value=YEAR * 2)) def test_release(addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime): - tv, end, total = tokenVestingStaking + tv, start, end, total = tokenVestingStaking assert cf.flip.balanceOf(addrs.BENEFICIARY) == 0 @@ -31,6 +31,7 @@ def test_release(addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime): cf.stateChainGateway, addressHolder, tv, + start, addrs.BENEFICIARY, addrs.REVOKER, True, @@ -41,7 +42,7 @@ def test_release(addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime): def test_release_all(addrs, cf, tokenVestingStaking, addressHolder): - tv, end, total = tokenVestingStaking + tv, start, end, total = tokenVestingStaking assert cf.flip.balanceOf(addrs.BENEFICIARY) == 0 @@ -57,6 +58,7 @@ def test_release_all(addrs, cf, tokenVestingStaking, addressHolder): cf.stateChainGateway, addressHolder, tv, + start, addrs.BENEFICIARY, addrs.REVOKER, True, @@ -69,7 +71,7 @@ def test_release_all(addrs, cf, tokenVestingStaking, addressHolder): def test_consecutive_releases_after_cliff( addrs, cf, tokenVestingStaking, maths, addressHolder ): - tv, end, total = tokenVestingStaking + tv, start, end, total = tokenVestingStaking assert cf.flip.balanceOf(addrs.BENEFICIARY) == 0 @@ -109,6 +111,7 @@ def test_consecutive_releases_after_cliff( cf.stateChainGateway, addressHolder, tv, + start, addrs.BENEFICIARY, addrs.REVOKER, True, @@ -128,7 +131,7 @@ def test_consecutive_releases_after_cliff( def test_release_staking_rewards_after_end( addrs, cf, tokenVestingStaking, addressHolder ): - tv, end, total = tokenVestingStaking + tv, start, end, total = tokenVestingStaking test_release_all(addrs, cf, tokenVestingStaking, addressHolder) @@ -137,8 +140,6 @@ def test_release_staking_rewards_after_end( tx = tv.release(cf.flip, {"from": addrs.BENEFICIARY}) - totalReleased = total + total - assert tx.events["TokensReleased"][0].values() == (cf.flip, total) # Shouldn't've changed @@ -146,6 +147,7 @@ def test_release_staking_rewards_after_end( cf.stateChainGateway, addressHolder, tv, + start, addrs.BENEFICIARY, addrs.REVOKER, True, @@ -160,7 +162,7 @@ def test_release_staking_rewards_after_end( def test_release_around_cliff( addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime ): - tv, end, total = tokenVestingStaking + tv, start, end, total = tokenVestingStaking chain.sleep(st_sleepTime) @@ -173,6 +175,7 @@ def test_release_around_cliff( cf.stateChainGateway, addressHolder, tv, + start, addrs.BENEFICIARY, addrs.REVOKER, True, diff --git a/tests/token_vesting/revoke/test_revoke_staking.py b/tests/token_vesting/revoke/test_revoke_staking.py index 87365e3f..10623806 100644 --- a/tests/token_vesting/revoke/test_revoke_staking.py +++ b/tests/token_vesting/revoke/test_revoke_staking.py @@ -6,7 +6,7 @@ @given(st_sleepTime=strategy("uint256", max_value=YEAR * 2)) def test_revoke(addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime): - tv, end, total = tokenVestingStaking + tv, start, end, total = tokenVestingStaking assert cf.flip.balanceOf(addrs.BENEFICIARY) == 0 assert cf.flip.balanceOf(addrs.REVOKER) == 0 @@ -34,6 +34,7 @@ def test_revoke(addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime): cf.stateChainGateway, addressHolder, tv, + start, addrs.BENEFICIARY, addrs.REVOKER, True, @@ -52,7 +53,7 @@ def test_revoke(addrs, cf, tokenVestingStaking, addressHolder, st_sleepTime): def test_revoke_rev_revoker(a, addrs, cf, tokenVestingStaking): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking for ad in a: if ad != addrs.REVOKER: @@ -68,6 +69,7 @@ def test_revoke_rev_revokable(addrs, cf, TokenVestingStaking): TokenVestingStaking, addrs.BENEFICIARY, ZERO_ADDR, + start + 2, end, BENEF_NON_TRANSF, cf.stateChainGateway, @@ -79,7 +81,7 @@ def test_revoke_rev_revokable(addrs, cf, TokenVestingStaking): def test_revoke_rev_revoked(addrs, cf, tokenVestingStaking): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking tx = tv.revoke(cf.flip, {"from": addrs.REVOKER}) @@ -94,7 +96,7 @@ def test_revoke_rev_revoked(addrs, cf, tokenVestingStaking): def test_revoke_staked(addrs, cf, tokenVestingStaking): - tv, end, total = tokenVestingStaking + tv, _, end, total = tokenVestingStaking nodeID1 = web3.toHex(1) amount = total @@ -139,7 +141,7 @@ def test_revoke_staked(addrs, cf, tokenVestingStaking): def test_retrieve_revoked_funds_and_rewards( addrs, cf, tokenVestingStaking, st_amount, rewards ): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking cf.flip.approve( cf.stateChainGateway.address, st_amount, {"from": addrs.BENEFICIARY} @@ -170,7 +172,7 @@ def test_retrieve_revoked_funds_and_rewards( # If revoked when staked, we don't get the funds. Then we have to enforce that the beneficiary unstakes it. # When that happens the beneficiary can't release the funds but they can front-run our retrieveFunds. def test_fund_revoked_staked(addrs, cf, tokenVestingStaking): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking test_revoke_staked(addrs, cf, tokenVestingStaking) nodeID1 = web3.toHex(1) with reverts(REV_MSG_TOKEN_REVOKED): diff --git a/tests/token_vesting/stakeStProvider/test_stProvider.py b/tests/token_vesting/stakeStProvider/test_stProvider.py index 9941c008..1b28c218 100644 --- a/tests/token_vesting/stakeStProvider/test_stProvider.py +++ b/tests/token_vesting/stakeStProvider/test_stProvider.py @@ -4,7 +4,7 @@ def test_stakeToStProvider(addrs, tokenVestingStaking, cf, mockStProvider): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking stFLIP, _, _, staking_address = mockStProvider assert cf.flip.balanceOf(tv) == total @@ -19,7 +19,7 @@ def test_stakeToStProvider(addrs, tokenVestingStaking, cf, mockStProvider): def test_rev_sender(addrs, tokenVestingStaking): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking with reverts(REV_MSG_NOT_BENEFICIARY): tv.stakeToStProvider(total, {"from": addrs.DEPLOYER}) with reverts(REV_MSG_NOT_BENEFICIARY): @@ -29,7 +29,7 @@ def test_rev_sender(addrs, tokenVestingStaking): def test_rev_amount(addrs, tokenVestingStaking): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking with reverts(REV_MSG_ERC20_EXCEED_BAL): tv.stakeToStProvider(total + 1, {"from": addrs.BENEFICIARY}) @@ -38,7 +38,7 @@ def test_rev_amount(addrs, tokenVestingStaking): def test_stake_rev_revoked(addrs, tokenVestingStaking, cf): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking tv.revoke(cf.flip, {"from": addrs.REVOKER}) with reverts(REV_MSG_TOKEN_REVOKED): @@ -46,7 +46,7 @@ def test_stake_rev_revoked(addrs, tokenVestingStaking, cf): def test_unstake_rev_revoked(addrs, tokenVestingStaking, mockStProvider): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking stFLIP, _, _, _ = mockStProvider tv.revoke(stFLIP, {"from": addrs.REVOKER}) @@ -56,7 +56,7 @@ def test_unstake_rev_revoked(addrs, tokenVestingStaking, mockStProvider): def test_claim_rev_revoked(addrs, tokenVestingStaking, mockStProvider): - tv, _, _ = tokenVestingStaking + tv, _, _, _ = tokenVestingStaking stFLIP, _, _, _ = mockStProvider tv.revoke(stFLIP, {"from": addrs.REVOKER}) @@ -66,7 +66,7 @@ def test_claim_rev_revoked(addrs, tokenVestingStaking, mockStProvider): def test_unstakeFromStProvider(addrs, tokenVestingStaking, cf, mockStProvider): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking stFLIP, _, burner, staking_address = mockStProvider test_stakeToStProvider(addrs, tokenVestingStaking, cf, mockStProvider) @@ -112,7 +112,7 @@ def test_unstakeFromStProvider(addrs, tokenVestingStaking, cf, mockStProvider): def test_stProviderClaimRewards(addrs, tokenVestingStaking, cf, mockStProvider): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking stFLIP, minter, _, _ = mockStProvider reward_amount = 100 * 10**18 @@ -150,7 +150,7 @@ def test_stProviderClaimRewards(addrs, tokenVestingStaking, cf, mockStProvider): def test_stProviderClaimRewardsInsufficientStflip( addrs, tokenVestingStaking, cf, mockStProvider ): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking stFLIP, minter, _, _ = mockStProvider reward_amount = 100 * 10**18 @@ -188,7 +188,7 @@ def test_stProviderClaimRewardsInsufficientStflip( def test_stProviderClaimRewardsSlash(addrs, tokenVestingStaking, cf, mockStProvider): - tv, _, total = tokenVestingStaking + tv, _, _, total = tokenVestingStaking stFLIP, _, _, _ = mockStProvider slash_amount = 100 * 10**18 diff --git a/tests/token_vesting/transferRights/test_transfer_beneficiary.py b/tests/token_vesting/transferRights/test_transfer_beneficiary.py index 1930068e..76403a7f 100644 --- a/tests/token_vesting/transferRights/test_transfer_beneficiary.py +++ b/tests/token_vesting/transferRights/test_transfer_beneficiary.py @@ -8,7 +8,7 @@ def test_transfer_beneficiary_0( addrs, tokenVestingStaking, tokenVestingNoStaking, st_sender ): - tv_staking, _, _ = tokenVestingStaking + tv_staking, _, _, _ = tokenVestingStaking tv_noStaking, _, _, _ = tokenVestingNoStaking for vestingContract in [tv_staking, tv_noStaking]: @@ -38,6 +38,7 @@ def test_transfer_beneficiary_1( TokenVestingStaking, addrs.BENEFICIARY, addrs.REVOKER, + getChainTime() + QUARTER_YEAR, end, BENEF_NON_TRANSF, cf.stateChainGateway, diff --git a/tests/token_vesting/transferRights/test_transfer_revoker.py b/tests/token_vesting/transferRights/test_transfer_revoker.py index 6b0cac8b..968ada59 100644 --- a/tests/token_vesting/transferRights/test_transfer_revoker.py +++ b/tests/token_vesting/transferRights/test_transfer_revoker.py @@ -6,7 +6,7 @@ @given(st_sender=strategy("address")) def test_transfer_revoker(addrs, tokenVestingStaking, tokenVestingNoStaking, st_sender): - tv_staking, _, _ = tokenVestingStaking + tv_staking, _, _, _ = tokenVestingStaking tv_noStaking, _, _, _ = tokenVestingNoStaking for vestingContract in [tv_staking, tv_noStaking]: