예제 #1
0
    def update(self, params):
        # If there is no value for the public key, the oracle is revoked. Ignore updates.
        sp.verify(self.data.publicKey.is_some(), "revoked")

        # Iterate over assets in the input map.
        keyValueList = params.items()
        sp.for assetData in keyValueList:
            # Extract asset names, signatures, and the new data.
            assetName = assetData.key
            signature = sp.compute(sp.fst(assetData.value))
            newData = sp.compute(sp.snd(assetData.value))

            # Verify Oracle is tracking this asset.
            sp.if self.data.oracleData.contains(assetName):
                # Verify start timestamp is newer than the last update.
                oldData = sp.compute(self.data.oracleData[assetName])
                oldStartTime = sp.compute(sp.fst(oldData))
                newStartTime = sp.compute(sp.fst(newData))    
                sp.if newStartTime > oldStartTime:                
                    # Verify signature.
                    bytes = sp.pack((assetName, newData))
                    sp.verify(
                        sp.check_signature(
                            self.data.publicKey.open_some(), signature, bytes
                        ),
                        "bad sig"
                    )

                    # Replace the data.
                    self.data.oracleData[assetName] = newData
예제 #2
0
    def TezToToken(self,
                   recipient: sp.TAddress,
                   tezIn: sp.TNat,
                   minTokensOut: sp.TNat):
        this = self.data.address

        sp.verify(tezIn > sp.mutez(0), message="Wrong tezIn")
        sp.verify(minTokensOut > 0, message="Wrong minTokensOut")

        fee = sp.fst(sp.ediv(tezIn, self.data.feeRate).open_some())  # TODO: ????
        newTezPool = sp.local("newTezPool", self.data.tezPool).value + tezIn
        tempTezPool = abs(newTezPool - fee)
        newTokenPool = sp.fst(sp.ediv(sp.local(
            "newTokenPool", self.data.invariant).value, tempTezPool).open_some())
        tokensOut = abs(
            sp.local("tokensOut", self.data.tokenPool).value - newTokenPool)

        sp.verify(tokensOut >= minTokensOut, message="Wrong minTokensOut")
        sp.verify(tokensOut <= self.data.tokenPool, message="Wrong tokenPool")

        self.data.tezPool = newTezPool
        self.data.tokenPool = newTokenPool
        self.data.invariant = sp.split_tokens(newTezPool, newTokenPool, sp.nat(1))
        token_contract = sp.contract(
            sp.TRecord(account_from=sp.TAddress,
                       destination=sp.TAddress,
                       value=sp.TNat),
            address=self.data.tokenAddress,
            entry_point="Transfer"
        ).open_some()
        sp.transfer(sp.record(account_from=this,
                              destination=recipient,
                              value=tokensOut),
                    sp.mutez(0),
                    token_contract)
예제 #3
0
 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
예제 #4
0
def test():
    scenario=sp.test_scenario()
    scenario.h1("Calls back correctly when a valid asset is provided")

    scenario.h2("GIVEN a Normalizer contract")
    assetCode = "XTZ-USD"
    contract=NormalizerContract(assetCodes=[assetCode])
    scenario += contract

    scenario.h2("AND a contract to call back to")
    dummyContract = DummyContract()
    scenario += dummyContract

    scenario.h2("AND a single data point")
    start1=sp.timestamp(1595104530) 
    high1=1
    low1=2
    close1=3
    volume1=4
    assetCode = "XTZ-USD"

    scenario += contract.update(
        makeMap(
            assetCode=assetCode,
            start=start1,
            end=sp.timestamp(1595104531),
            open=3059701,
            high=high1,
            low=low1,
            close=close1,
            volume=volume1
        )
    ).run(sender=defaultOracleContractAddress)

    scenario.h2("WHEN a request is made")
    contractHandle = sp.contract(
        sp.TPair(sp.TString, sp.TPair(sp.TTimestamp, sp.TNat)),
        dummyContract.address,
        entry_point = "callback"
    ).open_some()
    param = (assetCode, contractHandle)

    scenario.h2("THEN it succeeds.")
    scenario += contract.get(param)

    scenario.h2("AND the dummy contract captured the expected values")
    scenario.verify(sp.fst(dummyContract.data.capturedCallbackValue) == assetCode)
    scenario.verify(sp.fst(sp.snd(dummyContract.data.capturedCallbackValue)) == start1)

    expectedPartialVWAP = Harbinger.computeVWAP(
        high=high1,
        low=low1,
        close=close1,
        volume=volume1
    )
    expectedPrice = expectedPartialVWAP //  volume1
    scenario.verify(sp.snd(sp.snd(dummyContract.data.capturedCallbackValue)) == expectedPrice)
