예제 #1
0
 def __init__(self, admin):
     with open('metadata/metadata.json', 'r') as f:
         #loads then dumps to confirm correctly formatted json
         metadata = json.dumps(json.load(f))
         self.init(
             paused=False,
             balances=sp.big_map(tvalue=sp.TRecord(
                 approvals=sp.TMap(sp.TAddress, sp.TNat), balance=sp.TNat)),
             administrator=admin,
             totalSupply=0,
             permits=sp.big_map(tkey=sp.TPair(sp.TAddress, sp.TBytes),
                                tvalue=sp.TTimestamp),
             user_expiries=sp.big_map(tkey=sp.TAddress,
                                      tvalue=sp.TOption(sp.TNat)),
             permit_expiries=sp.big_map(tkey=sp.TPair(
                 sp.TAddress, sp.TBytes),
                                        tvalue=sp.TOption(sp.TNat)),
             counter=0,
             default_expiry=50000,
             max_expiry=2628000,
             metadata=sp.big_map(
                 l={
                     "": sp.bytes_of_string("tezos-storage:md-json"),
                     "md-json": sp.bytes_of_string(metadata)
                 }))
예제 #2
0
def test():
    time = sp.timestamp(1571761674)
    # Create test scenario
    scenario = sp.test_scenario()

    scenario.table_of_contents()

    # sp.test_account generates ED25519 key-pairs deterministically:
    alice = sp.test_account("Alice")
    bob = sp.test_account("Robert")

    # Create HTML output for debugging
    scenario.h1("Dutch Auction")

    # Instantiate Auction contract
    auction = DutchAuction(alice.address)
    scenario += auction

    alice_wallet = NFTWallet(alice.address)
    bob_wallet = NFTWallet(bob.address)

    scenario += alice_wallet
    scenario += bob_wallet

    scenario.h2("Create NFT")

    token_metadata = sp.map({"name": sp.bytes_of_string("Nft1")})
    scenario += alice_wallet.createNft(token_metadata).run(sender=alice)

    scenario.h2("Configure and start auction")
    scenario += alice_wallet.configNftAuction(auction_address=auction.address,
                                              opening_price=100,
                                              reserve_price=10,
                                              start_time=time,
                                              round_time=1000,
                                              ticket_id=0).run(source=alice,
                                                               sender=alice,
                                                               now=time)
    scenario.verify(~alice_wallet.data.tickets.contains(0))
    time = time.add_seconds(1)
    scenario += auction.startAuction().run(sender=alice, now=time)

    time = time.add_seconds(6001)

    scenario += auction.dropPrice(90).run(sender=alice, now=time)

    scenario.h2("Bob buys")
    time = time.add_seconds(1)
    scenario += auction.buy(bob_wallet.address).run(sender=bob,
                                                    source=bob,
                                                    now=time,
                                                    amount=sp.mutez(90))
    scenario.verify(bob_wallet.data.tickets.contains(0))
    scenario.verify(~auction.data.ticket.is_some())
