def _cash(self, cdtbalance, cdtsupply, cdtamount): # check overflow and change unit cdtbalance = math.uint256(cdtbalance) cdtsupply = math.uint256(cdtsupply) cdtamount = math.uint256(cdtamount) cdtbalance = math.ethertofloat(cdtbalance) cdtsupply = math.ethertofloat(cdtsupply) cdtamount = math.ethertofloat(cdtamount) # Approximate calculation for it is always less than actual amount cdtprice = math.div( cdtbalance, math.mul(cdtsupply, math.decimaltofloat(self.CDT_CRR * self.decimal))) ethamount = math.mul(cdtamount, cdtprice) assert ethamount < cdtbalance cashfee = math.mul( ethamount, math.decimaltofloat(self.CDT_CASHFEE * self.decimal)) ethamount = math.sub(ethamount, cashfee) cdtbalance = math.sub(cdtbalance, ethamount) cdtprice = math.div( cdtbalance, math.mul(cdtsupply, math.decimaltofloat(self.CDT_CRR * self.decimal))) return math.floattoether(ethamount), math.floattodecimal(cdtprice)
def _sigmoid(a, b, l, d, x): assert a > 0 assert b >= 0 assert l >= 0 assert d > 0 if x > l: rate = math.div(math.safeSub(x, l), d) if rate >> (math.PRECISION - math.MIN_PRECISION) < 0x1e00000000: exp = math.exp(rate) addexp = math.add(math.float(1), exp) divexp = math.div(math.float(1), addexp) mulexp = math.mul(a, divexp) y = math.add(mulexp, b) else: y = b elif (x < l) and (x >= 0): rate = math.div(math.safeSub(l, x), d) if rate >> (math.PRECISION - math.MIN_PRECISION) < 0x1e00000000: exp = math.exp(rate) addexp = math.add(math.float(1), exp) divexp = math.div(math.float(1), addexp) mulexp = math.mul(a, divexp) y = math.sub(math.add(a, b * 2), math.add(mulexp, b)) else: y = math.add(a, b) else: y = math.div(math.add(a, b * 2), math.float(2)) return y
def _withdraw(self, dptbalance, dptcirculation, dptamount): # check overflow and change unit dptbalance = math.uint256(dptbalance) dptcirculation = math.uint256(dptcirculation) dptamount = math.uint256(dptamount) dptbalance = math.ethertofloat(dptbalance) dptcirculation = math.ethertofloat(dptcirculation) dptamount = math.ethertofloat(dptamount) dptprice = math.div( dptbalance, math.mul(dptcirculation, self._get_crr(dptcirculation))) # Calculate the maximum ether should be returned to user ethamount = math.mul(dptamount, dptprice) # Calculate the maximum CRR after withdraw max_crr = self._get_crr(math.sub(dptcirculation, dptamount)) # Calculate the minimum price after withdraw dptprice = math.div(math.sub(dptbalance, ethamount), math.mul(dptcirculation, max_crr)) # the actual withdraw price of DPT is equal to the minimum possible price after withdraw, ether=DPT*P actual_ether = math.mul(dptamount, dptprice) return math.floattoether(actual_ether), math.floattodecimal( max_crr), math.floattodecimal(dptprice)
def _sigmoid(a, b, l, d, x): assert a > 0 assert b >= 0 assert l >= 0 assert d > 0 if x > l: rate = math.div(math.safeSub(x, l), d) if rate < 0x1e00000000: exp = math.fixedExp(rate) addexp = math.add(1 << 32, exp) divexp = math.div(1 << 32, addexp) mulexp = math.mul(a, divexp) y = math.add(mulexp, b) else: y = b elif (x < l) and (x >= 0): rate = math.div(math.safeSub(l, x), d) if rate < 0x1e00000000: exp = math.fixedExp(rate) addexp = math.add(1 << 32, exp) divexp = math.div(1 << 32, addexp) mulexp = math.mul(a, divexp) y = math.sub(math.add(a, b * 2), math.add(mulexp, b)) else: y = math.add(a, b) else: y = math.div(math.add(a, b * 2), math.float(2)) return y
def _get_loan_plan(self, supply, circulation): # check over flow and change unit high = math.decimaltofloat(self.high * self.decimal) low = math.decimaltofloat(self.low * self.decimal) supply = math.uint256(supply) circulation = math.uint256(circulation) supply = math.ethertofloat(supply) circulation = math.ethertofloat(circulation) assert 0 < supply assert 0 < circulation return math.floattodecimal( _sigmoid(high - low, low, math.div(supply, math.float(2)), math.div(supply, math.float(8)), circulation) ), self.loandays * 24 * 3600, self.exemptdays * 24 * 3600
def _loan(self, cdtamount, interestrate, crr): # check overflow and change unit cdtamount = math.uint256(cdtamount) interestrate = math.uint256(interestrate) crr = math.uint256(crr) cdtamount = math.ethertofloat(cdtamount) interestrate = math.decimaltofloat(interestrate) crr = math.decimaltofloat(crr) # loaned ether ethamount = math.mul(cdtamount, math.decimaltofloat(self.CDTL * self.decimal)) # calculate the interest earn = math.mul(ethamount, interestrate) cdtreserve = math.mul( earn, math.decimaltofloat(self.CDT_RESERVE * self.decimal)) interest = math.sub(earn, cdtreserve) issuecdtamount = math.div( math.mul(earn, crr), math.decimaltofloat(self.CDTIP * self.decimal)) # calculate the new issue CDT to prize loaned user using the interest ethamount = math.sub(ethamount, earn) sctamount = cdtamount return math.floattoether(ethamount), math.floattoether( interest), math.floattoether(issuecdtamount), math.floattoether( sctamount)
def _issue(self, circulation, ethamount): # check over flow and change unit circulation = math.uint256(circulation) ethamount = math.uint256(ethamount) circulation = math.ethertofloat(circulation) ethamount = math.ethertofloat(ethamount) crr = self._get_crr(circulation) ethdpt = math.mul(ethamount, crr) dpt = math.div(ethdpt, math.decimaltofloat(self.DPTIP * self.decimal)) cdt = math.div(math.mul(math.sub(math.float(1), crr), ethamount), math.decimaltofloat(self.CDTIP * self.decimal)) crr = self._get_crr(circulation) # Split the new issued tokens to User and Founder udpt = math.mul(dpt, math.decimaltofloat(self.U * self.decimal)) ucdt = math.mul(cdt, math.decimaltofloat(self.U * self.decimal)) fdpt = math.mul(dpt, math.decimaltofloat(self.F * self.decimal)) fcdt = math.mul(cdt, math.decimaltofloat(self.F * self.decimal)) return math.floattoether(udpt), math.floattoether( ucdt), math.floattoether(fdpt), math.floattoether( fcdt), math.floattoether(ethdpt), math.floattodecimal(crr)
def _to_credit_token(self, repayethamount, dctamount): # check over float and change unit repayethamount = math.uint256(repayethamount) dctamount = math.uint256(dctamount) repayethamount = math.ethertofloat(repayethamount) dctamount = math.ethertofloat(dctamount) ethamount = math.mul(dctamount, math.decimaltofloat(self.CDTL * self.decimal)) if repayethamount < ethamount: ethamount = repayethamount cdtamount = math.div(ethamount, math.decimaltofloat(self.CDTL * self.decimal)) refunddctamount = math.sub(dctamount, cdtamount) return 0, math.floattoether(cdtamount), math.floattoether( refunddctamount) else: cdtamount = math.div(ethamount, math.decimaltofloat(self.CDTL * self.decimal)) refundethamount = math.sub(repayethamount, ethamount) return math.floattoether(refundethamount), math.floattoether( cdtamount), 0
def _repay(self, repayethamount, sctamount): # check overflow and change unit repayethamount = math.uint256(repayethamount) sctamount = math.uint256(sctamount) repayethamount = math.ethertofloat(repayethamount) sctamount = math.ethertofloat(sctamount) ethamount = math.mul(sctamount, math.decimaltofloat(self.CDTL * self.decimal)) if repayethamount < ethamount: ethamount = repayethamount cdtamount = math.div(ethamount, math.decimaltofloat(self.CDTL * self.decimal)) refundsctamount = math.sub(sctamount, cdtamount) return 0, math.floattoether(cdtamount), math.floattoether( refundsctamount) else: cdtamount = math.div(ethamount, math.decimaltofloat(self.CDTL * self.decimal)) refundethamount = math.sub(repayethamount, ethamount) return math.floattoether(refundethamount), math.floattoether( cdtamount), 0
def _to_discredit_token(self, cdtbalance, supply, sctamount): # check overflow and change unit cdtbalance = math.uint256(cdtbalance) supply = math.uint256(supply) sctamount = math.uint256(sctamount) cdtbalance = math.ethertofloat(cdtbalance) supply = math.ethertofloat(supply) sctamount = math.ethertofloat(sctamount) cdtprice = math.div( cdtbalance, math.mul(supply, math.decimaltofloat(self.CDT_CRR * self.decimal))) return math.floattoether( math.mul(sctamount, math.decimaltofloat( 0.8 * self.decimal))), math.floattodecimal(cdtprice)
def _deposit(self, dptbalance, dptsupply, dptcirculation, ethamount): # check overflow and change unit dptbalance = math.uint256(dptbalance) dptsupply = math.uint256(dptsupply) dptcirculation = math.uint256(dptcirculation) ethamount = math.uint256(ethamount) dptbalance = math.ethertofloat(dptbalance) dptsupply = math.ethertofloat(dptsupply) dptcirculation = math.ethertofloat(dptcirculation) ethamount = math.ethertofloat(ethamount) # Calculate current CRR and price of DPT crr = self._get_crr(dptcirculation) dptprice = math.div(dptbalance, math.mul(dptcirculation, crr)) # Calculate the maximum DPT should be gave to user token = math.div(ethamount, dptprice) # Calculate the maximum balance of DPT contract max_balance = math.add(dptbalance, ethamount) # Calculate the minimum CRR of DPT crr = self._get_crr(math.add(dptcirculation, token)) # Calculate the maximum price of DPT dptprice = math.div(max_balance, math.mul(dptcirculation, crr)) # Actual price is equal to maximum price of DPT, for exchanging as less DPT to user as possible. token = math.div(ethamount, dptprice) # There could be less DPT remained in the DPT contract than supposed DPT, so contract need to issue new DPT # the first situation is there is enough DPT if math.sub(dptsupply, dptcirculation) >= token.real: crr = self._get_crr(math.add(dptcirculation, token)) dptprice = math.div(max_balance, math.mul(math.add(dptcirculation, token), crr)) return math.floattoether(token), 0, math.floattodecimal( crr), math.floattodecimal(dptprice) # the second situation is there is insufficient DPT in the contract else: # the maximum supposed token transfer from contract to user is determined by the remaining DPT in the contract. # the issue price of token is token = math.sub(dptsupply, dptcirculation) # the minimum CRR after the deposit crr = self._get_crr(math.add(dptcirculation, token)) # the maximum price after the deposit dptprice = math.div(max_balance, math.mul(dptcirculation, crr)) return math.floattoether(token), math.floattoether( math.sub(ethamount, math.mul(token, dptprice))), math.floattodecimal( crr), math.floattodecimal(dptprice)