Skip to content

Commit

Permalink
Restore updateloantoken (#1272)
Browse files Browse the repository at this point in the history
  • Loading branch information
Bushstar authored May 24, 2022
1 parent b0a9e04 commit 75b22b4
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 30 deletions.
3 changes: 0 additions & 3 deletions src/masternodes/loan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,9 +74,6 @@ Res CLoanView::SetLoanToken(CLoanSetLoanTokenImpl const & loanToken, DCT_ID cons

Res CLoanView::UpdateLoanToken(CLoanSetLoanTokenImpl const & loanToken, DCT_ID const & id)
{
if (loanToken.interest < 0)
return Res::Err("interest rate cannot be less than 0!");

WriteBy<LoanSetLoanTokenKey>(id, loanToken);

return Res::Ok();
Expand Down
60 changes: 44 additions & 16 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -537,10 +537,7 @@ class CCustomMetadataParseVisitor : public boost::static_visitor<Res>

Res operator()(CLoanUpdateLoanTokenMessage& obj) const {
auto res = isPostFortCanningFork();
if (!res)
return res;
res = isPostFortCanningCrunchFork();
return res ? Res::Err("called after FortCanningCrunch height") : serialize(obj);
return !res ? res : serialize(obj);
}

Res operator()(CLoanSchemeMessage& obj) const {
Expand Down Expand Up @@ -2458,7 +2455,16 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (!HasFoundationAuth())
return Res::Err("tx not from foundation member!");

auto loanToken = mnview.GetLoanToken(obj.tokenTx);
if (obj.interest < 0)
return Res::Err("interest rate cannot be less than 0!");

auto pair = mnview.GetTokenByCreationTx(obj.tokenTx);
if (!pair)
return Res::Err("Loan token (%s) does not exist!", obj.tokenTx.GetHex());

auto loanToken = height >= static_cast<uint32_t>(consensus.FortCanningCrunchHeight) ?
mnview.GetLoanTokenByID(pair->first) : mnview.GetLoanToken(obj.tokenTx);

if (!loanToken)
return Res::Err("Loan token (%s) does not exist!", obj.tokenTx.GetHex());

Expand All @@ -2468,30 +2474,52 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (obj.interest != loanToken->interest)
loanToken->interest = obj.interest;

auto pair = mnview.GetTokenByCreationTx(obj.tokenTx);
if (!pair)
return Res::Err("Loan token (%s) does not exist!", obj.tokenTx.GetHex());

if (obj.symbol != pair->second.symbol)
pair->second.symbol = trim_ws(obj.symbol).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH);

if (obj.name != pair->second.name)
pair->second.name = trim_ws(obj.name).substr(0, CToken::MAX_TOKEN_NAME_LENGTH);

if (obj.fixedIntervalPriceId != loanToken->fixedIntervalPriceId) {
if (!OraclePriceFeed(mnview, obj.fixedIntervalPriceId))
return Res::Err("Price feed %s/%s does not belong to any oracle", obj.fixedIntervalPriceId.first, obj.fixedIntervalPriceId.second);

loanToken->fixedIntervalPriceId = obj.fixedIntervalPriceId;
}

if (obj.mintable != (pair->second.flags & (uint8_t)CToken::TokenFlags::Mintable))
pair->second.flags ^= (uint8_t)CToken::TokenFlags::Mintable;

res = mnview.UpdateToken(pair->second);
if (!res)
return res;

if (height >= static_cast<uint32_t>(consensus.FortCanningCrunchHeight))
{
const auto& id = pair->first.v;

auto attributes = mnview.GetAttributes();
attributes->time = time;

CDataStructureV0 mintEnabled{AttributeTypes::Token, id, TokenKeys::LoanMintingEnabled};
CDataStructureV0 mintInterest{AttributeTypes::Token, id, TokenKeys::LoanMintingInterest};
CDataStructureV0 pairKey{AttributeTypes::Token, id, TokenKeys::FixedIntervalPriceId};

attributes->SetValue(mintEnabled, obj.mintable);
attributes->SetValue(mintInterest, obj.interest);
attributes->SetValue(pairKey, obj.fixedIntervalPriceId);

res = attributes->Validate(mnview);
if (!res)
return res;

res = attributes->Apply(mnview, height);
if (!res)
return res;

return mnview.SetVariable(*attributes);
}

if (obj.fixedIntervalPriceId != loanToken->fixedIntervalPriceId) {
if (!OraclePriceFeed(mnview, obj.fixedIntervalPriceId))
return Res::Err("Price feed %s/%s does not belong to any oracle", obj.fixedIntervalPriceId.first, obj.fixedIntervalPriceId.second);

loanToken->fixedIntervalPriceId = obj.fixedIntervalPriceId;
}

return mnview.UpdateLoanToken(*loanToken, pair->first);
}

Expand Down
6 changes: 3 additions & 3 deletions src/masternodes/rpc_loan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -428,14 +428,14 @@ UniValue updateloantoken(const JSONRPCRequest& request) {
UniValue const & txInputs = request.params[2];

boost::optional<CLoanSetLoanTokenImplementation> loanToken;
CTokenImplementation tokenImpl;
boost::optional<CTokenImplementation> token;

int targetHeight;
{
LOCK(cs_main);

DCT_ID id;
auto token = pcustomcsview->GetTokenGuessId(tokenStr, id);
token = pcustomcsview->GetTokenGuessId(tokenStr, id);
if (!token) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Token %s does not exist!", tokenStr));
}
Expand Down Expand Up @@ -469,7 +469,7 @@ UniValue updateloantoken(const JSONRPCRequest& request) {

CDataStream metadata(DfTxMarker, SER_NETWORK, PROTOCOL_VERSION);
metadata << static_cast<unsigned char>(CustomTxType::UpdateLoanToken)
<< static_cast<CLoanSetLoanToken>(*loanToken) << loanToken->creationTx;
<< static_cast<CLoanSetLoanToken>(*loanToken) << token->creationTx;

CScript scriptMeta;
scriptMeta << OP_RETURN << ToByteVector(metadata);
Expand Down
29 changes: 29 additions & 0 deletions test/functional/feature_loan_setloantoken.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ def run_test(self):
{"currency": "USD", "token": "TSLA"},
{"currency": "USD", "token": "GOOGL"},
{"currency": "USD", "token": "AMZN"},
{"currency": "USD", "token": "MSFT"},
]
oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds1, 10)
self.nodes[0].generate(1)
Expand Down Expand Up @@ -82,6 +83,7 @@ def run_test(self):
{"currency": "USD", "tokenAmount": "1@TSLA"},
{"currency": "USD", "tokenAmount": "1@GOOGL"},
{"currency": "USD", "tokenAmount": "1@AMZN"},
{"currency": "USD", "tokenAmount": "1@MSFT"},
]
timestamp = calendar.timegm(time.gmtime())
self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices)
Expand Down Expand Up @@ -210,5 +212,32 @@ def run_test(self):
assert_equal(result['v0/token/5/loan_minting_interest'], '0.01')
assert_equal(result['v0/token/5/fixed_interval_price_id'], 'AMZN/USD')