예제 #3
0
    def __init__(self, admin, supply, **extra_storage):
        contract_metadata = sp.big_map(
            l = {
                "": sp.bytes_of_string('tezos-storage:data'),
                "data": sp.bytes_of_string(
                    """{ 
                        "name": "SmartLink",
                        "description": "Decentralized escrow platform for Web 3.0",
                        "authors": ["SmartLink Dev Team <*****@*****.**>"],
                        "homepage": "https://smartlink.so/",
                        "interfaces": [ "TZIP-007", "TZIP-016"],
                        "symbol":"SMAK",
                        "icon":"ipfs://QmU2C4jU154nwA71AKHeiEj79qe7ZQC4Mf7AeUj5ALXZfe",
                        "decimals":"3"
                    }"""
                )
            },
          tkey = sp.TString,
          tvalue = sp.TBytes            
        )

        token_metadata = sp.big_map(
            l = {
                0: (
                    0,
                    sp.map(
                        l = {
                            "name": sp.bytes_of_string('Smartlink'), 
                            "decimals": sp.bytes_of_string('3'),
                            "symbol": sp.bytes_of_string('SMAK'),
                            "icon": sp.bytes_of_string('ipfs://QmU2C4jU154nwA71AKHeiEj79qe7ZQC4Mf7AeUj5ALXZfe')
                        },
                        tkey = sp.TString,
                        tvalue = sp.TBytes
                    )
                )
            },
            tkey = sp.TNat,
            tvalue = sp.TPair(sp.TNat, sp.TMap(sp.TString, sp.TBytes))
        )
        
        self.balances = sp.big_map(
            l = {admin: sp.record(balance = supply, approvals = {})}, 
            tkey = sp.TAddress,
            tvalue = sp.TRecord(approvals = sp.TMap(sp.TAddress, sp.TNat), balance = sp.TNat)
        )
        
        self.init(
            balances = self.balances,
            metadata = contract_metadata,
            token_metadata = token_metadata, 
            frozen_accounts = sp.big_map(tkey = sp.TAddress, tvalue = sp.TTimestamp),
            totalSupply = supply,  
            **extra_storage
        )
예제 #4
0
def init_metadata(md):
    return sp.big_map(l={"": sp.bytes_of_string("tezos-storage:data"), "data": sp.bytes_of_string(md)})
예제 #5
0
    def test():
        scenario = sp.test_scenario()
        scenario.h1("Simple ST12 Contract")

        # sp.test_account generates ED25519 key-pairs deterministically:
        admin = sp.test_account("AccessControl")
        alice = sp.test_account("Alice")
        bob = sp.test_account("Robert")

        # Let's display the accounts:
        scenario.h2("Accounts")
        scenario.show([admin, alice, bob])

        c1 = ST12(
            config = config,
            administrators = sp.set([admin.address]),
            metadata = sp.map(l =  {
                # Remember that michelson wants map already in ordered
                "decimals" : sp.bytes_of_string("%d" % 18),
                "name" : sp.bytes_of_string("Test Token"),
                "symbol" : sp.bytes_of_string("Test")
            })
        )

        scenario += c1
            
        scenario.h2("Admin mints a few coins")
        scenario += c1.mint(sp.list([sp.record(address=alice.address, amount=12)])).run(sender=admin)
        scenario += c1.mint(sp.list([
            sp.record(address=alice.address, amount=3),
            sp.record(address=alice.address, amount=3),
            ])).run(sender=admin)
        scenario.h2("Alice transfers her own tokens to Bob")
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(
            sender=alice
        )
        scenario.verify(c1.data.ledger[alice.address].balance == 14)
        scenario.h2("Bob tries to transfer from Alice but he doesn't have her approval")
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(
            sender=bob, valid=False
        )
        scenario.h2("Alice approves Bob and Bob transfers")
        scenario += c1.approve(spender=alice.address, value=5).run(
            sender=alice
        )
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(
            sender=admin
        )
        scenario.h2("Bob tries to over-transfer from Alice")
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(
            sender=bob, valid=False
        )
        scenario.h2("Admin burns Bob token")
        scenario += c1.burn(sp.list([sp.record(address=bob.address, amount=1)])).run(sender=admin)
        scenario.verify(c1.data.ledger[alice.address].balance == 10)
        scenario.h2("Alice tries to burn Bob token")
        scenario += c1.burn(sp.list([sp.record(address=bob.address, amount=1)])).run(
            sender=alice, valid=False
        )
        scenario.h2("Admin pauses the contract and Alice cannot transfer anymore")
        scenario += c1.set_paused(True).run(sender=admin)
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(
            sender=alice, valid=False
        )
        scenario.verify(c1.data.ledger[alice.address].balance == 10)
        scenario.h2("Admin transfers while on pause")
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=1).run(
            sender=admin
        )
        scenario.h2("Admin unpauses the contract and transferts are allowed")
        scenario += c1.set_paused(False).run(sender=admin)
        scenario.verify(c1.data.ledger[alice.address].balance == 9)
        scenario += c1.transfer(from_=alice.address, to_=bob.address, value=1).run(
            sender=admin
        )

        scenario.verify(c1.data.total_supply == 17)
        scenario.verify(c1.data.ledger[alice.address].balance == 8)
        scenario.verify(c1.data.ledger[bob.address].balance == 9)
        
        scenario.h2("Burn")
        scenario += c1.burn(
            sp.list([
                sp.record(
                address=alice.address,
                amount=3
            )
            ])
        ).run(sender=admin)
        
        scenario += c1.burn(
            sp.list(
                [
                    sp.record(
                        address=alice.address,
                        amount=3
                    )
                ]
            )
        ).run(sender=admin)

        scenario.table_of_contents()