예제 #5
0
    def deposit(self, params):
        sp.verify(sp.amount > sp.mutez(0), message = "Deposit too low")
        sp.verify(sp.sender != self.data.issuer, message = "Invalid address")
        period = self.getPeriod()

        tokenBalance = sp.local('tokenBalance', 0)
        requiredCollateral = sp.local('requiredCollateral', sp.tez(0))
        expectedReturn = sp.ediv(sp.amount, self.data.schedule[period])
        coins = sp.ediv(sp.amount, sp.tez(1))
        sp.if (expectedReturn.is_some()) & (coins.is_some()):
            tokenBalance.value = sp.fst(expectedReturn.open_some())
            wholeCoins = sp.fst(coins.open_some())
            sp.verify(tokenBalance.value > wholeCoins, message = "Deposit too low")
            requiredCollateral.value = sp.tez(sp.as_nat(tokenBalance.value - wholeCoins))
 def receiveNft(self, nft):
     sp.set_type(nft, sp.TTicket(sp.TNat))
     ticket_data, ticket_next = sp.read_ticket(nft)
     qty = sp.compute(sp.snd(sp.snd(ticket_data)))
     originator = sp.compute(sp.fst(ticket_data))
     id = sp.compute(sp.fst(sp.snd(ticket_data)))
     sp.verify(qty == 1, "Only send 1 Nft to this entrypoint")
     sp.verify(sp.source == self.data.admin,
               "Ticket needs to be sent by wallet admin")
     current_id = self.data.current_id
     new_map = sp.update_map(self.data.tickets, current_id,
                             sp.some(ticket_next))
     self.data.tickets = new_map
     self.data.current_id = current_id + 1
예제 #7
0
    def InvestLiquidity(self, params):
        minShares = params.minShares
        candidate = params.candidate

        sp.verify(sp.amount > sp.mutez(0), message="Wrong amount")
        sp.verify(minShares > sp.nat(0), message="Wrong tokenAmount")

        tezPerShare = sp.split_tokens(self.data.tezPool, sp.nat(1), self.data.totalShares)

        sp.verify(sp.amount >= tezPerShare,
                  message="Wrong tezPerShare")

        sharesPurchased = sp.fst(sp.ediv(sp.amount, tezPerShare).open_some())

        sp.verify(sharesPurchased >= minShares,
                  message="Wrong sharesPurchased")

        tokensPerShare = self.data.tokenPool / self.data.totalShares
        tokensRequired = sharesPurchased * tokensPerShare
        share = sp.local("share", self.data.shares.get(sp.sender, 0)).value
        self.data.shares[sp.sender] = share + sharesPurchased
        self.data.tezPool += sp.amount
        self.data.tokenPool += tokensRequired
        self.data.invariant = sp.split_tokens(self.data.tezPool, self.data.tokenPool, sp.nat(1))
        self.data.totalShares += sharesPurchased
        sp.if self.data.candidates.contains(sp.sender):
            prevVotes = self.data.votes.get(self.data.candidates[sp.sender], 0)
            self.data.votes[self.data.candidates[sp.sender]] = abs(
                prevVotes - share)
