def test(): c1 = Bls12_381( g1=sp.bls12_381_g1( "0x8ce3b57b791798433fd323753489cac9bca43b98deaafaed91f4cb010730ae1e38b186ccd37a09b8aed62ce23b699c48" ), g2=sp.bls12_381_g2( "0x8647aa9680cd0cdf065b94e818ff2bb948cc97838bcee987b9bc1b76d0a0a6e0d85db4e9d75aaedfc79d4ea2733a21ae0579014de7636dd2943d45b87c82b1c66a289006b0b9767921bb8edd3f6c5c5dec0d54cd65f61513113c50cc977849e5" ), fr=sp.bls12_381_fr( "0x60c8333ef28e1b3b7fc487952b1e21372bd43056e8cb993625735b645e8030b7" ), mulResult=sp.none, checkResult=sp.none) scenario = sp.test_scenario() scenario += c1 scenario += c1.add( g1=sp.bls12_381_g1( "0x8ce3b57b791798433fd323753489cac9bca43b98deaafaed91f4cb010730ae1e38b186ccd37a09b8aed62ce23b699c48" ), g2=sp.bls12_381_g2( "0x8647aa9680cd0cdf065b94e818ff2bb948cc97838bcee987b9bc1b76d0a0a6e0d85db4e9d75aaedfc79d4ea2733a21ae0579014de7636dd2943d45b87c82b1c66a289006b0b9767921bb8edd3f6c5c5dec0d54cd65f61513113c50cc977849e5" ), fr=sp.bls12_381_fr( "0x60c8333ef28e1b3b7fc487952b1e21372bd43056e8cb993625735b645e8030b7" )) scenario += c1.negate() scenario += c1.toInt() scenario += c1.mul( sp.pair( sp.bls12_381_fr( "0x8ce3b57b791798433fd323753489cac9bca43b98deaafaed91f4cb010730ae1e38b186ccd37a09b8aed62ce23b699c48" ), sp.bls12_381_fr( "0x8ce3b57b791798433fd323753489cac9bca43b98deaafaed91f4cb010730ae1e38b186ccd37a09b8aed62ce23b699c" ))) scenario += c1.pairing_check( sp.list([ sp.pair( sp.bls12_381_g1( "0x8ce3b57b791798433fd323753489cac9bca43b98deaafaed91f4cb010730ae1e38b186ccd37a09b8aed62ce23b699c48" ), sp.bls12_381_g2( "0x8647aa9680cd0cdf065b94e818ff2bb948cc97838bcee987b9bc1b76d0a0a6e0d85db4e9d75aaedfc79d4ea2733a21ae0579014de7636dd2943d45b87c82b1c66a289006b0b9767921bb8edd3f6c5c5dec0d54cd65f61513113c50cc977849e5" )), sp.pair( sp.bls12_381_g1( "0x8ce3b57b791798433fd323753489cac9bca43b98deaafaed91f4cb010730ae1e38b186ccd37a09b8aed62ce23b699c48" ), sp.bls12_381_g2( "0x8647aa9680cd0cdf065b94e818ff2bb948cc97838bcee987b9bc1b76d0a0a6e0d85db4e9d75aaedfc79d4ea2733a21ae0579014de7636dd2943d45b87c82b1c66a289006b0b9767921bb8edd3f6c5c5dec0d54cd65f61513113c50cc977849e5" )) ]))
def delete_permits(self, permit_keys): sp.set_type(permit_keys, sp.TList(sp.TPair(sp.TAddress, sp.TBytes))) effective_expiry = sp.local("effective_expiry", 0) sp.for permit_key in permit_keys: permit_exists = self.data.permits.contains(permit_key) sp.verify(permit_exists, sp.pair( "NO_PERMIT_TO_DELETE", permit_key)) effective_expiry = self.getEffectiveExpiry(permit_key) permit_submission_timestamp = self.data.permits[permit_key] sp.verify(sp.as_nat(sp.now - permit_submission_timestamp) >= effective_expiry, sp.pair("PERMIT_NOT_EXPIRED", permit_key)) self.delete_permit(permit_key)
def permit(self, params): sp.set_type( params, sp.TList(sp.TPair(sp.TKey, sp.TPair(sp.TSignature, sp.TBytes)))) sp.verify(~self.data.paused) with sp.for_('permit', params) as permit: params_hash = sp.snd(sp.snd(permit)) unsigned = sp.pack( sp.pair(sp.pair(sp.chain_id, sp.self_address), sp.pair(self.data.counter, params_hash))) pk_address = sp.to_address( sp.implicit_account(sp.hash_key(sp.fst(permit)))) permit_key = sp.pair(pk_address, params_hash) permit_exists = self.data.permits.contains(permit_key) effective_expiry = self.getEffectiveExpiry( sp.pair(pk_address, params_hash)) permit_submission_timestamp = self.data.permits[permit_key] sp.verify( ~(permit_exists & (sp.as_nat(sp.now - permit_submission_timestamp) < effective_expiry)), sp.pair("DUP_PERMIT", params_hash)) sp.verify( sp.check_signature(sp.fst(permit), sp.fst(sp.snd(permit)), unsigned), sp.pair("MISSIGNED", unsigned)) self.data.permits[sp.pair(pk_address, params_hash)] = sp.now self.data.counter = self.data.counter + 1
def transfer_presigned(self, params): sp.set_type( params, sp.TRecord(from_=sp.TAddress, to_=sp.TAddress, value=sp.TNat)) params_hash = sp.blake2b(sp.pack(params)) #unsigned = sp.blake2b(mi.operator("SELF; ADDRESS; CHAIN_ID; PAIR; PAIR; PACK", [sp.TPair(sp.TNat, sp.TBytes)], [sp.TBytes])(sp.pair(self.data.counter, params_hash))) permit_key = sp.pair(params.from_, params_hash) effective_expiry = sp.local("effective_expiry", 0) with sp.if_(self.data.permits.contains(permit_key)): permit_submission_timestamp = self.data.permits[permit_key] with sp.if_( self.data.permit_expiries.contains(permit_key) & self.data.permit_expiries[permit_key].is_some()): effective_expiry.value = self.data.permit_expiries[ permit_key].open_some() with sp.else_(): with sp.if_( self.data.user_expiries.contains(params.from_) & self.data.user_expiries[params.from_].is_some()): effective_expiry.value = self.data.user_expiries[ params.from_].open_some() with sp.else_(): effective_expiry.value = self.data.default_expiry # Deleting permit regardless of whether or not its expired with sp.if_( sp.as_nat(sp.now - permit_submission_timestamp) >= effective_expiry.value): # Expired self.delete_permit(permit_key) sp.result(sp.bool(False)) with sp.else_(): self.delete_permit(permit_key) sp.result(sp.bool(True)) with sp.else_(): sp.result(sp.bool(False))
def checkRedeem(self, address): sp.set_type(address, sp.TAddress) contract = sp.contract(sp.TPair(sp.TAddress, sp.TContract( sp.TBool)), self.data.contract, entry_point="hasRedeemed").open_some() payload = sp.pair(address, sp.contract( sp.TBool, sp.self_address, entry_point="callback").open_some()) sp.transfer(payload, sp.mutez(0), contract)
def fetchPriceFromHarbinger(self,harbingerContractAddress , asset , targetAddress): contractParams = sp.contract(sp.TPair(sp.TString , sp.TContract(sp.TPair(sp.TString , sp.TPair(sp.TTimestamp , sp.TNat)))) , harbingerContractAddress , entry_point="get").open_some() callBack = sp.contract(sp.TPair(sp.TString , sp.TPair(sp.TTimestamp , sp.TNat)) , targetAddress , entry_point="getResponseFromHarbinger").open_some() dataToBeSent = sp.pair(asset , callBack) sp.transfer(dataToBeSent , sp.mutez(0) , contractParams)
def setExpiry(self, params): sp.set_type(params, sp.TRecord(address=sp.TAddress, seconds=sp.TNat, permit=sp.TOption( sp.TBytes))).layout(("address", ("seconds", "permit"))) sp.verify(~self.data.paused) sp.verify(params.seconds <= self.data.max_expiry, "MAX_SECONDS_EXCEEDED") sp.verify_equal(params.address, sp.sender, message="NOT_AUTHORIZED") sp.if params.permit.is_some(): some_permit = params.permit.open_some() sp.verify(self.data.permits.contains( sp.pair(params.address, some_permit)), "PERMIT_NONEXISTENT") permit_submission_timestamp = self.data.permits[sp.pair( params.address, some_permit)] sp.if self.data.permit_expiries.contains(sp.pair(params.address, some_permit)) & self.data.permit_expiries[sp.pair(params.address, some_permit)].is_some(): permit_expiry = self.data.permit_expiries[sp.pair( params.address, some_permit)].open_some() sp.verify(sp.as_nat(sp.now - permit_submission_timestamp) < permit_expiry, "PERMIT_REVOKED")
def make(user, token): sp.set_type(user, sp.TAddress) sp.set_type(token, token_id_type) result = sp.pair(user, token) if readable: return result else: return sp.pack(result)
def custClose(self, params): sp.verify(self.data.custAddr == sp.sender) sp.verify((self.data.status == OPEN) | (self.data.status == MERCH_CLOSE)) # custClose inputs custBal = params.custBal merchBal = params.merchBal revLock = params.revLock s1 = params.s1 s2 = params.s2 # Prepare pairing check inputs g2 = self.data.g2 merchPk0 = self.data.merchPk0 merchPk1 = self.data.merchPk1 merchPk2 = self.data.merchPk2 merchPk3 = self.data.merchPk3 merchPk4 = self.data.merchPk4 chanID = self.data.chanID cust_b = sp.local('cust_b', sp.fst(sp.ediv(custBal, sp.mutez(1)).open_some())) one = sp.local('one', sp.bls12_381_fr("0x01")) cust_bal_b = sp.local("cust_bal_b", sp.mul(cust_b.value, one.value)) merch_b = sp.local('merch_b', sp.fst(sp.ediv(merchBal, sp.mutez(1)).open_some())) merch_bal_b = sp.local("merch_bal_b", sp.mul(merch_b.value, one.value)) revLockConcat = sp.local('revLockConcat', sp.concat([sp.bytes("0x050a00000020"), revLock])) rev_lock_b = sp.local('rev_lock_b', sp.unpack(revLockConcat.value, t = sp.TBls12_381_fr).open_some()) # Verify signature val1 = sp.local("val1", sp.mul(merchPk0, chanID)) val2 = sp.local("val2", sp.mul(merchPk1, rev_lock_b.value)) val3 = sp.local("val3", sp.mul(merchPk2, cust_bal_b.value)) val4 = sp.local("val4", sp.mul(merchPk3, merch_bal_b.value)) prod1 = sp.local("prod1", val1.value + val2.value + val3.value + val4.value + merchPk4) g2_negated = - g2 pair_list = sp.local("pair_list", [sp.pair(s1, prod1.value), sp.pair(s2, g2_negated)]) out = sp.local('out', False) sp.verify(sp.pairing_check(pair_list.value)) # Update on-chain state and transfer merchant's balance self.data.custBal = custBal self.data.revLock = revLock self.data.delayExpiry = sp.now.add_seconds(self.data.selfDelay) sp.send(self.data.merchAddr, merchBal) self.data.merchBal = sp.tez(0) self.data.status = CUST_CLOSE
def createNft(self, metadata): sp.set_type(metadata, METADATA_TYPE) sp.verify(sp.sender == self.data.admin) my_ticket = sp.ticket(self.data.current_id, 1) current_id = self.data.current_id new_map = sp.update_map(self.data.tickets, current_id, sp.some(my_ticket)) self.data.tickets = new_map self.data.token_metadata[current_id] = sp.pair(current_id, metadata) self.data.current_id = current_id + 1
def set_token_metadata(self, metadata): """ Store the token_metadata values in a big-map annotated %token_metadata of type (big_map nat (pair (nat %token_id) (map %token_info string bytes))). """ self.update_initial_storage( token_metadata = sp.big_map({ 0: sp.pair(0, self.normalize_metadata(metadata)) }) )
def test(): scenario = sp.test_scenario() scenario.h1("Update Fails With Bad Signature") scenario.h2("GIVEN an Oracle contract") assetCode = "XTZ-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract scenario.h2("AND an update signed by an alternative key") alternativeAccount = sp.test_account("AlternativeAccount") alternativeSecretKey = alternativeAccount.secret_key start = sp.timestamp(1) end = sp.timestamp(2) open = 3 high = 4 low = 5 close = 6 volume = 7 updateData = ( start, (end, (open, (high, (low, (close, volume)))))) message = sp.pack(updateData) signature = sp.make_signature( alternativeSecretKey, message, message_format='Raw' ) scenario.h2("WHEN the oracle is updated") update = sp.pair(signature, updateData) parameter = sp.map( l={ assetCode: update }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario.h2("THEN the update fails") scenario += contract.update(parameter).run(valid=False)
def transfer_presigned(self, params): sp.set_type(params, sp.TRecord( from_=sp.TAddress, to_=sp.TAddress, value=sp.TNat)) params_hash = sp.blake2b(sp.pack(params)) #unsigned = sp.blake2b(mi.operator("SELF; ADDRESS; CHAIN_ID; PAIR; PAIR; PACK", [sp.TPair(sp.TNat, sp.TBytes)], [sp.TBytes])(sp.pair(self.data.counter, params_hash))) permit_key = sp.pair(params.from_, params_hash) effective_expiry = sp.local("effective_expiry", 0) sp.if self.data.permits.contains(permit_key): permit_submission_timestamp = self.data.permits[permit_key] sp.if self.data.permit_expiries.contains(permit_key) & self.data.permit_expiries[permit_key].is_some(): effective_expiry.value = self.data.permit_expiries[permit_key].open_some()
def make(self, user, token): user = sp.set_type_expr(user, sp.TAddress) token = sp.set_type_expr(token, token_id_type) if self.config.single_asset: result = user else: result = sp.pair(user, token) if self.config.readable: return result else: return sp.pack(result)
def ps_sig_verify(self, params): sp.set_type(params.wallet.m0, Fr) sp.set_type(params.wallet.m1, Fr) sp.set_type(params.wallet.m2, Fr) sp.set_type(params.wallet.m3, Fr) sp.set_type(params.wallet.m4, Fr) sp.set_type(params.signature.s1, G1) sp.set_type(params.signature.s2, G2) # (Y0 * m0) + (Y1 * m1) + (Y2 * m2) + (Y3 * m3) + (Y4 * m4) + X prod1 = (self.data.pubkey.Y0 * params.wallet.m0) + (self.data.pubkey.Y1 * params.wallet.m1) + \ (self.data.pubkey.Y2 * params.wallet.m2) + (self.data.pubkey.Y3 * params.wallet.m3) + \ (self.data.pubkey.Y4 * params.wallet.m4) + self.data.pubkey.X # [ (s1, prod1_x); # (s2, g2 ^ -1) ] pairing_check_inputs = [ sp.pair(params.signature.s1, prod1), sp.pair(params.signature.s2, -self.data.pubkey.g2) ] # execute the pairing check and return the result self.data.close_sig = self.pairing_check(pairing_check_inputs)
def transfer_presigned(self, params): sp.set_type(params, sp.TRecord( from_=sp.TAddress, to_=sp.TAddress, value=sp.TNat)) params_hash = sp.blake2b(sp.pack(params)) permit_key = sp.pair(params.from_, params_hash) sp.if self.data.permit_data.permits.contains(permit_key): permit_submission_timestamp = self.data.permit_data.permits[permit_key] effective_expiry = self.getEffectiveExpiry(permit_key) # Deleting permit regardless of whether or not its expired sp.if sp.as_nat(sp.now - permit_submission_timestamp) >= effective_expiry: # Expired self.delete_permit(permit_key) sp.result(sp.bool(False))
def createMarket(self, params): sp.set_type(params, sp.TRecord(end=sp.TInt, ipfsString=sp.TString)) contractAddress = sp.create_contract(storage=sp.record( admin=sp.pair(self.data.admin, sp.sender), infoIPFS=params.ipfsString, uuid=0, endTime=sp.timestamp(0).add_seconds(params.end), result=sp.none, orders={}, buyLongOrders={}, buyShortOrders={}, sellLongOrders={}, sellShortOrders={}, sharesLong={}, sharesShort={}), contract=self.market) self.data.markets[contractAddress] = sp.sender
def setExpiry(self, params): sp.set_type(params, sp.TPair(sp.TAddress, sp.TPair(sp.TNat, sp.TOption( sp.TBytes)))) address = sp.fst(params) new_expiry = sp.fst(sp.snd(params)) possible_bytes = sp.snd(sp.snd(params)) sp.verify(new_expiry <= self.data.permit_data.max_expiry, self.error_message.expiry_exceeds_max()) sp.verify_equal(address, sp.sender, message=self.error_message.user_unauthorized()) sp.if possible_bytes.is_some(): some_permit = possible_bytes.open_some() permit_key = sp.pair(address, some_permit) sp.verify(self.data.permit_data.permits.contains( permit_key), self.error_message.permit_nonexistent()) permit_submission_timestamp = self.data.permit_data.permits[permit_key] effective_expiry = self.getEffectiveExpiry(permit_key) sp.verify(sp.as_nat(sp.now - permit_submission_timestamp) < effective_expiry, self.error_message.permit_revoked()) self.data.permit_data.permit_expiries[permit_key] = sp.some(new_expiry)
def test(): scenario = sp.test_scenario() #Test accounts admin1 = sp.test_account('Admin-1') admin2 = sp.test_account('Admin-2') alice = sp.test_account("Alice") bob = sp.test_account("Bob") mike = sp.test_account("Mike") john = sp.test_account("John") c = Market() c.set_storage(sp.record( admin = sp.pair(admin1.address, admin2.address), infoIPFS = "IPFSxyz", uuid = 0, endTime = sp.timestamp(1000000), result = sp.none, orders = {}, buyLongOrders = {}, buyShortOrders = {}, sellLongOrders = {}, sellShortOrders = {}, sharesLong = {}, sharesShort = {} )) scenario += c scenario.register(c.buyLong(quantity = 10, price = 700000).run(sender = alice, amount = sp.mutez(700000))) scenario.register(c.buyShort(quantity = 10, price = 300000).run(sender = bob, amount = sp.mutez(300000))) scenario.register(c.buyShort(quantity = 10, price = 400000).run(sender = mike, amount = sp.mutez(400000))) scenario.register(c.buyLong(quantity = 10, price = 600000).run(sender = john, amount = sp.mutez(600000))) scenario.h2('Admin sets the result') scenario += c.setResult(result = Position.Long).run(sender = admin1, now = sp.timestamp(1000005)) scenario.h2('Failed Withdrawal') scenario += c.withdrawPayout().run(sender = bob, valid = False) scenario.h2('Successful withdrawals') scenario += c.withdrawPayout().run(sender = alice) scenario += c.withdrawPayout().run(sender = john) scenario.verify(c.balance == sp.mutez(0))
def test(): scenario = sp.test_scenario() #Test accounts admin1 = sp.test_account('Admin-1') admin2 = sp.test_account('Admin-2') alice = sp.test_account("Alice") bob = sp.test_account("Bob") mike = sp.test_account("Mike") john = sp.test_account("John") c = Market() c.set_storage(sp.record( admin = sp.pair(admin1.address, admin2.address), infoIPFS = "IPFSxyz", uuid = 0, endTime = sp.timestamp(1000000), result = sp.none, orders = {}, buyLongOrders = {}, buyShortOrders = {}, sellLongOrders = {}, sellShortOrders = {}, sharesLong = {}, sharesShort = {} )) scenario += c scenario.register(c.buyLong(quantity = 10, price = 700000).run(sender = alice, amount = sp.mutez(700000))) scenario.register(c.buyShort(quantity = 10, price = 300000).run(sender = bob, amount = sp.mutez(300000))) scenario.register(c.buyShort(quantity = 10, price = 400000).run(sender = mike, amount = sp.mutez(400000))) scenario.register(c.buyLong(quantity = 10, price = 600000).run(sender = john, amount = sp.mutez(600000))) scenario.h2('Sell Long') scenario += c.sellLong(quantity = 10, price_buy = 700000, price_sell = 700000).run(sender = alice) scenario.h2('Sell Short') scenario += c.sellShort(quantity = 10, price_buy = 400000, price_sell = 300000).run(sender = mike) scenario += c.sellShort(quantity = 10, price_buy = 300000, price_sell = 500000).run(sender = bob) scenario.h2('Withdraw') scenario += c.withdrawSellOrder(id = 4).run(sender = bob)
def placeBet(self,params): self.checkBettingPaused() self.bettorNotAContract() sp.verify(sp.amount > sp.mutez(0) , message = "Amount should not be 0") currentCycle = sp.local("currentCycle" ,sp.int(0)) currentCycle = sp.fst(sp.ediv(sp.level,self.data.blocksPerCycle).open_some()) self.initializeInternalMapForNewBettor() self.betAlreadyPlacedForParticularCycle(currentCycle+self.data.stakingPeriod) self.betBelowBetLimit() self.isRangeValid(currentCycle+self.data.stakingPeriod , params.top , params.bottom) self.isCycleInitiated(currentCycle+self.data.stakingPeriod) betsByCycle = self.data.bettors[sp.sender] betsByCycle[currentCycle+self.data.stakingPeriod] = sp.record(amount = sp.amount , range = sp.pair(params.top , params.bottom) , withdrawn = sp.bool(False) , withdrawnAmount = sp.mutez(0) , stakedAt = currentCycle) self.data.cycleData[currentCycle+self.data.stakingPeriod].amountByRange[sp.pair(params.top , params.bottom)] += sp.amount self.data.cycleData[currentCycle+self.data.stakingPeriod].totalAmount += sp.amount
def getResponseFromHarbinger(self,response): sp.verify(self.data.admin.contains(sp.source) , "Un-authorized") sp.set_type(response , sp.TPair(sp.TString , sp.TPair(sp.TTimestamp , sp.TNat))) currentPrice=sp.local("currentPrice",sp.int(0)) currentPrice = sp.to_int(sp.fst(sp.ediv(sp.snd(sp.snd(response)) , sp.nat(1000)).open_some())) currentCycle = sp.local("currentCycle" ,sp.int(0)) currentCycle = sp.fst(sp.ediv(sp.level,self.data.blocksPerCycle).open_some()) sp.verify(~self.data.cycleData.contains(currentCycle+self.data.stakingPeriod)) rangeMap = sp.local("rangeMap" , sp.map(tkey = sp.TPair(sp.TInt, sp.TInt) , tvalue = sp.TMutez)) iterator = sp.local("iterator" , sp.int(0)) sp.while iterator.value<=self.data.rangeEnd: sp.if iterator.value+self.data.rangeStep<=self.data.rangeEnd: rangeMap.value[sp.pair(iterator.value,iterator.value+self.data.rangeStep)] =sp.mutez(0) rangeMap.value[(sp.int(-1)*(iterator.value+self.data.rangeStep),sp.int(-1)*iterator.value)] =sp.mutez(0)
def permit(self, params): sp.set_type(params, sp.TList( sp.TPair(sp.TKey, sp.TPair(sp.TSignature, sp.TBytes)))) sp.for permit in params: public_key = sp.fst(permit) signature = sp.fst(sp.snd(permit)) params_hash = sp.snd(sp.snd(permit)) #unsigned = sp.blake2b(mi.operator("SELF; ADDRESS; CHAIN_ID; PAIR; PAIR; PACK", [sp.TPair(sp.TNat, sp.TBytes)], [sp.TBytes])(sp.pair(self.data.permit_data.counter, params_hash))) unsigned = sp.pack(sp.pair(sp.pair(sp.chain_id, sp.self_address), sp.pair( self.data.permit_data.counter, params_hash))) pk_address = sp.to_address( sp.implicit_account(sp.hash_key(public_key))) permit_key = sp.pair(pk_address, params_hash) permit_exists = self.data.permit_data.permits.contains(permit_key) permit_submission_timestamp = self.data.permit_data.permits[permit_key] effective_expiry = self.getEffectiveExpiry(permit_key) sp.verify(~ (permit_exists & (sp.as_nat(sp.now - permit_submission_timestamp) < effective_expiry)), sp.pair(self.error_message.duplicate_permit(), params_hash)) sp.verify(sp.check_signature(public_key, signature, unsigned), sp.pair(self.error_message.permit_missigned(), unsigned)) self.data.permit_data.permits[permit_key] = sp.now self.data.permit_data.counter = self.data.permit_data.counter + 1
def test(): scenario = sp.test_scenario() scenario.h1("FA1.2 template - Fungible assets") scenario.table_of_contents() # sp.test_account generates ED25519 key-pairs deterministically: admin = sp.test_account("Administrator") alice = sp.test_account("Alice") bob = sp.test_account("Robert") carlos = sp.test_account("Carlos") # Let's display the accounts: scenario.h1("Accounts") scenario.show([admin, alice, bob, carlos]) scenario.h1("Contract") c1 = FA12(admin.address) scenario.h1("Entry points") scenario += c1 scenario.h2("Admin mints a few coins") scenario += c1.mint(address=alice.address, value=12).run(sender=admin) scenario += c1.mint(address=alice.address, value=3).run(sender=admin) scenario += c1.mint(address=alice.address, value=3).run(sender=admin) scenario.verify(c1.data.balances[alice.address].balance == 18) scenario.h2("Alice transfers to Bob") scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(sender=alice) scenario.verify(c1.data.balances[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=bob.address, value=5).run(sender=alice) scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(sender=bob) 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(address=bob.address, value=1).run(sender=admin) scenario.verify(c1.data.balances[alice.address].balance == 10) scenario.h2("Alice tries to burn Bob token") scenario += c1.burn(address=bob.address, value=1).run(sender=alice, valid=False) scenario.h2( "Admin pauses the contract and Alice cannot transfer anymore") scenario += c1.setPause(True).run(sender=admin) scenario += c1.transfer(from_=alice.address, to_=bob.address, value=4).run(sender=alice, valid=False) scenario.verify(c1.data.balances[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 transfers are allowed") scenario += c1.setPause(False).run(sender=admin) scenario.verify(c1.data.balances[alice.address].balance == 9) scenario += c1.transfer(from_=alice.address, to_=bob.address, value=1).run(sender=alice) scenario.verify(c1.data.totalSupply == 17) scenario.verify(c1.data.balances[alice.address].balance == 8) scenario.verify(c1.data.balances[bob.address].balance == 9) scenario.h2("Permit Submissions") scenario += c1.mint(address=carlos.address, value=10).run(sender=admin) scenario.verify(c1.data.balances[carlos.address].balance == 10) # add permit for transfer of 10 from carlos to bob. alice submits with correct info and also calls. params_bytes_1 = sp.pack( sp.pair(carlos.address, sp.pair(bob.address, 10))) params_bytes_2 = sp.pack( sp.pair(bob.address, sp.pair(carlos.address, 10))) params_hash_1 = sp.blake2b(params_bytes_1) params_hash_2 = sp.blake2b(params_bytes_2) unsigned_1 = sp.pack( sp.pair(sp.pair(sp.chain_id_cst("0x9caecab9"), c1.address), sp.pair(0, params_hash_1))) signature_1 = sp.make_signature(secret_key=carlos.secret_key, message=unsigned_1, message_format="Raw") unsigned_2 = sp.pack( sp.pair(sp.pair(sp.chain_id_cst("0x9caecab9"), c1.address), sp.pair(1, params_hash_2))) signature_2 = sp.make_signature(secret_key=bob.secret_key, message=unsigned_2, message_format="Raw") scenario += c1.permit([ sp.pair(carlos.public_key, sp.pair(signature_1, params_hash_1)), sp.pair(bob.public_key, sp.pair(signature_2, params_hash_2)) ]).run(sender=alice, now=sp.timestamp(1571761674), chain_id=sp.chain_id_cst("0x9caecab9")) scenario.verify(c1.data.counter == 2) scenario.verify_equal( c1.data.permits[(sp.pair(carlos.address, params_hash_1))], sp.timestamp(1571761674)) scenario.verify_equal( c1.data.permits[(sp.pair(bob.address, params_hash_2))], sp.timestamp(1571761674)) scenario.h2("Execute transfer using permit") scenario += c1.transfer(from_=carlos.address, to_=bob.address, value=10).run(sender=bob, now=sp.timestamp(1571761674)) scenario.verify(c1.data.balances[carlos.address].balance == 0) scenario.verify(c1.data.balances[bob.address].balance == 19) # Permit deleted scenario.verify( ~c1.data.permits.contains(sp.pair(carlos.address, params_hash_1))) scenario += c1.transfer(from_=bob.address, to_=carlos.address, value=10).run(sender=carlos, now=sp.timestamp(1571761674)) scenario.verify(c1.data.balances[carlos.address].balance == 10) scenario.verify(c1.data.balances[bob.address].balance == 9) # Permit deleted scenario.verify( ~c1.data.permits.contains(sp.pair(bob.address, params_hash_2))) # Set Expiry to 0 and try to execute transfer at time less than submission_time + default_expiry, expect invalid transfer scenario.h2("Expired Permit") unsigned_3 = sp.pack( sp.pair(sp.pair(sp.chain_id_cst("0x9caecab9"), c1.address), sp.pair(2, params_hash_1))) signature_3 = sp.make_signature(secret_key=carlos.secret_key, message=unsigned_3, message_format="Raw") scenario += c1.permit([ sp.pair(carlos.public_key, sp.pair(signature_3, params_hash_1)) ]).run(sender=alice, now=sp.timestamp(1571761674), chain_id=sp.chain_id_cst("0x9caecab9")) scenario.verify(c1.data.counter == 3) scenario.verify_equal( c1.data.permits[(sp.pair(carlos.address, params_hash_1))], sp.timestamp(1571761674)) scenario += c1.setExpiry(address=carlos.address, seconds=0, permit=sp.some(params_hash_1)).run( sender=carlos, now=sp.timestamp(1571761674)) scenario.verify(c1.data.permit_expiries[sp.pair( carlos.address, params_hash_1)].open_some() == 0) scenario += c1.transfer(from_=carlos.address, to_=bob.address, value=10).run( sender=bob, now=sp.timestamp(1571761680), valid=False) # Uses later time stamp scenario.h2("Delete Expired Permit") scenario += c1.delete_permits([sp.pair(carlos.address, params_hash_1) ]).run(now=sp.timestamp(1571761680)) scenario.verify(~c1.data.permit_expiries.contains( sp.pair(carlos.address, params_hash_1))) scenario.verify( ~c1.data.permits.contains(sp.pair(carlos.address, params_hash_1))) scenario.h1("Views") scenario.h2("Balance") view_balance = Viewer(sp.TNat) scenario += view_balance scenario += c1.getBalance(arg=sp.record(owner=alice.address), target=view_balance.address) scenario.verify_equal(view_balance.data.last, sp.some(8)) scenario.h2("Administrator") view_administrator = Viewer(sp.TAddress) scenario += view_administrator scenario += c1.getAdministrator(target=view_administrator.address) scenario.verify_equal(view_administrator.data.last, sp.some(admin.address)) scenario.h2("Total Supply") view_totalSupply = Viewer(sp.TNat) scenario += view_totalSupply scenario += c1.getTotalSupply(target=view_totalSupply.address) scenario.verify_equal(view_totalSupply.data.last, sp.some(27)) scenario.h2("Allowance") view_allowance = Viewer(sp.TNat) scenario += view_allowance scenario += c1.getAllowance(arg=sp.record(owner=alice.address, spender=bob.address), target=view_allowance.address) scenario.verify_equal(view_allowance.data.last, sp.some(1)) scenario.h2("Counter") view_counter = Viewer(sp.TNat) scenario += view_counter scenario += c1.getCounter(target=view_counter.address) scenario.verify_equal(view_counter.data.last, sp.some(3)) scenario.h2("Default Expiry") view_defaultExpiry = Viewer(sp.TNat) scenario += view_defaultExpiry scenario += c1.getDefaultExpiry(target=view_defaultExpiry.address) scenario.verify_equal(view_defaultExpiry.data.last, sp.some(50000))
def test(): scenario = sp.test_scenario() scenario.h1("Update with stale asset does not fail") scenario.h2("GIVEN an Oracle contract tracking two assets with an initial update") assetCode1 = "XTZ-USD" assetCode2 = "BTC-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode1: initialOracleData, assetCode2: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract start1 = sp.timestamp(1) end1 = sp.timestamp(2) open1 = 3 high1 = 4 low1 = 5 close1 = 6 volume1 = 7 updateData1 = ( start1, (end1, (open1, (high1, (low1, (close1, volume1)))))) asset1Message1 = sp.pack((assetCode1, updateData1)) asset1Signature1 = sp.make_signature( testAccountSecretKey, asset1Message1, message_format='Raw' ) asset2Message1 = sp.pack((assetCode2, updateData1)) asset2Signature1 = sp.make_signature( testAccountSecretKey, asset2Message1, message_format='Raw' ) asset1Update1 = sp.pair(asset1Signature1, updateData1) asset2Update1 = sp.pair(asset2Signature1, updateData1) parameter = sp.map( l={ assetCode1: asset1Update1, assetCode2: asset2Update1, }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter) scenario.h2("WHEN an update is posted to the oracle with only one asset containing new data") start2 = sp.timestamp(2) end2 = sp.timestamp(3) open2 = 8 high2 = 9 low2 = 10 close2 = 11 volume2 = 12 updateData2 = ( start2, (end2, (open2, (high2, (low2, (close2, volume2)))))) asset1Message2 = sp.pack((assetCode1, updateData2)) asset1Signature2 = sp.make_signature( testAccountSecretKey, asset1Message2, message_format='Raw' ) asset1Update2 = sp.pair(asset1Signature2, updateData2) parameter = sp.map( l={ assetCode1: asset1Update2, assetCode2: asset2Update1, }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter) scenario.h2("THEN data for the asset with two updates is the second update.") assetData1 = contract.data.oracleData[assetCode1] endPair1 = sp.snd(assetData1) openPair1 = sp.snd(endPair1) highPair1 = sp.snd(openPair1) lowPair1 = sp.snd(highPair1) closeAndVolumePair1 = sp.snd(lowPair1) oracleStart1 = sp.fst(assetData1) oracleEnd1 = sp.fst(endPair1) oracleOpen1 = sp.fst(openPair1) oracleHigh1 = sp.fst(highPair1) oracleLow1 = sp.fst(lowPair1) oracleClose1 = sp.fst(closeAndVolumePair1) oracleVolume1 = sp.snd(closeAndVolumePair1) scenario.verify(oracleStart1 == start2) scenario.verify(oracleEnd1 == end2) scenario.verify(oracleOpen1 == open2) scenario.verify(oracleHigh1 == high2) scenario.verify(oracleLow1 == low2) scenario.verify(oracleClose1 == close2) scenario.verify(oracleVolume1 == volume2) scenario.h2("THEN data for the asset with two updates is the second update.") assetData2 = contract.data.oracleData[assetCode2] endPair2 = sp.snd(assetData2) openPair2 = sp.snd(endPair2) highPair2 = sp.snd(openPair2) lowPair2 = sp.snd(highPair2) closeAndVolumePair2 = sp.snd(lowPair2) oracleStart2 = sp.fst(assetData2) oracleEnd2 = sp.fst(endPair2) oracleOpen2 = sp.fst(openPair2) oracleHigh2 = sp.fst(highPair2) oracleLow2 = sp.fst(lowPair2) oracleClose2 = sp.fst(closeAndVolumePair2) oracleVolume2 = sp.snd(closeAndVolumePair2) scenario.verify(oracleStart2 == start1) scenario.verify(oracleEnd2 == end1) scenario.verify(oracleOpen2 == open1) scenario.verify(oracleHigh2 == high1) scenario.verify(oracleLow2 == low1) scenario.verify(oracleClose2 == close1) scenario.verify(oracleVolume2 == volume1)
def test(): scenario = sp.test_scenario() scenario.h1("Incorrect Revoke Fails to Revoke An Oracle") scenario.h2( "GIVEN an oracle contract and a revoke message signed by another account.") testAccount = sp.test_account("Incorrect_Account") message = sp.pack(sp.none) signature = sp.make_signature( testAccount.secret_key, message, message_format='Raw' ) assetCode = "XTZ-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract scenario.h2("WHEN revoke is called") scenario.h2("THEN the call fails") scenario += contract.revoke(signature).run(valid=False) scenario.h2("AND future updates succeed") start = sp.timestamp(1) end = sp.timestamp(2) open = 3 high = 4 low = 5 close = 6 volume = 7 updateData = ( start, (end, (open, (high, (low, (close, volume)))))) message = sp.pack((assetCode, updateData)) signature = sp.make_signature( testAccountSecretKey, message, message_format='Raw' ) update = sp.pair(signature, updateData) parameter = sp.map( l={ assetCode: update }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter)
def test(): scenario = sp.test_scenario() scenario.h1("Revokes An Oracle") scenario.h2( "GIVEN an oracle contract and a correctly signed revoke message.") message = sp.pack(sp.none) signature = sp.make_signature( testAccountSecretKey, message, message_format='Raw' ) assetCode = "XTZ-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract scenario.h2("WHEN revoke is called.") scenario += contract.revoke(signature) scenario.h2("THEN the oracle is revoked") scenario.verify(~contract.data.publicKey.is_some()) scenario.h2("AND the oracle's data no longer contains the original asset") scenario.verify(~contract.data.oracleData.contains(assetCode)) scenario.h2("AND future updates fail.") start = sp.timestamp(1) end = sp.timestamp(2) open = 3 high = 4 low = 5 close = 6 volume = 7 updateData = ( start, (end, (open, (high, (low, (close, volume)))))) message = sp.pack((assetCode, updateData)) signature = sp.make_signature( testAccountSecretKey, message, message_format='Raw' ) update = sp.pair(signature, updateData) parameter = sp.map( l={ assetCode: update }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter).run(valid=False)
def test(): scenario = sp.test_scenario() scenario.h1("Untracked Asset does not update oracle") scenario.h2("GIVEN an Oracle contract tracking an asset") assetCode = "XTZ-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract start1 = sp.timestamp(2) end1 = sp.timestamp(3) open1 = 3 high1 = 4 low1 = 5 close1 = 6 volume1 = 7 updateData1 = ( start1, (end1, (open1, (high1, (low1, (close1, volume1)))))) message1 = sp.pack((assetCode, updateData1)) signature1 = sp.make_signature( testAccountSecretKey, message1, message_format='Raw' ) update1 = sp.pair(signature1, updateData1) parameter1 = sp.map( l={ assetCode: update1 }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter1) scenario.h2("WHEN the oracle is updated with an untracked asset") untrackedAsset = "BTC-USD" start2 = sp.timestamp(4) end2 = sp.timestamp(5) open2 = 8 high2 = 9 low2 = 10 close2 = 11 volume2 = 12 updateData2 = ( start2, (end2, (open2, (high2, (low2, (close2, volume2)))))) message2 = sp.pack((untrackedAsset, updateData2)) signature2 = sp.make_signature( testAccountSecretKey, message2, message_format='Raw' ) update2 = sp.pair(signature2, updateData2) parameter2 = sp.map( l={ untrackedAsset: update2 }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter2) scenario.h2("THEN the oracle only contains the data for the tracked asset.") assetData = contract.data.oracleData[assetCode] endPair = sp.snd(assetData) openPair = sp.snd(endPair) highPair = sp.snd(openPair) lowPair = sp.snd(highPair) closeAndVolumePair = sp.snd(lowPair) oracleStart = sp.fst(assetData) oracleEnd = sp.fst(endPair) oracleOpen = sp.fst(openPair) oracleHigh = sp.fst(highPair) oracleLow = sp.fst(lowPair) oracleClose = sp.fst(closeAndVolumePair) oracleVolume = sp.snd(closeAndVolumePair) scenario.verify(oracleStart == start1) scenario.verify(oracleEnd == end1) scenario.verify(oracleOpen == open1) scenario.verify(oracleHigh == high1) scenario.verify(oracleLow == low1) scenario.verify(oracleClose == close1) scenario.verify(oracleVolume == volume1) scenario.h2("AND does not contain data for the untracked asset") scenario.verify(~contract.data.oracleData.contains(untrackedAsset))
def test(): scenario = sp.test_scenario() scenario.h1("Correctly Processes Updates With Data From The Past") scenario.h2("GIVEN an Oracle contract with some initial data.") assetCode = "XTZ-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract start1 = sp.timestamp(3) end1 = sp.timestamp(4) open1 = 3 high1 = 4 low1 = 5 close1 = 6 volume1 = 7 updateData1 = ( start1, (end1, (open1, (high1, (low1, (close1, volume1)))))) message1 = sp.pack((assetCode, updateData1)) signature1 = sp.make_signature( testAccountSecretKey, message1, message_format='Raw' ) update1 = sp.pair(signature1, updateData1) parameter1 = sp.map( l={ assetCode: update1 }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter1) scenario.h2("WHEN the oracle is updated with a time in the past") start2 = sp.timestamp(1) # In past end2 = sp.timestamp(2) open2 = 8 high2 = 9 low2 = 10 close2 = 11 volume2 = 12 updateData2 = ( start2, (end2, (open2, (high2, (low2, (close2, volume2)))))) message2 = sp.pack(updateData2) signature2 = sp.make_signature( testAccountSecretKey, message2, message_format='Raw' ) update2 = sp.pair(signature2, updateData2) parameter2 = sp.map( l={ assetCode: update2 }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter2) scenario.h2("THEN the update in the past does not modify the data.") assetData = contract.data.oracleData[assetCode] endPair = sp.snd(assetData) openPair = sp.snd(endPair) highPair = sp.snd(openPair) lowPair = sp.snd(highPair) closeAndVolumePair = sp.snd(lowPair) oracleStart = sp.fst(assetData) oracleEnd = sp.fst(endPair) oracleOpen = sp.fst(openPair) oracleHigh = sp.fst(highPair) oracleLow = sp.fst(lowPair) oracleClose = sp.fst(closeAndVolumePair) oracleVolume = sp.snd(closeAndVolumePair) scenario.verify(oracleStart == start1) scenario.verify(oracleEnd == end1) scenario.verify(oracleOpen == open1) scenario.verify(oracleHigh == high1) scenario.verify(oracleLow == low1) scenario.verify(oracleClose == close1) scenario.verify(oracleVolume == volume1)
def test(): scenario = sp.test_scenario() scenario.h1("Second Update Overwrites First Update") scenario.h2("GIVEN an Oracle contract") assetCode = "XTZ-USD" contract = OracleContract( publicKey=testAccountPublicKey, initialData=sp.big_map( l={ assetCode: initialOracleData }, tkey=sp.TString, tvalue=Harbinger.OracleDataType ) ) scenario += contract scenario.h2("AND two updates") start1 = sp.timestamp(1) end1 = sp.timestamp(2) open1 = 3 high1 = 4 low1 = 5 close1 = 6 volume1 = 7 updateData1 = ( start1, (end1, (open1, (high1, (low1, (close1, volume1)))))) message1 = sp.pack((assetCode, updateData1)) signature1 = sp.make_signature( testAccountSecretKey, message1, message_format='Raw' ) start2 = sp.timestamp(8) end2 = sp.timestamp(9) open2 = 10 high2 = 11 low2 = 12 close2 = 13 volume2 = 14 updateData2 = ( start2, (end2, (open2, (high2, (low2, (close2, volume2)))))) message2 = sp.pack((assetCode, updateData2)) signature2 = sp.make_signature( testAccountSecretKey, message2, message_format='Raw' ) scenario.h2("WHEN the oracle is updated") update1 = sp.pair(signature1, updateData1) update2 = sp.pair(signature2, updateData2) parameter1 = sp.map( l={ assetCode: update1 }, tkey=sp.TString, tvalue=SignedOracleDataType ) parameter2 = sp.map( l={ assetCode: update2 }, tkey=sp.TString, tvalue=SignedOracleDataType ) scenario += contract.update(parameter1) scenario += contract.update(parameter2) scenario.h2("THEN the oracle contains the data points of the latter update") assetData = contract.data.oracleData[assetCode] endPair = sp.snd(assetData) openPair = sp.snd(endPair) highPair = sp.snd(openPair) lowPair = sp.snd(highPair) closeAndVolumePair = sp.snd(lowPair) oracleStart = sp.fst(assetData) oracleEnd = sp.fst(endPair) oracleOpen = sp.fst(openPair) oracleHigh = sp.fst(highPair) oracleLow = sp.fst(lowPair) oracleClose = sp.fst(closeAndVolumePair) oracleVolume = sp.snd(closeAndVolumePair) scenario.verify(oracleStart == start2) scenario.verify(oracleEnd == end2) scenario.verify(oracleOpen == open2) scenario.verify(oracleHigh == high2) scenario.verify(oracleLow == low2) scenario.verify(oracleClose == close2) scenario.verify(oracleVolume == volume2)