예제 #6
0
# This specific main uses the relative new feature of non-default tests
# sp.for the browser version.
if "templates" not in __name__:
    add_test(environment_config())
    # if not global_parameter("only_environment_test", False):
    #     add_test(FA12_config(debug_mode=True), is_default=not sp.in_browser)
    #     add_test(FA12_config(readable=False), is_default=not sp.in_browser)
    #     add_test(FA12_config(force_layouts=False), is_default=not sp.in_browser)
    #     add_test(FA12_config(lazy_entry_points=True), is_default=not sp.in_browser)
    #     add_test(
    #         FA12_config(lazy_entry_points_multiple=True), is_default=not sp.in_browser
    #     )

    sp.add_compilation_target(
        "ST12_compiled", 
        ST12(
            config = environment_config(),
            administrators = sp.set([sp.address("tz1M9CMEtsXm3QxA7FmMU2Qh7xzsuGXVbcDr")]),
            validators = sp.set([sp.address("KT1QkFxZqfCok6LZUJ7zDn6gCDBS7kSao26P")]),
            burners = sp.set([sp.address("KT1S3M3Cn7XBLcNi54cfvMP15j9ew4W4eb1C")]),
            minters = sp.set([sp.address("KT1S3M3Cn7XBLcNi54cfvMP15j9ew4W4eb1C")]),
            metadata = sp.big_map(l = {
                "": sp.bytes_of_string("tezos-storage:m"),
                "m" : sp.bytes_of_string("{\"name\":\"Test\",\"version\":\"security token v1.0\",\"description\":\"Test Digital Security Token\"}"),
                "name" : sp.bytes_of_string("Test"),
                "symbol" : sp.bytes_of_string("TST"),
                "decimals" : sp.bytes_of_string("18"),
            })
        )
    )