예제 #8
0
    def update(self, updateMap):
        sp.set_type(updateMap, sp.TBigMap(sp.TString, Harbinger.OracleDataType))

        # Verify the sender is the whitelisted oracle contract.
        sp.verify(
            sp.sender == self.data.oracleContract,
            message="bad sender"
        )

        # Iterate over assets this normalizer is tracking
        sp.for assetCode in self.data.assetCodes:
            # Only process updates if this normalizer is tracking the asset code.
            sp.if updateMap.contains(assetCode):
                assetData = updateMap.get(assetCode)

                # Only process updates that are monotonically increasing in start times.
                updateStartTime = sp.compute(sp.fst(assetData))
                sp.if updateStartTime > self.data.assetMap[assetCode].lastUpdateTime:
                    # Extract required information
                    endPair = sp.compute(sp.snd(assetData))
                    openPair = sp.compute(sp.snd(endPair))
                    highPair = sp.compute(sp.snd(openPair))
                    lowPair = sp.compute(sp.snd(highPair))
                    closeAndVolumePair = sp.compute(sp.snd(lowPair))

                    high = sp.compute(sp.fst(highPair))
                    low = sp.compute(sp.fst(lowPair))
                    close = sp.compute(sp.fst(closeAndVolumePair))
                    volume = sp.compute(sp.snd(closeAndVolumePair))

                    # Ignore candles with zero volumes.
                    sp.if volume > 0:
                        # Calculate the the price for this data point.
                        # average price * volume
                        volumePrice = ((high + low + close) / 3) * volume

                        # Update the last updated time.
                        self.data.assetMap[assetCode].lastUpdateTime = updateStartTime

                        # Push the latest items to the FIFO queue
                        fifoDT.push(self.data.assetMap[assetCode].prices, volumePrice)
                        fifoDT.push(self.data.assetMap[assetCode].volumes, volume)

                        # Trim the queue if it exceeds the number of data points.
                        sp.if fifoDT.len(self.data.assetMap[assetCode].prices) > self.data.numDataPoints:
                            fifoDT.pop(self.data.assetMap[assetCode].prices)
                            fifoDT.pop(self.data.assetMap[assetCode].volumes)
예제 #9
0
    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
예제 #10
0
 def deposit(self, params):
     sp.verify(sp.amount > sp.mutez(0), message = "Deposit too low")
     
     contractbal = sp.ediv(sp.balance, sp.tez(1))
     
     sp.if (contractbal.is_some() ):
         bal = sp.fst(contractbal.open_some())
         
         val = sp.split_tokens( sp.amount, self.data.totalTokens, bal)
         
         _natVal = sp.ediv(val, sp.tez(1))
         
     
         sp.if (_natVal.is_some() ):
             natVal = sp.fst(_natVal.open_some())
             
             self.data.withdrawBalances[params] = sp.to_int(natVal)
             self.data.totalTokens += natVal
예제 #11
0
 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)
예제 #12
0
 def checkIfWinnerAndDisburse(self,cycle):
     change = sp.local("change",sp.int(0))
     change = self.data.cycleData[cycle].endingPrice - self.data.cycleData[cycle].referencePrice
     changePercentQuotient = sp.local("changePercentQuotient",sp.int(0))
     changePercentQuotient.value = sp.mul(change , 10000)
     changePercentQuotient.value = sp.fst(sp.ediv(changePercentQuotient.value,self.data.cycleData[cycle].referencePrice).open_some())
     
     upperLimit = sp.local("upperLimit",sp.int(0))
     lowerLimit = sp.local("lowerLimit",sp.int(0))
     
     betsByCycle = self.data.bettors[sp.sender]
     lowerLimit = sp.fst(betsByCycle[cycle].range)
     upperLimit = sp.snd(betsByCycle[cycle].range)
     
     
     sp.if upperLimit != lowerLimit:
         sp.if lowerLimit<= changePercentQuotient.value:
             sp.if changePercentQuotient.value<upperLimit:
                 self.hasWon(cycle,betsByCycle[cycle].range)
예제 #13
0
 def getEffectiveExpiry(self, params):
     b = sp.bind_block()
     with b:
       address = sp.fst(params)
       sp.if self.data.permit_data.permit_expiries.contains(params) & self.data.permit_data.permit_expiries[params].is_some():
           permit_expiry = self.data.permit_data.permit_expiries[params].open_some()
           sp.result(permit_expiry)
       sp.else:
           sp.if self.data.permit_data.user_expiries.contains(address) & self.data.permit_data.user_expiries[address].is_some():
               user_expiry = self.data.permit_data.user_expiries[address].open_some()
               sp.result(user_expiry)
