def test_unwrap_amount_for_account_and_distribute_fees(self): amount = 100 fees = 1 res = self.bender_contract.unwrap_erc20( unwrap_fungible_parameters(amount=amount, fees=fees)).interpret( storage=valid_storage(fees_ratio=100), self_address=self_address, source=user ) self.assertEqual(2, len(res.operations)) burn_operation = res.operations[0] self.assertEqual('0', burn_operation['amount']) self.assertEqual(f'{token_contract}', burn_operation['destination']) self.assertEqual('tokens', burn_operation['parameters']['entrypoint']) self.assertEqual(michelson_to_micheline(f'(Left {{ Pair "{user}" 1 {amount + fees} }})'), burn_operation['parameters']['value']) mint_operation = res.operations[1] self.assertEqual('0', mint_operation['amount']) self.assertEqual(f'{token_contract}', mint_operation['destination']) self.assertEqual('tokens', mint_operation['parameters']['entrypoint']) self.assertEqual(michelson_to_micheline(f'(Right {{ Pair "{self_address}" 1 {fees} }})'), mint_operation['parameters']['value']) self.assertEqual(fees, self._tokens_of(res.storage, self_address, (token_contract, 1)))
def compile(self, view_name, return_type=None, description="", pure=True): (parameter, main_return_type) = self._compile_parameter(view_name) result = { "name": view_name, "description": description, "pure": pure, "implementations": [{ "michelsonStorageView": { "returnType": michelson_to_micheline(return_type) if return_type is not None else main_return_type, "code": self._compile_expression(view_name) } }] } if parameter != json.loads('{"prim": "unit"}'): result["implementations"][0]["michelsonStorageView"][ "parameter"] = parameter return result
def test_should_transfer_all_tokens_from_contract(self): storage = valid_storage() first_token_address = (token_contract, 0) second_token_address = (token_contract, 1) with_token_balance(signer_1_key, first_token_address, 100, storage) with_token_balance(signer_1_key, second_token_address, 200, storage) res = self.minter_contract.withdraw_all_tokens( token_contract, [0, 1]).interpret(storage=storage, sender=signer_1_key, self_address=self_address) self.assertEqual(1, len(res.operations)) transfer = res.operations[0] self.assertEqual(token_contract, transfer['destination']) self.assertEqual("0", transfer['amount']) self.assertEqual('transfer', transfer['parameters']['entrypoint']) self.assertEqual( michelson_to_micheline( f'{{ Pair "{self_address}" {{ Pair "{signer_1_key}" 1 200 ; Pair "{signer_1_key}" 0 100 }} }}' ), transfer['parameters']['value']) self.assertEqual( None, self._tokens_of(res.storage, signer_1_key, first_token_address)) self.assertEqual( None, self._tokens_of(res.storage, signer_1_key, second_token_address))
def packed_payload(amount, token_id, block_hash, log_index): ty = MichelsonType.match(payload_type) call = minter_call(amount, token_id, block_hash, log_index) payload_value = michelson_to_micheline(f"(Pair " f" (Pair \"{chain_id}\" \"{self_address}\")" f" (Pair {call} \"{minter_contract}%minter\")" f")") return ty.from_micheline_value(payload_value).pack().hex()
def test_generates_only_one_mint_if_fees_to_low(self): amount = 1 res = self.minter_contract.mint_erc20( mint_erc20_parameters(amount=amount)).interpret( storage=valid_storage(fees_ratio=1), sender=quorum_contract) self.assertEqual(1, len(res.operations)) user_mint = res.operations[0] self.assertEqual( michelson_to_micheline(f'( Right {{ Pair "{user}" 1 {amount}}})'), user_mint['parameters']['value'])
def test_calls_erc721_mint(self): res = self.bender_contract.mint_erc721(mint_erc721_parameters(token_id=5)) \ .interpret(storage=valid_storage(nft_fees=20), sender=super_admin, amount=20, self_address=self_address) self.assertEqual(1, len(res.operations)) user_mint = res.operations[0] self.assertEqual('0', user_mint['amount']) self.assertEqual(f'{nft_contract}', user_mint['destination']) self.assertEqual('tokens', user_mint['parameters']['entrypoint']) self.assertEqual(michelson_to_micheline( f'( Right {{ Pair "{user}" 5 1 }})'), user_mint['parameters']['value']) self.assertEqual(20, self._xtz_of(self_address, res.storage))
def test_should_send_current_quorum_for_xtz_distribution(self): res = self.contract.distribute_xtz_with_quorum(minter_contract) \ .interpret( storage=storage(), sender=first_signer_key.public_key_hash(), self_address=self_address) self.assertEqual(1, len(res.operations)) op = res.operations[0] self.assertEqual(minter_contract, op["destination"]) self.assertEqual('oracle', op["parameters"]["entrypoint"]) self.assertEqual(michelson_to_micheline( f'(Right {{ "{first_signer_key.public_key_hash()}" }})'), op['parameters']['value'])
def test_should_send_current_quorum_for_tokens_distribution(self): tokens = [('KT1RXpLtz22YgX24QQhxKVyKvtKZFaAVtTB9', 0)] res = self.contract.distribute_tokens_with_quorum(minter_contract=minter_contract, tokens=tokens) \ .interpret( storage=storage(), sender=first_signer_key.public_key_hash(), self_address=self_address) self.assertEqual(1, len(res.operations)) op = res.operations[0] self.assertEqual(minter_contract, op["destination"]) self.assertEqual('oracle', op["parameters"]["entrypoint"]) self.assertEqual(michelson_to_micheline( f'(Left (Pair {{ "{first_signer_key.public_key_hash()}" }} ' f'{{ Pair "KT1RXpLtz22YgX24QQhxKVyKvtKZFaAVtTB9" 0 }} ))'), op['parameters']['value'])
def test_takes_no_fees_if_amount_to_small(self): amount = 10 fees = 0 res = self.minter_contract.unwrap_erc20( unwrap_fungible_parameters(amount=amount, fees=fees)).interpret( storage=valid_storage(fees_ratio=200), source=user) self.assertEqual(1, len(res.operations)) burn_operation = res.operations[0] self.assertEqual('0', burn_operation['amount']) self.assertEqual(f'{token_contract}', burn_operation['destination']) self.assertEqual('tokens', burn_operation['parameters']['entrypoint']) self.assertEqual( michelson_to_micheline(f'(Left {{ Pair "{user}" 1 {amount} }})'), burn_operation['parameters']['value'])
def test_should_set_signer_payment_address(self): payment_address = Key.generate(export=False).public_key_hash() signature = first_signer_key.sign(self._pack_set_payment_address(0, payment_address)) res = self.contract.set_signer_payment_address(minter_contract=minter_contract, signer_id=first_signer_id, signature=signature).interpret( storage=storage(), sender=payment_address, self_address=self_address, chain_id=chain_id) self.assertEqual(1, len(res.operations)) op = res.operations[0] self.assertEqual(minter_contract, op["destination"]) self.assertEqual('signer_ops', op["parameters"]["entrypoint"]) self.assertEqual(michelson_to_micheline( f'(Pair "{first_signer_key.public_key_hash()}" "{payment_address}")'), op['parameters']['value']) self.assertEqual(1, res.storage["counters"][first_signer_id])
def test_accepts_valid_signature(self): amount = 10000000 token_id = b"contract_on_eth" block_hash = b"txId" log_index = 5 packed = packed_payload(amount, token_id, block_hash, log_index) params = forge_params(amount, token_id, block_hash, log_index, [[first_signer_id, first_signer_key.sign(packed)]]) res = self.contract.minter(params).interpret(storage=storage(), sender=first_signer_key.public_key_hash(), chain_id=chain_id, self_address=self_address) self.assertEqual(1, len(res.operations)) user_mint = res.operations[0] self.assertEqual(minter_contract, user_mint["destination"]) self.assertEqual(michelson_to_micheline(minter_call(amount, token_id, block_hash, log_index)), user_mint['parameters']['value'])
def test_should_transfer_token(self): storage = valid_storage() token_address = (token_contract, 0) with_token_balance(signer_1_key, token_address, 100, storage) res = self.bender_contract.withdraw_token(token_contract, 0, 40).interpret(storage=storage, sender=signer_1_key, self_address=self_address) self.assertEqual(1, len(res.operations)) self.assertEqual(token_contract, res.operations[0]['destination']) self.assertEqual("0", res.operations[0]['amount']) self.assertEqual('transfer', res.operations[0]['parameters']['entrypoint']) self.assertEqual(michelson_to_micheline(f'{{ Pair "{self_address}" {{ Pair "{signer_1_key}" 0 40 }} }}'), res.operations[0]['parameters']['value']) t = self._tokens_of(res.storage, signer_1_key, token_address) self.assertEqual(60, t)
def test_calls_fa2_mint_for_user_and_collect_fees(self): amount = 1 * 10 ** 16 res = self.bender_contract.mint_erc20( mint_erc20_parameters(amount=amount)).interpret( storage=valid_storage(fees_ratio=1), self_address=self_address, sender=super_admin) self.assertEqual(1, len(res.operations)) user_mint = res.operations[0] self.assertEqual('0', user_mint['amount']) self.assertEqual(f'{token_contract}', user_mint['destination']) self.assertEqual('tokens', user_mint['parameters']['entrypoint']) collected_fees = int(0.0001 * 10 ** 16) self.assertEqual(michelson_to_micheline( f'( Right {{ Pair "{user}" 1 {int(0.9999 * 10 ** 16)} ; Pair "{self_address}" 1 {collected_fees} }})'), user_mint['parameters']['value']) self.assertEqual(collected_fees, self._tokens_of(res.storage, self_address, (token_contract, 1)))
def test_unwrap_nft(self): token_id = 1337 fees = 10 res = self.bender_contract.unwrap_erc721( unwrap_nft_parameters(token_id=token_id)).interpret( storage=valid_storage(nft_fees=fees), sender=user, amount=10, self_address=self_address ) self.assertEqual(1, len(res.operations)) burn_operation = res.operations[0] self.assertEqual('0', burn_operation['amount']) self.assertEqual(f'{nft_contract}', burn_operation['destination']) self.assertEqual('tokens', burn_operation['parameters']['entrypoint']) self.assertEqual(michelson_to_micheline(f'(Left {{ Pair "{user}" 1337 1}})'), burn_operation['parameters']['value']) self.assertEqual(10, self._xtz_of(self_address, res.storage))
def test_accepts_minting_even_with_bad_signature_if_threshold_is_reached(self): amount = 10000000 token_id = b"contract_on_eth" block_hash = b"txId" log_index = 3 packed = packed_payload(amount, token_id, block_hash, log_index) bad = packed_payload(amount, token_id, block_hash, log_index + 1) params = forge_params(amount, token_id, block_hash, log_index, [ [first_signer_id, first_signer_key.sign(packed)], [second_signer_id, second_signer_key.sign(bad)] ]) res = self.contract.minter(params).interpret(storage=storage_with_two_keys(threshold=1), sender=first_signer_key.public_key_hash(), chain_id=chain_id, self_address=self_address) self.assertEqual(1, len(res.operations)) user_mint = res.operations[0] self.assertEqual(minter_contract, user_mint["destination"]) self.assertEqual(michelson_to_micheline(minter_call(amount, token_id, block_hash, log_index)), user_mint['parameters']['value'])
def _pack_set_payment_address(counter, payment_address): ty = MichelsonType.match( michelson_to_micheline(f"(pair (pair chain_id address) (pair nat (pair address address)))")) return ty.from_python_object([chain_id, self_address, counter, minter_contract, payment_address]).pack().hex()
minter_ep = """(or (or (pair %add_fungible_token (bytes %eth_contract) (pair %token_address address nat)) (pair %add_nft (bytes %eth_contract) (address %token_contract))) (or (pair %mint_fungible_token (bytes %erc_20) (pair (pair %event_id (bytes %block_hash) (nat %log_index)) (pair (address %owner) (nat %amount)))) (pair %mint_nft (bytes %erc_721) (pair (pair %event_id (bytes %block_hash) (nat %log_index)) (pair (address %owner) (nat %token_id))))))""" first_signer_id = "k51qzi5uqu5dilfdi6xt8tfbw4zmghwewcvvktm7z9fk4ktsx4z7wn0mz2glje" second_signer_id = "k51qzi5uqu5dhuc1pto6x98woksrqgwhq6d1lff2hfymxmlk4qd7vqgtf980yl" first_signer_key = Key.generate(curve=b'sp', export=False) second_signer_key = Key.generate(curve=b'sp', export=False) payload_type = michelson_to_micheline(f"(pair (pair chain_id address) (pair {minter_ep} address))") self_address = "KT1BEqzn5Wx8uJrZNvuS9DVHmLvG9td3fDLi" class QuorumContractTest(unittest.TestCase): @classmethod def setUpClass(cls) -> None: root_dir = Path(__file__).parent.parent / "ligo" cls.contract = LigoContract(root_dir / "quorum" / "multisig.mligo", "main").get_contract() class SignerTest(QuorumContractTest): def test_accepts_valid_signature(self): amount = 10000000 token_id = b"contract_on_eth"