예제 #7
0
def test():
    scenario = sp.test_scenario()
    scenario.h1("Auction House")
    scenario.table_of_contents()

    admin = sp.test_account("Administrator")
    alice = sp.test_account("Alice")
    bob = sp.test_account("Robert")
    dan = sp.test_account("Dan")
    minter = sp.test_account("Minter")

    # Let's display the accounts:
    scenario.h2("Accounts")
    scenario.show([admin, alice, bob, dan, minter])

    auction_house = AuctionHouse()
    scenario += auction_house

    scenario.h2("AcuteArtFA2")
    fa2 = AcuteArtFA2(auction_house.address, minter.address)
    scenario += fa2

    scenario.h2("Initial minting")

    scenario.p("Minter mints token 0 with no royalty")
    scenario += fa2.mint(token_id = 0, royalty = sp.none, metadata = sp.bytes_of_string('ipfs://foo')).run(sender = minter.address)

    scenario.p("Alice fails to mint token 1")
    scenario += fa2.mint(token_id = 1, royalty = sp.none, metadata = sp.bytes_of_string('ipfs://foo')).run(sender = alice.address, valid=False)

    scenario.p("Minter fails to re-mint token 0")
    scenario += fa2.mint(token_id = 0, royalty = sp.none, metadata = sp.bytes_of_string('ipfs://foo')).run(sender = minter.address, valid=False)

    scenario.p("Minter sends token to Bob")
    scenario += fa2.transfer([BatchTransfer.item(minter.address, [sp.record(to_=bob.address, token_id=0, amount=1)])]).run(sender=minter, valid=True)

    scenario.p("Bob updates operators")
    scenario += fa2.update_operators([sp.variant('add_operator', sp.record(owner=bob.address,operator=auction_house.address,token_id=sp.nat(0)))]).run(sender=bob)

    scenario.h2("User Auction")
    scenario.p("Bob creates auction")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += auction_house.create_auction(sp.record(auction_id=auction_id, token_address=fa2.address, token_id=sp.nat(0), token_amount=sp.nat(1),  end_timestamp=sp.timestamp(60*60),  bid_amount=sp.mutez(100000))).run(sender=bob, now=sp.timestamp(0))

    scenario.p("Bob tries to withdraw")
    scenario += auction_house.withdraw(0).run(sender=bob, amount=sp.mutez(0), now=sp.timestamp(0), valid=False)

    scenario.p("Alice bids")
    scenario += auction_house.bid(0).run(sender=alice,amount=sp.mutez(200000), now=sp.timestamp(0))

    scenario.p("Dan bids")
    scenario += auction_house.bid(0).run(sender=dan,amount=sp.mutez(300000), now=sp.timestamp(1))

    scenario.p("Alice rebids")
    scenario += auction_house.bid(0).run(sender=alice,amount=sp.mutez(400000), now=sp.timestamp(2))

    scenario.p("Bob tries to withdraw")
    scenario += auction_house.withdraw(0).run(sender=bob, amount=sp.mutez(0), now=sp.timestamp(60*60), valid=False)

    scenario.p("Dan bids")
    scenario += auction_house.bid(0).run(sender=dan,amount=sp.mutez(500000), now=sp.timestamp(60*60-5))

    scenario.p("Alice rebids")
    scenario += auction_house.bid(0).run(sender=alice,amount=sp.mutez(600000), now=sp.timestamp(60*60+5*60-6))

    scenario.p("Alice withdraws")
    scenario += auction_house.withdraw(0).run(sender=alice, amount=sp.mutez(0), now=sp.timestamp(60*60+5*60-6+5*60+1))

    scenario.h2("Self-Withdraw")
    scenario.p("Alice creates auction")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += fa2.update_operators([sp.variant('add_operator', sp.record(owner=alice.address,operator=auction_house.address,token_id=sp.nat(0)))]).run(sender=alice)
    scenario += auction_house.create_auction(sp.record(auction_id=auction_id, token_address=fa2.address, token_id=sp.nat(0), token_amount=sp.nat(1),  end_timestamp=sp.timestamp(60*60),  bid_amount=sp.mutez(100000))).run(sender=alice, now=sp.timestamp(0))


    scenario.h2("Transfers")
    scenario.p("Bob cannot transfer alice's token")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += fa2.transfer([BatchTransfer.item(alice.address, [sp.record(to_=bob.address, token_id=0, amount=1)])]).run(sender=bob, valid=False)
    scenario.p("Alice cannot transfer own token")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += fa2.transfer([BatchTransfer.item(alice.address, [sp.record(to_=bob.address, token_id=0, amount=1)])]).run(sender=alice, valid=False)

    scenario.p("Bob bids")
    scenario += auction_house.bid(0).run(sender=bob, amount=sp.mutez(100000000), now=sp.timestamp(60))

    scenario.p("Bob withdraws")
    scenario += auction_house.withdraw(0).run(sender=bob, now=sp.timestamp(120*60))

    scenario.p("Auction house cannot transfer Bob's token before allowance")
    scenario += fa2.transfer([BatchTransfer.item(bob.address, [sp.record(to_=alice.address, token_id=0, amount=1)])]).run(sender=auction_house.address, valid=False)

    # scenario.show(fa2.data.ledger[LedgerKey.make(owner = auction_house.address, token_id = 0)])

    scenario.p("Auction house can transfer Bob's token after allowance")
    scenario += fa2.update_operators([sp.variant('add_operator', sp.record(owner=bob.address,operator=auction_house.address,token_id=0))]).run(sender=bob)
    scenario += fa2.transfer([BatchTransfer.item(bob.address, [sp.record(to_=alice.address, token_id=0, amount=1)])]).run(sender=auction_house.address)


    scenario.p("Bob cannot transfer more token")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += fa2.transfer([BatchTransfer.item(bob.address, [sp.record(to_=bob.address, token_id=0, amount=2)])]).run(sender=bob, valid=False)

    scenario.p("Bob cannot transfer from non balance address")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += fa2.transfer([BatchTransfer.item(alice.address, [sp.record(to_=dan.address, token_id=0, amount=1)])]).run(sender=bob, valid=False)

    scenario.p("Alice can transfer as owner")
    auction_id = sp.nat(0) # we can reuse 0
    scenario += fa2.transfer([BatchTransfer.item(alice.address, [sp.record(to_=dan.address, token_id=0, amount=1)])]).run(sender=alice)
    
    
    scenario.h2("Royalties Mechanics")
    auction_id = sp.nat(1)
    fraction = sp.nat(215000000) # 215000000/2**32 ~= 5%
    token_id = sp.nat(10)
    
    scenario.p("Minter mints token 10 with royalty")
    scenario += fa2.mint(token_id = token_id, royalty = sp.some(sp.record(recipient=minter.address, fraction=fraction)), metadata = sp.bytes_of_string('ipfs://foo')).run(sender = minter.address)

    scenario.p("Minter fails to send token to Bob")
    scenario += fa2.transfer([BatchTransfer.item(minter.address, [sp.record(to_=bob.address, token_id=token_id, amount=1)])]).run(sender=minter, valid=False)

    scenario.p("Minter updates operators")
    scenario += fa2.update_operators([sp.variant('add_operator', sp.record(owner=minter.address,operator=auction_house.address,token_id=token_id))]).run(sender=minter)
    
    scenario.p("Minter creates auction")
    scenario += auction_house.create_auction(sp.record(auction_id=auction_id, token_address=fa2.address, token_id=token_id, token_amount=sp.nat(1),  end_timestamp=sp.timestamp(60*60),  bid_amount=sp.mutez(100000))).run(sender=minter, now=sp.timestamp(0))
    
    scenario.p("No one has bid, no royalty expected...")
    scenario += auction_house.withdraw(auction_id).run(sender=minter, now=sp.timestamp(60*60+1))
    scenario.verify(~auction_house.data.accumulated_royalties.contains(minter.address))
    
    scenario.p("Minter updates operators")
    scenario += fa2.update_operators([sp.variant('add_operator', sp.record(owner=minter.address,operator=auction_house.address,token_id=token_id))]).run(sender=minter)
    
    scenario.p("Minter creates new auction")
    scenario += auction_house.create_auction(sp.record(auction_id=auction_id, token_address=fa2.address, token_id=token_id, token_amount=sp.nat(1),  end_timestamp=sp.timestamp(60*60),  bid_amount=sp.mutez(100000))).run(sender=minter, now=sp.timestamp(0))
    
    scenario += auction_house.bid(auction_id).run(sender=alice,amount=sp.tez(100), now=sp.timestamp(0))
    
    scenario.p("Now we have a bid, we expect royalty")
    scenario += auction_house.withdraw(auction_id).run(sender=minter, now=sp.timestamp(60*60+1))
    scenario.verify(auction_house.data.accumulated_royalties.contains(minter.address))
    scenario.verify_equal(auction_house.data.accumulated_royalties[minter.address],sp.mutez(5005858))
    
    scenario.p("Only minter can collect royalties")
    scenario += auction_house.collect_royalties(bob.address).run(sender=bob, valid=False)
    scenario += auction_house.collect_royalties(minter.address).run(sender=minter, valid=True)
    scenario.verify(~auction_house.data.accumulated_royalties.contains(minter.address))
    
    
    scenario.p("Only royalty recipient can update _own_ recipient")
    scenario += auction_house.update_royalty_recipient(sp.record(fa2_address=fa2.address, new_recipient=bob.address, token_id=token_id)).run(sender=bob, valid=False)
    
    scenario += auction_house.update_royalty_recipient(sp.record(fa2_address=fa2.address, new_recipient=bob.address, token_id=sp.nat(0))).run(sender=bob, valid=False)
    
    scenario += auction_house.update_royalty_recipient(sp.record(fa2_address=fa2.address, new_recipient=bob.address, token_id=sp.nat(0))).run(sender=minter, valid=False)
    
    
    scenario += auction_house.update_royalty_recipient(sp.record(fa2_address=fa2.address, new_recipient=bob.address, token_id=token_id)).run(sender=minter, valid=True)
    
    scenario += auction_house.update_royalty_recipient(sp.record(fa2_address=fa2.address, new_recipient=alice.address, token_id=token_id)).run(sender=minter, valid=False)