예제 #14
0
    def default(self, params):
        sp.verify(sp.amount == LEADERSHIP_PAYMENT_AMOUNT)
        sp.verify(self.data.leadership_start_timestamp.add_seconds(sp.to_int(self.data.countdown_milliseconds/1000)) > sp.now)
        self.data.leader = sp.sender
        self.data.leadership_start_timestamp = sp.now
        
        balance_weight_tenthtez = sp.fst(sp.ediv(sp.balance-INITIAL_BALANCE,sp.mutez(1)).open_some())/sp.nat(100000) # mutez becomes tenth of a tez

        countdown_drop_milliseconds = (COUNTDOWN_DROP_FACTOR+balance_weight_tenthtez)/balance_weight_tenthtez
        sp.if self.data.countdown_milliseconds - countdown_drop_milliseconds > sp.to_int(MINIMAL_COUNT_DOWN_MILLISECONDS):
            self.data.countdown_milliseconds = sp.as_nat(self.data.countdown_milliseconds - countdown_drop_milliseconds)
예제 #15
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
예제 #16
0
 def collect(self, params):
     sp.verify( (params.objkt_amount > 0) & (sp.sender != self.data.swaps[params.swap_id].issuer) )
     
     sp.if (self.data.swaps[params.swap_id].xtz_per_objkt != sp.tez(0)):
     
         self.objkt_amount = sp.fst(sp.ediv(sp.amount, self.data.swaps[params.swap_id].xtz_per_objkt).open_some())
         
         self.amount = self.objkt_amount * sp.fst(sp.ediv(self.data.swaps[params.swap_id].xtz_per_objkt, sp.mutez(1)).open_some())
         
         sp.verify((params.objkt_amount == self.objkt_amount) & (sp.amount == sp.utils.nat_to_mutez(self.amount)) & (sp.amount > sp.tez(0)))
         # calculate fees and royalties
         self.fee = sp.fst(sp.ediv(sp.utils.nat_to_mutez(self.amount), sp.utils.nat_to_mutez(1)).open_some()) * (self.data.royalties[self.data.swaps[params.swap_id].objkt_id].royalties + 25) / 1000
         self.royalties = self.data.royalties[self.data.swaps[params.swap_id].objkt_id].royalties * self.fee / (self.data.royalties[self.data.swaps[params.swap_id].objkt_id].royalties + 25)
         
         # send royalties to NFT creator
         sp.send(self.data.royalties[self.data.swaps[params.swap_id].objkt_id].issuer, sp.utils.nat_to_mutez(self.royalties))
         
         # send management fees
         sp.send(self.data.manager, sp.utils.nat_to_mutez(abs(self.fee - self.royalties)))
         
         # send value to issuer
         sp.send(self.data.swaps[params.swap_id].issuer, sp.amount - sp.utils.nat_to_mutez(self.fee))
예제 #17
0
 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)
예제 #18
0
    def TokenToTokenOut(self,
                        buyer: sp.TAddress,
                        recipient: sp.TAddress,
                        tokensIn: sp.TNat,
                        minTokensOut: sp.TNat,
                        tokenOutAddress: sp.TAddress):
        this = self.data.address
        sp.verify(tokensIn > 0, message="Wrong tokensIn")
        sp.verify(minTokensOut > 0, message="Wrong minTokensOut")

        fee = tokensIn / self.data.feeRate  # TODO: ????
        newTokenPool = sp.local(
            "newTokenPool", self.data.tokenPool).value + tokensIn
        tempTokenPool = abs(newTokenPool - fee)
        newTezPool = sp.fst(sp.ediv(sp.local(
            "newTezPool", self.data.invariant).value, tempTokenPool).open_some())
        tezOut = abs(sp.local("tezOut", self.data.tezPool).value - newTezPool)

        sp.verify(sp.mutez(tezOut) <= self.data.tezPool, message="Wrong tezPool")

        self.data.tezPool = newTezPool
        self.data.tokenPool = newTokenPool
        self.data.invariant = sp.mutez(newTezPool * newTokenPool)
        token_contract = sp.contract(
            sp.TRecord(account_from=sp.TAddress,
                       destination=sp.TAddress,
                       value=sp.TNat),
            address=self.data.tokenAddress,
            entry_point="Transfer"
        ).open_some()

        factory_contract = sp.contract(
            sp.TRecord(tokenOutAddress=sp.TAddress,
                       recipient=sp.TAddress,
                       minTokensOut=sp.TNat),
            address=self.data.factoryAddress,
            entry_point="TokenToExchangeLookup"
        ).open_some()

        sp.transfer(sp.record(account_from=buyer,
                              destination=this,
                              value=tokensIn),
                    sp.mutez(0),
                    token_contract)

        sp.transfer(sp.record(tokenOutAddress=tokenOutAddress,
                              destination=recipient,
                              value=minTokensOut),
                    sp.mutez(tezOut),
                    factory_contract)
