Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update token related calls for Fort Canning Crunch #1265

Merged
merged 2 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 43 additions & 7 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -535,10 +535,7 @@ class CCustomMetadataParseVisitor : public boost::static_visitor<Res>

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

Res operator()(CLoanUpdateLoanTokenMessage& obj) const {
Expand Down Expand Up @@ -2356,6 +2353,48 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (!res)
return res;

if (!HasFoundationAuth())
return Res::Err("tx not from foundation member!");

if (height >= static_cast<uint32_t>(consensus.FortCanningSpiceGardenHeight))
{
CTokenImplementation token;
token.symbol = trim_ws(obj.symbol).substr(0, CToken::MAX_TOKEN_SYMBOL_LENGTH);
token.name = trim_ws(obj.name).substr(0, CToken::MAX_TOKEN_NAME_LENGTH);
token.creationTx = tx.GetHash();
token.creationHeight = height;
token.flags = obj.mintable ? static_cast<uint8_t>(CToken::TokenFlags::Default) : static_cast<uint8_t>(CToken::TokenFlags::Tradeable);
token.flags |= (uint8_t)CToken::TokenFlags::LoanToken | (uint8_t)CToken::TokenFlags::DAT;

auto resVal = mnview.CreateToken(token);
if ( !resVal) {
return res;
}

const auto& tokenId = resVal.val->v;

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

CDataStructureV0 mintEnabled{AttributeTypes::Token, tokenId, TokenKeys::LoanMintingEnabled};
CDataStructureV0 mintInterest{AttributeTypes::Token, tokenId, TokenKeys::LoanMintingInterest};
CDataStructureV0 pairKey{AttributeTypes::Token, tokenId, 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);
}

CLoanSetLoanTokenImplementation loanToken;
static_cast<CLoanSetLoanToken&>(loanToken) = obj;

Expand All @@ -2377,9 +2416,6 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (!resSetFixedPrice)
return Res::Err(resSetFixedPrice.msg);

if (!HasFoundationAuth())
return Res::Err("tx not from foundation member!");

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

Expand Down
66 changes: 63 additions & 3 deletions test/functional/feature_loan_setloantoken.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def set_test_params(self):
self.num_nodes = 1
self.setup_clean_chain = True
self.extra_args = [
['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-fortcanningheight=50', '-eunosheight=50', '-txindex=1']]
['-txnotokens=0', '-amkheight=50', '-bayfrontheight=50', '-eunosheight=50', '-fortcanningheight=50', '-fortcanninghillheight=50', '-fortcanningspicegardenheight=110', '-txindex=1']]

def run_test(self):
assert_equal(len(self.nodes[0].listtokens()), 1) # only one token == DFI
Expand Down Expand Up @@ -48,7 +48,11 @@ def run_test(self):
assert("no live oracles for specified request" in errorString)

oracle_address1 = self.nodes[0].getnewaddress("", "legacy")
price_feeds1 = [{"currency": "USD", "token": "TSLA"}]
price_feeds1 = [
{"currency": "USD", "token": "TSLA"},
{"currency": "USD", "token": "GOOGL"},
{"currency": "USD", "token": "AMZN"},
]
oracle_id1 = self.nodes[0].appointoracle(oracle_address1, price_feeds1, 10)
self.nodes[0].generate(1)

Expand All @@ -74,7 +78,11 @@ def run_test(self):
errorString = e.error['message']
assert("price feed not in valid format - token/currency" in errorString)

oracle1_prices = [{"currency": "USD", "tokenAmount": "1@TSLA"}]
oracle1_prices = [
{"currency": "USD", "tokenAmount": "1@TSLA"},
{"currency": "USD", "tokenAmount": "1@GOOGL"},
{"currency": "USD", "tokenAmount": "1@AMZN"},
]
timestamp = calendar.timegm(time.gmtime())
self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices)
self.nodes[0].generate(1)
Expand Down Expand Up @@ -142,5 +150,57 @@ def run_test(self):
'mintable': True,
'interest': 0})

# Move to fork height
self.nodes[0].generate(110 - self.nodes[0].getblockcount())

# Create loan tokens
self.nodes[0].setloantoken({
'symbol': "GOOGL",
'name': "Google",
'fixedIntervalPriceId': "GOOGL/USD",
'mintable': True,
'interest': 0.01})
self.nodes[0].generate(1)

self.nodes[0].setloantoken({
'symbol': "AMZN",
'name': "Amazon",
'fixedIntervalPriceId': "AMZN/USD",
'mintable': False,
'interest': 0.01})
self.nodes[0].generate(1)

# Check tokens
result = self.nodes[0].gettoken("GOOGL")['4']
assert_equal(result['symbol'], 'GOOGL')
assert_equal(result['symbolKey'], 'GOOGL')
assert_equal(result['name'], 'Google')
assert_equal(result['mintable'], True)
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)

result = self.nodes[0].gettoken("AMZN")['5']
assert_equal(result['symbol'], 'AMZN')
assert_equal(result['symbolKey'], 'AMZN')
assert_equal(result['name'], 'Amazon')
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'], 'true')
assert_equal(result['v0/token/4/loan_minting_interest'], '0.01')
assert_equal(result['v0/token/4/fixed_interval_price_id'], 'GOOGL/USD')
assert_equal(result['v0/token/5/loan_minting_enabled'], 'false')
assert_equal(result['v0/token/5/loan_minting_interest'], '0.01')
assert_equal(result['v0/token/5/fixed_interval_price_id'], 'AMZN/USD')

if __name__ == '__main__':
LoanSetLoanTokenTest().main()
6 changes: 0 additions & 6 deletions test/functional/feature_loan_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -750,12 +750,6 @@ def loan_and_collateral_token_to_govvar(self):
self.move_to_gw_fork()

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