def test_token_rename(token: Contract, team_multisig, token_new_name, token_new_symbol): """We will update token's information here""" token.transact({"from": team_multisig}).setTokenInformation(token_new_name, token_new_symbol) assert token.call().name() == token_new_name assert token.call().symbol() == token_new_symbol
def test_close_early(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, preico_ends_at, team_multisig): """Soft cap triggered, close crowdsale early.""" # Close earlier than anticipated new_early = preico_starts_at + 1*3600 assert new_early < preico_ends_at time_travel(chain, preico_starts_at + 1) assert ico.call().getState() == CrowdsaleState.Funding ico.transact({"from": customer, "value": to_wei(1, "ether")}).buy() ico.transact({"from": team_multisig}).setEndsAt(new_early) # Here we try to switch the strategy, and buy again, 1 wei for 1 token args = [ 1, ] tx = { "from": team_multisig, } pricing_strategy, hash = chain.provider.deploy_contract('FlatPricing', deploy_args=args, deploy_transaction=tx) ico.transact({"from": team_multisig}).setPricingStrategy(pricing_strategy.address) assert ico.call().pricingStrategy() == pricing_strategy.address ico.transact({"from": customer, "value": 1}).buy() # Finally, here we travel in time to situation after the early closing: time_travel(chain, new_early + 1) assert ico.call().getState() == CrowdsaleState.Failure with pytest.raises(TransactionFailed): ico.transact({"from": customer, "value": to_wei(1, "ether")}).buy()
def decimalize_token_amount(contract: Contract, amount: int) -> Decimal: """Convert raw fixed point token amount to decimal format. :param contract: ERC-20 token contract with decimals field :param amount: Raw token amount :return: The resultdroping :py:class:`decimal.Decimal` carries a correct decimal places. """ val = Decimal(amount) / Decimal(10 ** contract.call().decimals()) quantizer = Decimal(1) / Decimal(10 ** contract.call().decimals()) return val.quantize(quantizer)
def test_unlock(chain, token: Contract, team_multisig: str, vault: Contract, unlock_time: int): """Unlock tokens.""" assert token.call().balanceOf(team_multisig) == 0 assert token.call().balanceOf(vault.address) == 1000000 time_travel(chain, unlock_time + 1) vault.transact({"from": team_multisig}).unlock() assert token.call().balanceOf(team_multisig) == 1000000 assert token.call().balanceOf(vault.address) == 0
def test_buy_one_investor(chain: TestRPCChain, web3: Web3, ico: Contract, uncapped_token: Contract, customer: str, preico_token_price, preico_starts_at, team_multisig): """Can buy when crowdsale is running.""" original_balance = web3.eth.getBalance(team_multisig) wei_value = to_wei(1, "ether") buys_tokens = wei_value // preico_token_price assert buys_tokens > 0 time_travel(chain, preico_starts_at + 1) assert ico.call().getState() == CrowdsaleState.Funding assert ico.call().investorCount() == 0 assert ico.call().investedAmountOf(customer) == 0 ico.transact({"from": customer, "value": wei_value}).buy() # # See everything was correctly credited # # Tokens on every account assert uncapped_token.call().balanceOf(customer) == buys_tokens assert uncapped_token.call().totalSupply() == buys_tokens assert ico.call().tokensSold() == buys_tokens assert ico.call().investorCount() == 1 # Ether on every account assert ico.call().weiRaised() == wei_value assert ico.call().investedAmountOf(customer) == wei_value balance_diff = web3.eth.getBalance(team_multisig) - original_balance assert balance_diff == wei_value # Investors assert ico.call().investorCount() == 1 # # Events # # Crowdsale events = ico.pastEvents("Invested").get() assert len(events) == 1 e = events[0] assert e["args"]["investor"] == customer assert e["args"]["weiAmount"] == wei_value assert e["args"]["tokenAmount"] == buys_tokens # ERC-20 events = uncapped_token.pastEvents("Transfer").get() assert len(events) == 1 e = events[0] assert e["args"]["from"] == "0x0000000000000000000000000000000000000000" assert e["args"]["to"] == customer assert e["args"]["value"] == buys_tokens
def test_cannot_transfer(token: Contract, team_multisig, customer: str, customer_2: str): """Tokens cannot be transferred before they are released.""" assert not token.call().released() # team_multisig is on the whitelisted transfer agent list assert token.call().transferAgents(team_multisig) == False with pytest.raises(TransactionFailed): token.transact({"from": team_multisig}).transfer(customer, 10000) # customer cannot transfer to customer 2 before release assert token.call().transferAgents(customer) == False with pytest.raises(TransactionFailed): token.transact({"from": customer}).transfer(customer_2, 10000)
def test_halt(chain: TestRPCChain, web3: Web3, ico: Contract, uncapped_token: Contract, customer: str, preico_token_price, preico_starts_at, team_multisig): """Cannot buy tokens during the emergency pause mode.""" time_travel(chain, preico_starts_at + 1) wei_value = to_wei(1, "ether") ico.transact({"from": team_multisig}).halt() assert ico.call().halted() with pytest.raises(TransactionFailed): ico.transact({"from": customer, "value": wei_value}).buy() ico.transact({"from": team_multisig}).unhalt() assert not ico.call().halted() ico.transact({"from": customer, "value": wei_value}).buy()
def test_erc20_interface(token: Contract, token_owner: str, empty_address: str): """Token satisfies ERC-20 interface.""" # https://github.com/OpenZeppelin/zeppelin-solidity/blob/master/contracts/token/ERC20.sol assert token.call().balanceOf(empty_address) == 0 assert token.call().allowance(token_owner, empty_address) == 0 # Event # We follow OpenZeppelin - in the ERO20 issue names are _from, _to, _value transfer = token._find_matching_event_abi("Transfer", ["from", "to", "value"]) assert transfer approval = token._find_matching_event_abi("Approval", ["owner", "spender", "value"]) assert approval
def test_close_late(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, preico_ends_at, team_multisig): """Extend crowdsale.""" new_end = preico_ends_at + 1*3600 assert new_end > preico_ends_at time_travel(chain, preico_starts_at + 1) assert ico.call().getState() == CrowdsaleState.Funding ico.transact({"from": customer, "value": to_wei(1, "ether")}).buy() ico.transact({"from": team_multisig}).setEndsAt(new_end) time_travel(chain, preico_ends_at + 1) assert ico.call().getState() == CrowdsaleState.Funding ico.transact({"from": customer, "value": to_wei(1, "ether")}).buy()
def test_early_whitelist_only_owner(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, team_multisig, uncapped_token): """Only owner can early whitelist.""" time_travel(chain, preico_starts_at - 1) assert ico.call().getState() == CrowdsaleState.PreFunding with pytest.raises(TransactionFailed): ico.transact({"from": customer}).setEarlyParicipantWhitelist(customer, True)
def test_signature_contract_verify_v_r_s(web3: Web3, signature_contract: Contract): """Test that our signature verification works in Solidity contract. """ # Use random Ethereum address as payload for signing data = "0xda39147df55f6c51ad539a5e108adc5d7284b309" # Convert address to raw bytes data_bin = binascii.unhexlify(data[2:]) assert type(data_bin) == bytes private_key_seed = "foobar" # Address is 0x58708390680239282143999941903085911172379991841 signature_data = sign(data_bin, private_key_seed) # hash = big_endian_to_int(signature_data["hash"]) hash = signature_data["hash"] v = signature_data["v"] r = signature_data["r_bytes"] s = signature_data["s_bytes"] # 0x0a489345f9e9bc5254e18dd14fa7ecfdb2ce5f21 result = signature_contract.call().verify(hash, v, r, s) assert result == signature_data["address_ethereum"]
def test_buy_late_goal_reached(chain: TestRPCChain, uncapped_flatprice_goal_reached: Contract, customer: str, preico_ends_at): """Cannot buy after closing time when the goal was not reached.""" time_travel(chain, preico_ends_at + 1) assert uncapped_flatprice_goal_reached.call().getState() == CrowdsaleState.Success with pytest.raises(TransactionFailed): uncapped_flatprice_goal_reached.transact({"from": customer, "value": to_wei(1, "ether")}).buy()
def failed_ico_ready_to_refund(chain: TestRPCChain, failed_ico: Contract, team_multisig) -> Contract: """An ICO that did not reach a goal, but has participants. The team has moved funds back from the multisig wallet on the crowdsale contract. Note that due to transaction fees you need to pay a minimal transaction cost out of your own pocket. """ failed_ico.transact({"from" : team_multisig, "value": failed_ico.call().weiRaised()}).loadRefund() return failed_ico
def test_buy_early(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, uncapped_token): """Cannot buy too early.""" time_travel(chain, preico_starts_at - 1) assert ico.call().getState() == CrowdsaleState.PreFunding with pytest.raises(TransactionFailed): ico.transact({"from": customer, "value": to_wei(1, "ether")}).buy()
def test_cannot_refund_twice(failed_ico_ready_to_refund: Contract, customer: str): """Customer can reclaim refund only once.""" assert failed_ico_ready_to_refund.call().getState() == CrowdsaleState.Refunding failed_ico_ready_to_refund.transact({"from": customer}).refund() with pytest.raises(TransactionFailed): failed_ico_ready_to_refund.transact({"from": customer}).refund()
def test_sign_balance_proof_contract(channel_manager_contract: Contract): sig = sign_balance_proof( SENDER_PRIVATE_KEY, RECEIVER_ADDR, 37, 15, channel_manager_contract.address ) sender_recovered = channel_manager_contract.call().extractBalanceProofSignature( RECEIVER_ADDR, 37, 15, sig ) assert is_same_address(sender_recovered, SENDER_ADDR)
def sweep_account( private_key: str, faucet_address: str, token_contract: Contract, web3: Web3, wait_for_transaction ): address = privkey_to_addr(private_key) log.info('Sweeping account {}'.format(address)) token_balance = token_contract.call().balanceOf(address) if token_balance > 0: tx = create_signed_contract_transaction( private_key, token_contract, 'transfer', [ faucet_address, token_balance ] ) try: tx_hash = web3.eth.sendRawTransaction(tx) except ValueError as e: if e.args[0]['message'].startswith('Insufficient funds.'): pass else: raise else: wait_for_transaction(tx_hash) assert token_contract.call().balanceOf(address) == 0 balance = web3.eth.getBalance(address) if balance < NETWORK_CFG.POT_GAS_LIMIT * NETWORK_CFG.GAS_PRICE: return tx = create_signed_transaction( private_key, web3, to=faucet_address, value=balance - NETWORK_CFG.POT_GAS_LIMIT * NETWORK_CFG.GAS_PRICE, gas_limit=NETWORK_CFG.POT_GAS_LIMIT ) tx_hash = web3.eth.sendRawTransaction(tx) wait_for_transaction(tx_hash) assert web3.eth.getBalance(address) == 0, ( 'Sweeping of account {} (private key {}) failed.'.format(address, private_key) )
def test_sign_close_contract(channel_manager_contract: Contract): sig = sign_close( RECEIVER_PRIVATE_KEY, SENDER_ADDR, 315832, 13, channel_manager_contract.address ) receiver_recovered = channel_manager_contract.call().extractClosingSignature( SENDER_ADDR, 315832, 13, sig ) assert is_same_address(receiver_recovered, RECEIVER_ADDR)
def test_buy_early_whitelisted(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, team_multisig, uncapped_token): """Whitelisted participants can buy earliy.""" time_travel(chain, preico_starts_at - 1) assert ico.call().getState() == CrowdsaleState.PreFunding ico.transact({"from": team_multisig}).setEarlyParicipantWhitelist(customer, True) ico.transact({"from": customer, "value": to_wei(1, "ether")}).buy() assert uncapped_token.call().balanceOf(customer) > 0
def test_cannot_upgrade_too_many(released_token: Contract, upgrade_agent: Contract, team_multisig, customer): """We cannot upgrade more tokens than we have.""" released_token.transact({"from": team_multisig}).setUpgradeAgent(upgrade_agent.address) assert released_token.call().balanceOf(customer) == 10000 with pytest.raises(TransactionFailed): released_token.transact({"from": customer}).upgrade(20000)
def test_unlock_early(chain, token: Contract, team_multisig: str, vault: Contract, unlock_time: int): """Early unlock fails.""" assert token.call().balanceOf(team_multisig) == 0 assert token.call().balanceOf(vault.address) == 1000000 time_travel(chain, unlock_time - 1) with pytest.raises(TransactionFailed): vault.transact({"from": team_multisig}).unlock()
def test_refund(failed_ico_ready_to_refund: Contract, web3: Web3, customer: str, customer_2: str): """Customers can claim their refunds.""" assert failed_ico_ready_to_refund.call().loadedRefund() == to_wei(120, "ether") assert failed_ico_ready_to_refund.call().getState() == CrowdsaleState.Refunding # Check that the customer gets money back invested_amount = failed_ico_ready_to_refund.call().investedAmountOf(customer) begin_balance = web3.eth.getBalance(customer) failed_ico_ready_to_refund.transact({"from": customer}).refund() end_balance = web3.eth.getBalance(customer) eth = from_wei(end_balance - begin_balance, "ether") # Decimal('49.999999999999954693') assert (end_balance - begin_balance) >= eth - TRANSACTION_COST_ETH_EPSILON failed_ico_ready_to_refund.transact({"from": customer_2}).refund() # Everything has been refunded assert failed_ico_ready_to_refund.call().weiRefunded() == to_wei(120, "ether")
def test_finalize_success(chain: TestRPCChain, uncapped_flatprice_final: Contract, uncapped_token: Contract, team_multisig: str, customer: str, preico_starts_at, preico_ends_at, preico_funding_goal, default_finalize_agent): """Finalize releases the token.""" time_travel(chain, preico_starts_at + 1) wei_value = preico_funding_goal uncapped_flatprice_final.transact({"from": customer, "value": wei_value}).buy() time_travel(chain, preico_ends_at + 1) assert uncapped_flatprice_final.call().getState() == CrowdsaleState.Success assert uncapped_flatprice_final.call().finalizeAgent() == default_finalize_agent.address # Release the tokens uncapped_flatprice_final.transact({"from": team_multisig}).finalize() assert uncapped_flatprice_final.call().getState() == CrowdsaleState.Finalized # Here we go assert uncapped_token.call().released() assert uncapped_token.call().mintingFinished()
def test_buy_fail_goal(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, preico_ends_at, preico_funding_goal): """Goal is not reached if there is not enough investment.""" time_travel(chain, preico_starts_at + 1) wei_value = preico_funding_goal // 2 ico.transact({"from": customer, "value": wei_value}).buy() time_travel(chain, preico_ends_at + 1) assert ico.call().getState() == CrowdsaleState.Failure
def test_bad_released(token: Contract, team_multisig: str, malicious_address: str, empty_address: str): """Only release agent can make token transferable.""" assert not token.call().released() with pytest.raises(TransactionFailed): token.transact({"from": malicious_address}).releaseTokenTransfer() # Even owner cannot release, need to go through release agent process with pytest.raises(TransactionFailed): token.transact({"from": team_multisig}).releaseTokenTransfer()
def test_set_upgrade_agent(upgradeable_token: Contract, upgrade_agent: Contract, team_multisig): """Upgrade agent can be set on a released token.""" # Preconditions are met assert upgrade_agent.call().isUpgradeAgent() assert upgradeable_token.call().canUpgrade() assert upgradeable_token.call().upgradeMaster() == team_multisig assert upgrade_agent.call().oldToken() == upgradeable_token.address assert upgrade_agent.call().originalSupply() == upgradeable_token.call().totalSupply() assert upgradeable_token.call().getUpgradeState() == UpgradeState.WaitingForAgent upgradeable_token.transact({"from": team_multisig}).setUpgradeAgent(upgrade_agent.address) assert upgradeable_token.call().getUpgradeState() == UpgradeState.ReadyToUpgrade
def test_upgrade_all(released_token: Contract, upgrade_agent: Contract, team_multisig, customer): """We can upgrade all tokens of two owners.""" released_token.transact({"from": team_multisig}).setUpgradeAgent(upgrade_agent.address) assert released_token.call().balanceOf(team_multisig) == 9990000 assert released_token.call().balanceOf(customer) == 10000 assert released_token.call().totalSupply() == 10000000 released_token.transact({"from": team_multisig}).upgrade(9990000) released_token.transact({"from": customer}).upgrade(10000) assert released_token.call().getUpgradeState() == UpgradeState.Upgrading assert released_token.call().totalSupply() == 0 assert upgrade_agent.call().totalSupply() == 10000000 assert released_token.call().totalUpgraded() == 10000000 assert upgrade_agent.call().balanceOf(team_multisig) == 9990000 assert upgrade_agent.call().balanceOf(customer) == 10000
def test_initialized(ico: Contract, uncapped_token: Contract, team_multisig, preico_starts_at, preico_ends_at, preico_funding_goal): """Is initialized with the parameters we want.""" # We have owner assert ico.call().owner() == team_multisig # Crowdsale contract is in minters assert uncapped_token.call().mintAgents(ico.address) == True assert not uncapped_token.call().released() assert not ico.call().halted() assert ico.call().startsAt() == preico_starts_at assert ico.call().endsAt() == preico_ends_at assert ico.call().getState() == CrowdsaleState.PreFunding assert ico.call().minimumFundingGoal() == preico_funding_goal
def test_finalize_fail_goal(chain: TestRPCChain, uncapped_flatprice_final: Contract, customer: str, preico_starts_at, preico_ends_at, preico_funding_goal): """Finalize can be done only for successful crowdsales.""" time_travel(chain, preico_starts_at + 1) wei_value = preico_funding_goal // 2 uncapped_flatprice_final.transact({"from": customer, "value": wei_value}).buy() time_travel(chain, preico_ends_at + 1) assert uncapped_flatprice_final.call().getState() == CrowdsaleState.Failure with pytest.raises(TransactionFailed): uncapped_flatprice_final.transact().finalize()
def failed_ico(chain: TestRPCChain, web3, uncapped_flatprice: Contract, team_multisig, customer, customer_2, preico_starts_at, preico_ends_at, uncapped_flatprice_finalizer) -> Contract: """An ICO that did not reach a goal, but has participants. Both ``customer`` and ``customer_2`` had bought token. * customer: 50 ether * customer_2: 70 ether * total: 120 ether * minimum funding goal: 1200 ether """ time_travel(chain, preico_starts_at + 1) uncapped_flatprice.transact({"from": customer, "value": to_wei(50, "ether")}).buy() uncapped_flatprice.transact({"from": customer_2, "value": to_wei(70, "ether")}).buy() assert not uncapped_flatprice.call().isMinimumGoalReached() # Make sure customer 1 has some token balance time_travel(chain, uncapped_flatprice.call().endsAt() + 1) return uncapped_flatprice
def test_no_transfer_before_close(open_crowdsale: Contract, token: Contract, customer: str, beneficiary: str, empty_address: str, web3: Web3, end: int): """Buyer cannot transfer tokens before ICO is over.""" web3.eth.sendTransaction({ "from": customer, "to": open_crowdsale.address, "value": to_wei(20, "ether"), "gas": 250000, }) amount = 4000 with pytest.raises(TransactionFailed): token.transact({"from": customer}).transfer(empty_address, amount) token.transact().setCurrent(end+1) token.transact({"from": customer}).transfer(empty_address, amount) assert token.call().balanceOf(empty_address) == amount
def test_set_upgrade_agent(released_token: Contract, upgrade_agent: Contract, team_multisig): """Upgrade agent can be set on a released token.""" # Preconditions are met assert upgrade_agent.call().isUpgradeAgent() assert released_token.call().canUpgrade() assert released_token.call().upgradeMaster() == team_multisig assert upgrade_agent.call().oldToken() == released_token.address assert upgrade_agent.call().originalSupply() == released_token.call( ).totalSupply() released_token.transact({ "from": team_multisig }).setUpgradeAgent(upgrade_agent.address) assert released_token.call().getUpgradeState( ) == UpgradeState.ReadyToUpgrade
def test_finalize_fail_goal(chain: TesterChain, uncapped_flatprice_final: Contract, customer: str, preico_starts_at, preico_ends_at, preico_funding_goal): """Finalize can be done only for successful crowdsales.""" time_travel(chain, preico_starts_at + 1) wei_value = preico_funding_goal // 2 uncapped_flatprice_final.transact({ "from": customer, "value": wei_value }).buy() time_travel(chain, preico_ends_at + 1) assert uncapped_flatprice_final.call().getState() == CrowdsaleState.Failure with pytest.raises(TransactionFailed): uncapped_flatprice_final.transact().finalize()
def test_finalize_fail_again(chain: TestRPCChain, uncapped_flatprice_final: Contract, customer: str, preico_starts_at, preico_ends_at, preico_funding_goal): """Finalize cannot be done again.""" time_travel(chain, preico_starts_at + 1) wei_value = preico_funding_goal uncapped_flatprice_final.transact({ "from": customer, "value": wei_value }).buy() time_travel(chain, preico_ends_at + 1) assert uncapped_flatprice_final.call().getState() == CrowdsaleState.Success uncapped_flatprice_final.transact().finalize() with pytest.raises(TransactionFailed): uncapped_flatprice_final.transact().finalize()
def reclaim_address(token: Contract, entry: Entry, tx_params: dict) -> Tuple[int, str]: """Reclsaim tokens for a single participant. :param token: Token contract we reclaim :param owner: Token owner account :param address: Etherereum address :param label: User notification label regarding this address :param tx_params: Ethereum transaction parameters to use :return: 1 on reclaim, 0 on skip """ # Make sure we are not fed bad input, raises validate_ethereum_address(entry.address) if token.call().balanceOf(entry.address) == 0: logger.info("%s: looks like already reclaimed %s", entry.address, entry.label) return 0, None txid = token.transact(tx_params).transferToOwner(entry.address) logger.info("%s: reclaiming %s in txid %s", entry.address, entry.label, txid) return 1, txid
def test_upgrade_partial(upgradeable_token: Contract, upgrade_agent: Contract, team_multisig, customer): """We can upgrade some of tokens.""" upgradeable_token.transact({"from": team_multisig}).setUpgradeAgent(upgrade_agent.address) # Fiddle numbers so that we have some balance on other users too upgradeable_token.transact({"from": team_multisig}).transfer(customer, 1000) to_upgrade = 3000000 begin_tokens = upgradeable_token.call().balanceOf(team_multisig) supply_start = upgradeable_token.call().totalSupply() assert begin_tokens > to_upgrade upgradeable_token.transact({"from": team_multisig}).upgrade(to_upgrade) assert upgradeable_token.call().getUpgradeState() == UpgradeState.Upgrading assert upgradeable_token.call().totalSupply() == supply_start - to_upgrade assert upgrade_agent.call().totalSupply() == to_upgrade assert upgradeable_token.call().totalUpgraded() == to_upgrade assert upgradeable_token.call().balanceOf(team_multisig) == begin_tokens - to_upgrade assert upgrade_agent.call().balanceOf(team_multisig) == to_upgrade
def import_investor_data(contract: Contract, deploy_address: str, fname: str): """Load investor data to a MultiVault contract. Mysterium specific data loader. :return: List of unconfirmed transaction ids """ assert fname.endswith(".csv") txs = [] with open(fname, "rt") as inp: for line in inp: address, amount = line.split(",") address = address.strip() amount = amount.strip() assert address.startswith("0x") amount = int(float(amount) * 10000) # Use this precision if contract.call().balances(address) == 0: contract.transact({ "from": deploy_address }).addInvestor(address, amount)
def test_buy_two_investors(chain: TestRPCChain, web3: Web3, ico: Contract, uncapped_token: Contract, customer: str, customer_2, preico_token_price, preico_starts_at, team_multisig): """Two different customers buy in.""" original_balance = web3.eth.getBalance(team_multisig) wei_value = to_wei(1, "ether") buys_tokens = wei_value // preico_token_price assert buys_tokens > 0 time_travel(chain, preico_starts_at + 1) # Buy twice ico.transact({"from": customer, "value": wei_value}).buy() ico.transact({"from": customer_2, "value": wei_value}).buy() # # See everything was correctly credited # # Tokens on every account assert uncapped_token.call().balanceOf(customer) == buys_tokens assert uncapped_token.call().totalSupply() == buys_tokens * 2 assert ico.call().tokensSold() == buys_tokens * 2 # Ether on every account assert ico.call().weiRaised() == wei_value * 2 assert ico.call().investedAmountOf(customer) == wei_value balance_diff = web3.eth.getBalance(team_multisig) - original_balance assert balance_diff == wei_value * 2 # Investors assert ico.call().investorCount() == 2 # # Events # # Crowdsale events = ico.pastEvents("Invested").get() assert len(events) == 2 # ERC-20 events = uncapped_token.pastEvents("Transfer").get() assert len(events) == 2
def test_check_burn(open_crowdsale: Contract, token: Contract, customer: str, beneficiary: str, web3: Web3, end: int): """Extra tokens are burnt as described as the end of the ICO.""" minimum_goal_value = open_crowdsale.call().fundingGoal( ) * open_crowdsale.call().getPrice() # Buy some tokens web3.eth.sendTransaction({ "from": customer, "to": open_crowdsale.address, "value": minimum_goal_value, "gas": 250000, }) # Close token.transact().setCurrent(end + 1) finished_token = token open_crowdsale.transact().setCurrent(end + 1) finished_crowdsale = open_crowdsale # Supply before burn supply_before_burn = token.call().totalSupply() owner_before_burn = token.call().balanceOf(beneficiary) assert not finished_token.call().burned() # Trigger goal check finished_crowdsale.transact().checkGoalReached() assert finished_crowdsale.call().fundingGoalReached() # We get crowdsale over event events = finished_crowdsale.pastEvents("GoalReached").get() assert len(events) == 1 # We burned succesfully assert finished_token.call().burned() assert token.call().totalSupply() < supply_before_burn assert token.call().balanceOf(beneficiary) < owner_before_burn # Burned event gives us the diff events = finished_token.pastEvents("Burned").get() assert len(events) == 1 e = events[0] assert e["args"]["amount"] == 390000000
def test_finalize_only_by_crowdsale(chain: TesterChain, uncapped_flatprice_final: Contract, team_multisig: str, customer: str, preico_starts_at, preico_ends_at, preico_funding_goal, default_finalize_agent): """Finalizer can be only triggered by crowdsale.""" time_travel(chain, preico_starts_at + 1) wei_value = preico_funding_goal uncapped_flatprice_final.transact({ "from": customer, "value": wei_value }).buy() time_travel(chain, preico_ends_at + 1) assert uncapped_flatprice_final.call().getState() == CrowdsaleState.Success # Checks for the owner with pytest.raises(TransactionFailed): default_finalize_agent.transact({ "from": team_multisig }).finalizeCrowdsale()
def test_call_check_goal_reached_after_close(finished_crowdsale: Contract, token: Contract, customer: str, beneficiary: str, web3: Web3): """Checking goal reached closes crowdsale if we are the past end deadline.""" finished_crowdsale.transact().checkGoalReached() assert finished_crowdsale.call().crowdsaleClosed() == True
def test_call_check_goal_reached_too_early(open_crowdsale: Contract, token: Contract, customer: str, beneficiary: str, web3: Web3): """Checking goal reached does nothing unless ICO is over.""" open_crowdsale.transact().checkGoalReached() assert open_crowdsale.call().crowdsaleClosed() == False
def close_open_channels( private_key: str, state: ChannelManagerState, channel_manager_contract: Contract, repetitions=None, wait=lambda: gevent.sleep(1) ): web3 = channel_manager_contract.web3 channels_with_balance_proof = [ c for c in state.channels.values() if c.last_signature is not None ] n_channels = len(state.channels) n_no_balance_proof = len(state.channels) - len(channels_with_balance_proof) n_txs_sent = 0 pending_txs = {} if repetitions: iterator = range(repetitions) else: iterator = count() for _ in iterator: n_non_existant = 0 n_invalid_balance_proof = 0 for channel in channels_with_balance_proof: # lookup channel on block chain channel_id = (channel.sender, channel.receiver, channel.open_block_number) try: channel_info = channel_manager_contract.call().getChannelInfo(*channel_id) except (BadFunctionCallOutput, TransactionFailed): n_non_existant += 1 continue _, deposit, settle_block_number, closing_balance, transferred_tokens = channel_info is_valid = channel.balance <= deposit n_invalid_balance_proof += int(not is_valid) close_sent = (channel.sender, channel.open_block_number) in pending_txs # send close if open or settling with wrong balance, unless already done if not close_sent and is_valid: closing_sig = sign_close( private_key, channel.sender, channel.open_block_number, channel.balance, channel_manager_contract.address ) raw_tx = create_signed_contract_transaction( private_key, channel_manager_contract, 'cooperativeClose', [ channel.receiver, channel.open_block_number, channel.balance, decode_hex(channel.last_signature), closing_sig ] ) tx_hash = web3.eth.sendRawTransaction(raw_tx) log.info('sending close tx (hash: {})'.format(tx_hash)) pending_txs[channel.sender, channel.open_block_number] = tx_hash n_txs_sent += 1 # print status msg_status = 'block: {}, pending txs: {}, total txs sent: {}' msg_progress = ( 'initial channels: {}, settled: {}, pending txs: {}, no BP: {}, invalid BP: {}' ) log.info(msg_status.format(web3.eth.blockNumber, len(pending_txs), n_txs_sent)) log.info(msg_progress.format( n_channels, n_non_existant, len(pending_txs), n_no_balance_proof, n_invalid_balance_proof )) # wait for next block block_before = web3.eth.blockNumber while web3.eth.blockNumber == block_before: wait() # update pending txs confirmed = [] for channel_id, tx_hash in pending_txs.items(): receipt = web3.eth.getTransactionReceipt(tx_hash) if receipt is None: continue tx = web3.eth.getTransaction(tx_hash) if receipt.gasUsed == tx.gas: raise ValueError('Transaction failed, out of gas (hash: {})'.format(tx_hash)) confirmed.append(channel_id) for channel_id in confirmed: pending_txs.pop(channel_id)
def test_cannot_upgrade_until_released(token: Contract): """Non-released tokens cannot be upgradeable.""" assert not token.call().canUpgrade() assert token.call().getUpgradeState() == UpgradeState.NotAllowed
def test_can_upgrade_released_token(released_token: Contract): """Released token is free to upgrade.""" assert released_token.call().canUpgrade() assert released_token.call().getUpgradeState( ) == UpgradeState.WaitingForAgent
def test_app_drain(monkeypatch: MonkeyPatch, keyfiles: None, client_app: App, passwords: List[str], private_keys: List[PrivateKeyHex], addresses: List[Address], web3: Web3, token_contract: Contract, faucet_address: Address, use_tester: bool, wait_for_transaction, faucet_private_key: PrivateKeyHex): i = 6 j = 3 fund_account(addresses[i], WEI_ALLOWANCE, REI_ALLOWANCE, token_contract, web3, wait_for_transaction, faucet_private_key) fund_account(addresses[j], WEI_ALLOWANCE, REI_ALLOWANCE, token_contract, web3, wait_for_transaction, faucet_private_key) if use_tester: ethereum.tester.accounts.append(decode_hex(addresses[i])) ethereum.tester.keys.append(decode_hex(private_keys[i])) ethereum.tester.accounts.append(decode_hex(addresses[j])) ethereum.tester.keys.append(decode_hex(private_keys[j])) input_sequence = ( value for value in [str(i), passwords[i], False, True, str(j), passwords[j], True]) mock_prompt(monkeypatch, input_sequence) client_app.start() account_rei = token_contract.call().balanceOf(addresses[i]) account_wei = web3.eth.getBalance(addresses[i]) faucet_rei = token_contract.call().balanceOf(faucet_address) faucet_wei = web3.eth.getBalance(faucet_address) assert account_rei > 0 assert account_wei > 0 # Should drain nothing. client_app.drain(faucet_address) assert token_contract.call().balanceOf(addresses[i]) == account_rei assert web3.eth.getBalance(addresses[i]) == account_wei with pytest.raises(AssertionError): # Address not checksummed. client_app.drain(to_normalized_address(faucet_address), rdn=True) # Not confirmed. client_app.drain(faucet_address, rdn=True) assert token_contract.call().balanceOf(addresses[i]) == account_rei assert web3.eth.getBalance(addresses[i]) == account_wei # Confirmed. client_app.drain(faucet_address, rdn=True) assert token_contract.call().balanceOf(addresses[i]) == 0 assert 0 < web3.eth.getBalance(addresses[i]) < account_wei assert token_contract.call().balanceOf( faucet_address) == faucet_rei + account_rei assert web3.eth.getBalance(faucet_address) == faucet_wei # Second round, different account. client_app.start() account_rei = token_contract.call().balanceOf(addresses[j]) account_wei = web3.eth.getBalance(addresses[j]) faucet_rei = token_contract.call().balanceOf(faucet_address) faucet_wei = web3.eth.getBalance(faucet_address) assert account_rei > 0 assert account_wei > 0 # Drain both ETH and RDN. client_app.drain(faucet_address, rdn_and_eth=True) assert token_contract.call().balanceOf(addresses[j]) == 0 assert web3.eth.getBalance(addresses[j]) == 0 assert token_contract.call().balanceOf( faucet_address) == faucet_rei + account_rei assert web3.eth.getBalance(faucet_address) > faucet_wei
def get_length(self, account: Address, storage: Contract = None) -> int: if storage is None: storage = self.get_storage(account) return storage.call().length()
def import_invoicing_address(contract: Contract, tieke_data: dict): """Sample importer for an invoicing address. Slow. Confirms each transaction in serial fashion. """ vat_id = ytunnus_to_vat_id(tieke_data["Y-tunnus"]) print("Importing {}".format(vat_id)) # We have not imported this company yet if not contract.call().hasCompany(vat_id): # TODO: This demo creates a company record too, but all vatIds should be prepopulated txid = contract.transact().createCompany(vat_id) assert check_succesful_tx(contract, txid) # Create core company info data = {"name": tieke_data["Yrityksen nimi"]} data = json.dumps(data) # Convert to UTF-8 string contract.transact().setCompanyData(vat_id, ContentType.TiekeCompanyData.value, data) address = tieke_data["Vastaanotto-osoite"] if not address: # Some old gappy data? address = "OVT:" + tieke_data["OVT-tunnus"] else: address = normalize_invoicing_address(address) assert address # We have not imported this address yet if contract.call().getVatIdByAddress(address) != "": print("Already exists: VAT id: {}, address: {}".format( vat_id, address)) return # Create new OVT address txid = contract.transact().createInvoicingAddress(vat_id, address) assert check_succesful_tx(contract, txid, timeout=180) tieke_address_data = { "operatorName": tieke_data["Operaattori"], "operatorId": tieke_data["Välittäjän tunnus"], "permissionToSend": tieke_data["Lähetyslupa"] == "Kyllä", "sends": tieke_data["Lähettää"] == "Kyllä", "receives": tieke_data["Vastaanottaa"] == "Kyllä", } tieke_address_data = json.dumps(tieke_address_data) # UTF-8 encoded string txid = contract.transact().setInvoicingAddressData( vat_id, address, ContentType.TiekeAddressData.value, tieke_address_data) assert check_succesful_tx(contract, txid) print("Done with {} {}".format(vat_id, address)) return address
def get_price(contract: Contract, now: datetime.datetime): contract.transact().setNow(to_timestamp(now)) return contract.call().getPrice()
def close_open_channels(private_key: str, state: ChannelManagerState, channel_manager_contract: Contract, gas_price: int = None, wait=lambda: gevent.sleep(1)): web3 = channel_manager_contract.web3 pending_txs = {} for channel in state.channels.values(): if not channel.last_signature: continue channel_id = (channel.sender, channel.receiver, channel.open_block_number) try: channel_info = channel_manager_contract.call().getChannelInfo( *channel_id) except (BadFunctionCallOutput, TransactionFailed): continue _, deposit, settle_block_number, closing_balance, transferred_tokens = channel_info available_tokens = channel.balance - transferred_tokens if not channel.balance <= deposit: log.info('Invalid channel: balance %d > deposit %d', channel.balance, deposit) continue closing_sig = utils.sign_close(private_key, channel.sender, channel.open_block_number, channel.balance, channel_manager_contract.address) raw_tx = utils.create_signed_contract_transaction( private_key, channel_manager_contract, 'cooperativeClose', [ channel.receiver, channel.open_block_number, channel.balance, decode_hex(channel.last_signature), closing_sig ], gas_price=gas_price, ) tx_hash = web3.eth.sendRawTransaction(raw_tx) log.info('Sending cooperative close tx (hash: %s): %d from %r', encode_hex(tx_hash), available_tokens, channel_id) pending_txs[channel_id] = (tx_hash, available_tokens) success = 0 total_tokens = 0 total_gas = 0 gas_price = 0 for channel_id, close_info in pending_txs.items(): tx_hash, available_tokens = close_info receipt = None # wait for tx to be mined while True: receipt = web3.eth.getTransactionReceipt(tx_hash) if not receipt or not receipt.blockNumber: wait() else: break tx = web3.eth.getTransaction(tx_hash) total_gas += receipt.gasUsed gas_price = tx.gasPrice if receipt.gasUsed == tx.gas or getattr(receipt, 'status', None) == 0: log.error('Transaction failed (hash: %s, tokens: %d, channel: %r)', encode_hex(tx_hash), available_tokens, channel_id) else: log.info('Transaction success (hash: %s, tokens: %d, channel: %r)', encode_hex(tx_hash), available_tokens, channel_id) success += 1 total_tokens += available_tokens log.info( 'FINISHED Close all channels: total tokens recovered: %d, ' 'transactions succeeded: %d, total gas cost: %s ETH', total_tokens, success, web3.fromWei(total_gas * gas_price, 'ether'), )
def test_sign_balance_proof_contract(channel_manager_contract: Contract): sig = sign_balance_proof(SENDER_PRIVATE_KEY, RECEIVER_ADDR, 37, 15, channel_manager_contract.address) sender_recovered = channel_manager_contract.call( ).extractBalanceProofSignature(RECEIVER_ADDR, 37, 15, sig) assert is_same_address(sender_recovered, SENDER_ADDR)
def test_sign_close_contract(channel_manager_contract: Contract): sig = sign_close(RECEIVER_PRIVATE_KEY, SENDER_ADDR, 315832, 13, channel_manager_contract.address) receiver_recovered = channel_manager_contract.call( ).extractClosingSignature(SENDER_ADDR, 315832, 13, sig) assert is_same_address(receiver_recovered, RECEIVER_ADDR)
def test_change_multisig(chain: TestRPCChain, ico: Contract, customer: str, preico_starts_at, preico_ends_at, team_multisig): """Owner can update the multisig address.""" ico.transact({"from": team_multisig}).setMultisig(customer) assert ico.call().multisigWallet() == customer
def load(chain, web3: Web3, address: str, csv_file: str, token: Contract, address_column: str, amount_column: str, vault_address: str): decimals = token.call().decimals() decimal_multiplier = 10**decimals transaction = {"from": address} TokenVault = chain.contract_factories.TokenVault token_vault = TokenVault(address=vault_address) # Check that our tokens are the same assert token_vault.call().token().lower() == token.address.lower() print("Starting to import investor data to ", token_vault.address) print("Reading data", csv_file) with open(csv_file, "rt") as inp: reader = csv.DictReader(inp) rows = [row for row in reader] # Check that we have unique addresses uniq_addresses = set() total = 0 for row in rows: addr = row[address_column].strip() amount = row[amount_column].strip() if addr in uniq_addresses: raise RuntimeError("Address appears twice in input data", addr) uniq_addresses.add(addr) amount = Decimal(amount) total += amount if amount <= 0: raise RuntimeError("Invalid amount:".format(amount)) if token_vault.call().tokensToBeAllocated() != total * decimal_multiplier: raise RuntimeError("Expected total amount {}, CSV sum is {}".format( token_vault.call().tokensToBeAllocated(), total)) # Start distribution start_time = time.time() start_balance = from_wei(web3.eth.getBalance(address), "ether") tx_to_confirm = [] # List of txids to confirm tx_batch_size = 16 # How many transactions confirm once print("Total rows", len(rows)) for i in range(len(rows)): data = rows[i] addr = data[address_column].strip() tokens = Decimal(data[amount_column].strip()) tokens *= decimal_multiplier end_balance = from_wei(web3.eth.getBalance(address), "ether") spent = start_balance - end_balance # http://stackoverflow.com/a/19965088/315168 if not tokens % 1 == 0: raise RuntimeError( "Could not issue tokens because after multiplication was not integer" ) tokens = int(tokens) print("Row", i, "giving", tokens, "to", addr, "vault", token_vault.address, "time passed", time.time() - start_time, "ETH spent", spent) if token_vault.call().balances(addr) > 0: print("Already issued, skipping") continue txid = token_vault.transact(transaction).setInvestor(addr, tokens) tx_to_confirm.append(txid) # Confirm N transactions when batch max size is reached if len(tx_to_confirm) >= tx_batch_size: check_multiple_succesful_txs(web3, tx_to_confirm) tx_to_confirm = [] # Confirm dangling transactions check_multiple_succesful_txs(web3, tx_to_confirm) end_balance = from_wei(web3.eth.getBalance(address), "ether") print("Deployment cost is", start_balance - end_balance, "ETH")