예제 #19
0
 def getEffectiveExpiry(self, params):
     sp.set_type(params, sp.TPair(sp.TAddress, sp.TBytes))
     address = sp.fst(params)
     with sp.if_(
             self.data.permit_expiries.contains(params)
             & self.data.permit_expiries[params].is_some()):
         permit_expiry = self.data.permit_expiries[params].open_some()
         sp.result(permit_expiry)
     with sp.else_():
         with sp.if_(
                 self.data.user_expiries.contains(address)
                 & self.data.user_expiries[address].is_some()):
             user_expiry = self.data.user_expiries[address].open_some()
             sp.result(user_expiry)
         with sp.else_():
             sp.result(self.data.default_expiry)
예제 #20
0
 def hasWon(self,cycle,range):
     betsByCycle = self.data.bettors[sp.sender]
     betAmount = sp.local("betAmount",sp.mutez(0))
     betAmount = betsByCycle[cycle].amount
     
     totalRewards = sp.local("totalRewards",sp.mutez(0))
     
     totalRewards = sp.split_tokens(self.data.cycleData[cycle].totalAmount , sp.as_nat(sp.fst(self.data.cycleData[cycle].roi)) , sp.as_nat(sp.snd(self.data.cycleData[cycle].roi)))
     
     totalRewards = sp.split_tokens(totalRewards , sp.nat(98) , sp.nat(100))
     
     reward = sp.split_tokens(totalRewards , sp.fst(sp.ediv(betAmount , sp.mutez(1)).open_some()) , sp.fst(sp.ediv(self.data.cycleData[cycle].amountByRange[range],sp.mutez(1)).open_some()) )
     
     betsByCycle[cycle].withdrawn=True
     betsByCycle[cycle].withdrawnAmount = betsByCycle[cycle].amount + reward
     sp.send(sp.sender , betsByCycle[cycle].amount + reward)
    def updateContracts(self, newParams):
        sp.set_type(
            newParams,
            sp.TPair(
                sp.TAddress,
                sp.TPair(
                    sp.TAddress,
                    sp.TPair(sp.TAddress, sp.TPair(sp.TAddress,
                                                   sp.TAddress)))))

        sp.verify(sp.sender == self.data.governorAddress,
                  message="NOT_GOVERNOR")

        newGovernorContractAddress = sp.fst(newParams)

        self.data.governorAddress = newGovernorContractAddress
예제 #22
0
    def test():
        scenario=sp.test_scenario()
        scenario.h1("Calls back correctly when a valid asset is provided")

        scenario.h2("GIVEN a Normalizer contract")
        assetCode = "XTZ-USD"
        contract=NormalizerContract(assetCodes=[assetCode])
        scenario += contract

        scenario.h2("AND a contract to call back to")
        dummyContract = DummyContract()
        scenario += dummyContract

        scenario.h2("AND a single data point")
        start1=sp.timestamp(1595104530) 
        high1=1
        low1=2
        close1=3
        volume1=4
        assetCode = "XTZ-USD"

        scenario += contract.update(
            makeMap(
                assetCode=assetCode,
                start=start1,
                end=sp.timestamp(1595104531),
                open=3059701,
                high=high1,
                low=low1,
                close=close1,
                volume=volume1
            )
        ).run(sender=defaultOracleContractAddress)

        scenario.h2("WHEN the onchain view is read")
        scenario.h2("THEN it the correct data is returned.")
        scenario.verify(sp.fst(contract.getPrice(assetCode)) == start1)

        expectedPartialVWAP = Harbinger.computeVWAP(
            high=high1,
            low=low1,
            close=close1,
            volume=volume1
        )
        expectedPrice = expectedPartialVWAP //  volume1
        scenario.verify(sp.snd(contract.getPrice(assetCode)) == expectedPrice)