# Update loan token
self.nodes[0].updateloantoken("GOOGL", {
'symbol': "MSFT",
'name': "Microsoft",
'fixedIntervalPriceId': "MSFT/USD",
'mintable': False,
'interest': 0.05})
self.nodes[0].generate(1)

# Check tokens
result = self.nodes[0].gettoken("MSFT")['4']
assert_equal(result['symbol'], 'MSFT')
assert_equal(result['symbolKey'], 'MSFT')
assert_equal(result['name'], 'Microsoft')
assert_equal(result['mintable'], False)
assert_equal(result['tradeable'], True)
assert_equal(result['isDAT'], True)
assert_equal(result['isLPS'], False)
assert_equal(result['finalized'], False)
assert_equal(result['isLoanToken'], True)

# Check attributess
result = self.nodes[0].listgovs()[8][0]['ATTRIBUTES']
assert_equal(result['v0/token/4/loan_minting_enabled'], 'false')
assert_equal(result['v0/token/4/loan_minting_interest'], '0.05')
assert_equal(result['v0/token/4/fixed_interval_price_id'], 'MSFT/USD')

if __name__ == '__main__':
LoanSetLoanTokenTest().main()
8 changes: 0 additions & 8 deletions test/functional/feature_loan_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -749,14 +749,6 @@ def loan_and_collateral_token_to_govvar(self):
# Move to hard fork again
self.move_to_gw_fork()

# Try and call disabled RPC calls
assert_raises_rpc_error(-32600, 'called after FortCanningCrunch height', self.nodes[0].updateloantoken, "DUSD", {
'symbol': "DUSD",
'name': "DUSD stable token",
'fixedIntervalPriceId': "DUSD/USD",
'mintable': True,
'interest': 1})

# Test setting collateral token partially
self.nodes[0].setgov({"ATTRIBUTES":{f'v0/token/{self.idETH}/fixed_interval_price_id':'ETH/USD', f'v0/token/{self.idETH}/loan_collateral_enabled':'true'}})
self.nodes[0].generate(1)
Expand Down

0 comments on commit 75b22b4

Please sign in to comment.