def test_num256_mod(assert_tx_failed): num256_code = """ def _num256_mod(x: num256, y: num256) -> num256: return num256_mod(x, y) def _num256_addmod(x: num256, y: num256, z: num256) -> num256: return num256_addmod(x, y, z) def _num256_mulmod(x: num256, y: num256, z: num256) -> num256: return num256_mulmod(x, y, z) """ c = get_contract(num256_code) t.s = s assert c._num256_mod(3, 2) == 1 assert c._num256_mod(34, 32) == 2 assert c._num256_addmod(1, 2, 2) == 1 assert c._num256_addmod(32, 2, 32) == 2 assert c._num256_addmod((2**256) - 1, 0, 2) == 1 assert_tx_failed(t, lambda: c._num256_addmod((2**256) - 1, 1, 1)) assert c._num256_mulmod(3, 1, 2) == 1 assert c._num256_mulmod(200, 3, 601) == 600 assert c._num256_mulmod(2**255, 1, 3) == 2 assert_tx_failed(t, lambda: c._num256_mulmod(2**255, 2, 1))
def test_invalid_contract_reference_call(assert_tx_failed): contract = """ def bar(arg1: address, arg2: num) -> num: return Foo(arg1).foo(arg2) """ t.s = t.Chain() assert_tx_failed(t, lambda: get_contract(contract), exception = VariableDeclarationException)
def test_logging_fails_with_when_log_is_undeclared(assert_tx_failed): loggy_code = """ def foo(): log.MyLog() """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), VariableDeclarationException)
def test_ownership(assert_tx_failed): code = """ owners: address[2] @public def __init__(): self.owners[0] = msg.sender @public def set_owner(i: num, new_owner: address): assert msg.sender in self.owners self.owners[i] = new_owner @public def is_owner() -> bool: return msg.sender in self.owners """ c = get_contract_with_gas_estimation(code) assert c.is_owner() is True # contract creator is owner. assert c.is_owner(sender=t.k1) is False # no one else is. # only an owner may set another owner. assert_tx_failed(lambda: c.set_owner(1, t.a1, sender=t.k1)) c.set_owner(1, t.a1) assert c.is_owner(sender=t.k1) is True # Owner in place 0 can be replaced. c.set_owner(0, t.a1) assert c.is_owner() is False
def test_logging_fails_after_a_global_declaration(assert_tx_failed): loggy_code = """ age: num MyLog: __log__({arg1: bytes <= 3}) """ t.s = s assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), StructureException)
def test_invalid_external_contract_call_to_the_same_contract(assert_tx_failed): contract_1 = """ def bar() -> num: return 1 """ contract_2 = """ class Bar(): def bar() -> num: pass def bar() -> num: return 1 def _stmt(x: address): Bar(x).bar() def _expr(x: address) -> num: return Bar(x).bar() """ t.s = t.Chain() c1 = get_contract(contract_1) c2 = get_contract(contract_2) c2._stmt(c1.address) c2._expr(c1.address) assert_tx_failed(t, lambda: c2._stmt(c2.address)) assert_tx_failed(t, lambda: c2._expr(c2.address))
def test_constant_external_contract_call_cannot_change_state(assert_tx_failed): contract_1 = """ lucky: public(num) @public def set_lucky(_lucky: num) -> num: self.lucky = _lucky return _lucky """ lucky_number = 7 c = get_contract_with_gas_estimation(contract_1) contract_2 = """ class Foo(): def set_lucky(_lucky: num) -> num: pass @public @constant def set_lucky_expr(arg1: address, arg2: num): Foo(arg1).set_lucky(arg2) @public @constant def set_lucky_stmt(arg1: address, arg2: num) -> num: return Foo(arg1).set_lucky(arg2) """ c2 = get_contract_with_gas_estimation(contract_2) assert_tx_failed(lambda: c2.set_lucky_expr(c.address, lucky_number)) assert_tx_failed(lambda: c2.set_lucky_stmt(c.address, lucky_number)) print( 'Successfully tested an constant external contract call attempted state change' )
def test_logging_fails_with_over_three_topics(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: indexed(num), arg2: indexed(num), arg3: indexed(num), arg4: indexed(num)}) def __init__(): log.MyLog(1, 2, 3, 4) """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), VariableDeclarationException)
def test_fails_when_input_data_is_the_wrong_size(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: bytes <= 3}) def foo(arg1: bytes <= 4): log.MyLog(arg1) """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), TypeMismatchException)
def test_fails_when_topic_is_the_wrong_size(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: indexed(bytes <= 3)}) def foo(): log.MyLog('bars') """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), TypeMismatchException)
def test_logging_fails_after_a_function_declaration(assert_tx_failed): loggy_code = """ def foo(): pass MyLog: __log__({arg1: bytes <= 3}) """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), StructureException)
def test_logging_fails_with_topic_type_mismatch(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: indexed(num)}) def foo(): log.MyLog(self) """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), TypeMismatchException)
def test_fails_when_log_data_is_over_32_bytes(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: bytes <= 100}) def foo(): pass """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), VariableDeclarationException)
def test_fails_when_input_is_the_wrong_type(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: indexed(num)}) def foo_(): log.MyLog('yo') """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), TypeMismatchException)
def test_logging_fails_with_data_type_mismatch(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: bytes <= 3}) def foo(): log.MyLog(self) """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), AttributeError)
def test_event_logging_cannot_have_more_than_three_topics(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: indexed(bytes <= 3), arg2: indexed(bytes <= 4), arg3: indexed(address), arg4: indexed(num)}) @public def foo(): log.MyLog('bar', 'home', self) """ assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), VariableDeclarationException)
def test_fails_when_data_is_the_wrong_size(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: bytes <= 3}) @public def foo(): log.MyLog('bars') """ t.s = s assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException)
def test_logging_fails_with_duplicate_log_names(assert_tx_failed): loggy_code = """ MyLog: __log__({}) MyLog: __log__({}) def foo(): log.MyLog() """ t.s = s assert_tx_failed(t, lambda: get_contract(loggy_code), VariableDeclarationException)
def test_external_contracts_must_be_declared_first_2(assert_tx_failed): contract = """ MyLog: __log__({}) class Foo(): def foo(arg2: num) -> num: pass """ t.s = t.Chain() assert_tx_failed(t, lambda: get_contract(contract), exception = StructureException)
def test_invalid_contract_reference_return_type(assert_tx_failed): contract = """ class Foo(): def foo(arg2: num) -> invalid: pass def bar(arg1: address, arg2: num) -> num: return Foo(arg1).foo(arg2) """ t.s = t.Chain() assert_tx_failed(t, lambda: get_contract(contract), exception = InvalidTypeException)
def test_fails_when_input_topic_is_the_wrong_size(assert_tx_failed): loggy_code = """ MyLog: __log__({arg1: indexed(bytes <= 3)}) @public def foo(arg1: bytes <= 4): log.MyLog(arg1) """ t.s = s assert_tx_failed(lambda: get_contract_with_gas_estimation(loggy_code), TypeMismatchException)
def test_overbuy(tester, assert_tx_failed): # If all the stock has been bought, no one can buy more test_shares = int(tester.c.get_total_shares() / 2) test_value = int(test_shares * tester.c.get_price()) tester.c.buy_stock(sender=t.k1, value=test_value) tester.c.buy_stock(sender=t.k1, value=test_value) assert tester.c.stock_available() == 0 assert tester.c.get_holding(t.a1) == (test_shares * 2) one_stock = tester.c.get_price() assert_tx_failed(lambda: tester.c.buy_stock(sender=t.k1, value=one_stock)) assert_tx_failed(lambda: tester.c.buy_stock(sender=t.k2, value=one_stock))
def test_external_contracts_must_be_declared_first_1(assert_tx_failed): contract = """ item: public(num) class Foo(): def foo(arg2: num) -> num: pass """ t.s = t.Chain() assert_tx_failed(lambda: get_contract(contract), exception=StructureException)
def test_abort(srp_tester, assert_tx_failed): srp_tester.c = srp_tester.s.contract(contract_code, language = "viper", args = [], value=2) #Only sender can trigger refund assert_tx_failed(lambda: srp_tester.c.abort(sender=srp_tester.k2)) #Refund works correctly srp_tester.c.abort(sender=srp_tester.k0) assert check_balance(srp_tester) == [INIT_BAL, INIT_BAL] #Purchase in process, no refund possible srp_tester.c = srp_tester.s.contract(contract_code, language = "viper", args = [], value=2) srp_tester.c.purchase(value=2, sender=srp_tester.k1) assert_tx_failed(lambda: srp_tester.c.abort(sender=srp_tester.k0))
def test_received(srp_tester, assert_tx_failed): srp_tester.c = srp_tester.s.contract(contract_code, language = "viper", args = [], value=2) #Can only be called after purchase assert_tx_failed(lambda: srp_tester.c.received(sender=srp_tester.k1)) #Purchase completed srp_tester.c.purchase(value=2, sender=srp_tester.k1) #Check that e.g. sender cannot trigger received assert_tx_failed(lambda: srp_tester.c.received(sender=srp_tester.k0)) #Check if buyer can call receive srp_tester.c.received(sender=srp_tester.k1) #Final check if everything worked. 1 value has been transferred assert check_balance(srp_tester) == [INIT_BAL+1, INIT_BAL-1]
def test_invalid_contract_reference_declaration(assert_tx_failed): contract = """ class Bar(): get_magic_number: 1 best_number: public(num) def __init__(): pass """ t.s = t.Chain() assert_tx_failed(t, lambda: get_contract(contract), exception = StructureException)
def test_initial_state(srp_tester, assert_tx_failed): assert check_balance(srp_tester) == [INIT_BAL, INIT_BAL] #Inital deposit has to be divisible by two assert_tx_failed(lambda: srp_tester.s.contract(contract_code, language = "viper", args = [], value = 1)) #Seller puts item up for sale srp_tester.c = tester.s.contract(contract_code, language = "viper", args = [], value=2) #Check that the seller is set correctly assert utils.remove_0x_head(srp_tester.c.get_seller()) == srp_tester.accounts[0].hex() #Check if item value is set correctly (Half of deposit) assert srp_tester.c.get_value() == 1 #Check if unlocked() works correctly after initialization assert srp_tester.c.get_unlocked() == True #Check that sellers (and buyers) balance is correct assert check_balance(srp_tester) == [INIT_BAL-2, INIT_BAL]
def test_num256_with_exponents(assert_tx_failed): exp_code = """ def _num256_exp(x: num256, y: num256) -> num256: return num256_exp(x,y) """ c = get_contract(exp_code) t.s = s assert c._num256_exp(2, 0) == 1 assert c._num256_exp(2, 1) == 2 assert c._num256_exp(2, 3) == 8 assert_tx_failed(t, lambda: c._num256_exp(2**128, 2)) assert c._num256_exp(2**64, 2) == 2**128 assert c._num256_exp(7**23, 3) == 7**69
def test_num_bound(assert_tx_failed): num_bound_code = """ @public def _num(x: num) -> num: return x @public def _num_add(x: num, y: num) -> num: return x + y @public def _num_sub(x: num, y: num) -> num: return x - y @public def _num_add3(x: num, y: num, z: num) -> num: return x + y + z @public def _num_max() -> num: return 170141183460469231731687303715884105727 # 2**127 - 1 @public def _num_min() -> num: return -170141183460469231731687303715884105728 # -2**127 """ c = get_contract_with_gas_estimation(num_bound_code) t.s = s NUM_MAX = 2**127 - 1 NUM_MIN = -2**127 assert c._num_add(NUM_MAX, 0) == NUM_MAX assert c._num_sub(NUM_MIN, 0) == NUM_MIN assert c._num_add(NUM_MAX - 1, 1) == NUM_MAX assert c._num_sub(NUM_MIN + 1, 1) == NUM_MIN assert_tx_failed(lambda: c._num_add(NUM_MAX, 1)) assert_tx_failed(lambda: c._num_sub(NUM_MIN, 1)) assert_tx_failed(lambda: c._num_add(NUM_MAX - 1, 2)) assert_tx_failed(lambda: c._num_sub(NUM_MIN + 1, 2)) assert c._num_max() == NUM_MAX assert c._num_min() == NUM_MIN assert_tx_failed(lambda: c._num_add3(NUM_MAX, 1, -1)) assert c._num_add3(NUM_MAX, -1, 1) == NUM_MAX
def test_transfer(token_tester, assert_tx_failed): # Basic transfer. assert token_tester.c.transfer(token_tester.accounts[1], 1) is True assert token_tester.c.balanceOf(token_tester.accounts[1]) == 1 assert token_tester.c.balanceOf(token_tester.accounts[0]) == TOKEN_TOTAL_SUPPLY - 1 # Some edge cases: # more than allowed assert token_tester.c.transfer(token_tester.accounts[1], TOKEN_TOTAL_SUPPLY) is False # Negative transfer value. assert_tx_failed( tester=token_tester, function_to_test=lambda: tester.c.transfer(token_tester.accounts[1], -1), exception=ValueOutOfBounds )