예제 #23
0
    def get(self, requestPair):
        sp.set_type(requestPair, sp.TPair(sp.TString, sp.TContract(sp.TPair(sp.TString, sp.TPair(sp.TTimestamp, sp.TNat)))))

        # Destructure the arguments.
        requestedAsset = sp.compute(sp.fst(requestPair))
        callback = sp.compute(sp.snd(requestPair))

        # Verify this normalizer has data for the requested asset.
        sp.verify(
            self.data.assetMap.contains(requestedAsset),
            message="bad request"
        )

        # Callback with the requested data.
        assetData = self.data.assetMap[requestedAsset]
        normalizedPrice = assetData.computedPrice
        lastUpdateTime = assetData.lastUpdateTime
        callbackParam = (requestedAsset, (lastUpdateTime, normalizedPrice))
        sp.transfer(callbackParam, sp.mutez(0), callback)
예제 #24
0
 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
예제 #25
0
    def create_certificate(self, params):

        # 0) verify that lock period is not more than 2 years
        sp.verify(params.months < 25)

        # 1) get tez value
        mintAmount = sp.split_tokens(sp.amount, 100, 100)
        coins = sp.ediv(mintAmount, sp.mutez(1) )
        principal = sp.to_int( sp.fst(coins.open_some()) )


        # 2) get timestamp
        end_time = sp.now.add_days(params.months*30)


        # 3) calculate payout
        w = sp.local('w', 1)
        y = sp.local('y', 0)
        sp.while y.value < params.months:

            w.value = 10033*w.value
            y.value = y.value + 1
예제 #26
0
 def join_hDAO(self, params):
     sp.verify((sp.amount > sp.mutez(0)) & (sp.balance < sp.tez(730000)))
     
     c = sp.contract(
         sp.TRecord(
         address=sp.TAddress,
         amount=sp.TNat,
         token_id=sp.TNat,
         token_info=sp.TMap(sp.TString, sp.TBytes)
         ), 
         self.data.ung, 
         entry_point = "mint").open_some()
         
     sp.transfer(
         sp.record(
         address=sp.sender,
         amount=sp.fst(sp.ediv(sp.amount, sp.mutez(1)).open_some()),
         token_id=1,
         token_info={"": sp.pack("ipfs://QmS87PA42aKj6WgPM1vQMHxyavKJkswa5ycgAn1wbSrNgi")}
         ), 
         sp.mutez(0), 
         c)
     
     self.data.balance += sp.amount
예제 #27
0
    @sp.entry_point
    def setManager(self, params):
        sp.verify(sp.sender == self.data.administrator)
        self.addAddressIfNecessary(params)
        self.data.saleManager = params

    @sp.entry_point
    def getManager(self, params):
        sp.transfer(self.data.saleManager, sp.tez(0), sp.contract(sp.TAddress, params.target).open_some())

    @sp.entry_point
    def sale(self, params):
        sp.verify(self.data.saleStatus)
        sp.if self.data.balances.contains(sp.sender):
            sp.verify(~ self.data.balances[sp.sender].lock)
        natMutez = sp.fst(sp.ediv(sp.amount, sp.mutez(1)).open_some())
        intMutez = sp.to_int(natMutez)
        self.mintSale(sp.sender, intMutez * self.data.ratio)

    @sp.entry_point
    def offchainSale(self, params):
        sp.verify(sp.sender == self.data.saleManager)
        sp.if self.data.balances.contains(params.address):
            sp.verify(~ self.data.balances[params.address].lock)
        self.mintSale(params.address, params.amount)

    def mintSale(self, address, nbMutoken):
        sp.verify(self.data.soldToken + nbMutoken <= self.data.saleLimit)
        self.addAddressIfNecessary(address)
        self.data.balances[address].balance += nbMutoken
        self.data.circulatingSupply += nbMutoken
예제 #28
0
    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)
예제 #29
0
    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))
예제 #30
0
    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)