예제 #8
0
 def test():
     scenario = sp.test_scenario()
     
     scenario.h1("VestingEscrowMinterBurnerWallet")
     
     admin = sp.test_account("Token Admin")
     alice = sp.test_account("Alice")
     bob = sp.test_account("Bob")
     
     fa12 = ST12(admin.address)
     fa2 = ST2(admin.address)
     v = VestingEscrowMinterBurnerWallet()
     
     scenario += fa12
     scenario += fa2
     scenario += v
     scenario += v.vest(
         sp.list([
             sp.record(
                 schedule_name = "4 Months Cliff Vesting From 12-12-2020",
                 beneficiery = alice.address, 
                 start = sp.timestamp(0), 
                 cliff = sp.timestamp(5), 
                 end = sp.timestamp(10), 
                 vesting_amount = 100,
                 token_address = fa2.address,
                 token_id = sp.some(0),
                 metadata = sp.some(sp.map({
                     "decimals": sp.bytes_of_string("%d" % 18),
                     "name": sp.bytes_of_string("Test"),
                     "symbol": sp.bytes_of_string("TEST")
                 }))
             )
         ])
     )
     
     scenario += v.claim().run(sender = alice, now = sp.timestamp(5))
     scenario += v.claim().run(sender = alice, now = sp.timestamp(7))
     scenario += v.claim().run(sender = alice, now = sp.timestamp(10))
     scenario += v.claim().run(sender = alice, now = sp.timestamp(10), valid=False)
     scenario += v.claim().run(sender = alice, now = sp.timestamp(15), valid=False)
     
     scenario += v.vest(
         sp.list([
             sp.record(
                 schedule_name = "5 Months Cliff Vesting From 12-12-2020",
                 beneficiery = alice.address, 
                 start = sp.timestamp(0), 
                 cliff = sp.timestamp(5), 
                 end = sp.timestamp(10), 
                 vesting_amount = 200,
                 token_address = fa12.address,
                 token_id = sp.none,
                 metadata = sp.none
             ),
             sp.record(
                 schedule_name = "8 Months Cliff Vesting From 12-12-2020",
                 beneficiery = bob.address, 
                 start = sp.timestamp(0), 
                 cliff = sp.timestamp(5), 
                 end = sp.timestamp(10), 
                 vesting_amount = 200,
                 token_address = fa12.address,
                 token_id = sp.none,
                 metadata = sp.none
             )
         ])
     )
     
     scenario += v.changeBeneficiery(
         sp.list([
             sp.record(
                 schedule_name = "8 Months Cliff Vesting From 12-12-2020",
                 from_ = bob.address, 
                 to_ = alice.address
             )
         ])
     ).run(sender = alice, valid = False)
     
     scenario += v.changeBeneficiery(
         sp.list([
             sp.record(
                 schedule_name = "8 Months Cliff Vesting From 12-12-2020",
                 from_ = bob.address, 
                 to_ = alice.address
             )
         ])
     ).run(sender = admin)
     
     scenario += v.changeBeneficieryForAll(
         sp.list([
             sp.record(
                 from_ = alice.address, 
                 to_ = bob.address
             )
         ])
     ).run(sender = alice, valid = False)
     
     scenario += v.changeBeneficieryForAll(
         sp.list([
             sp.record(
                 from_ = alice.address, 
                 to_ = bob.address
             )
         ])
     ).run(sender = admin)