Skip to content

Commit

Permalink
Allow Governance and Foundation to update loan tokens after the fork (#…
Browse files Browse the repository at this point in the history
…3091)

* Allow Governance and Foundation to update loan tokens after the fork

* simplify branch

* lint: Format CPP

---------

Co-authored-by: Prasanna Loganathar <[email protected]>
  • Loading branch information
Bushstar and prasannavl authored Oct 11, 2024
1 parent 97497e2 commit bd5782f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 25 deletions.
10 changes: 7 additions & 3 deletions src/dfi/consensus/tokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,13 @@ Res CTokensConsensus::operator()(const CUpdateTokenMessage &obj) const {

if (!ownerAuth) {
// Governance or foundation can still mark/unmark token deprecation
if (auto res = authCheck.HasGovOrFoundationAuth(); res) {
if (auto res = authCheck.HasGovOrFoundationAuth(); !res) {
return Res::Err("Authentication failed for token owner");
}

// If it's loan token, that's owned by gov, so we don't need to disallow.
// Limit update token for governance and foundation for non-loan tokens
if (!mnview.GetLoanTokenByID(tokenID)) {
// Allow only deprecation. We disallow changes like name or symbol
// as a token holder shouldn't be misrepresented by governance.
// Governance can choose completely discard it by deprecating it
Expand All @@ -216,8 +222,6 @@ Res CTokensConsensus::operator()(const CUpdateTokenMessage &obj) const {
if (disallowedChanges) {
return Res::Err("Only token deprecation toggle is allowed by governance");
}
} else {
return Res::Err("Authentication failed for token owner");
}
}

Expand Down
4 changes: 3 additions & 1 deletion src/dfi/rpc_tokens.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,8 @@ UniValue updatetoken(const JSONRPCRequest &request) {

auto [view, accountView, vaultView] = GetSnapshots();
auto targetHeight = view->GetLastHeight() + 1;
DCT_ID id{};
{
DCT_ID id;
auto token = view->GetTokenGuessId(tokenStr, id);
if (!token) {
throw JSONRPCError(RPC_INVALID_PARAMETER, strprintf("Token %s does not exist!", tokenStr));
Expand Down Expand Up @@ -350,6 +350,8 @@ UniValue updatetoken(const JSONRPCRequest &request) {
const auto members = GetFoundationMembers(*view);
isFoundersToken =
!members.empty() ? members.count(owner) : Params().GetConsensus().foundationMembers.count(owner);
} else if (view->GetLoanTokenByID(id)) {
isFoundersToken = true;
}

if (isFoundersToken) { // need any founder's auth
Expand Down
100 changes: 79 additions & 21 deletions test/functional/feature_community_governance.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ def run_test(self):
# Test updating Governance
self.govvar_checks()

# Test loan token Foundation update after fork
self.update_loan_token(0)

# Test loan token Governance update after fork
self.update_loan_token(1)

# Test member addition, removal and errors
self.member_update_and_errors()

Expand Down Expand Up @@ -235,8 +241,55 @@ def pre_fork_checks(self):
},
)

def test_setting_governance(self):
def update_loan_token(self, node):
# Rollback block
self.rollback_to_start()

# Enable Governance
self.enable_governance(self.governance_member)

# Create loan token
id = self.create_meta_loan_token(node)

# Token split
self.nodes[node].setgovheight(
{
"ATTRIBUTES": {
f"v0/oracles/splits/{self.nodes[node].getblockcount() + 4}": f"{id}/2"
}
},
self.nodes[node].getblockcount() + 2,
)
self.nodes[node].generate(4)

# Update the ID after split
id = list(self.nodes[node].gettoken("META").keys())[0]

# Unlock token
self.nodes[node].setgovheight(
{"ATTRIBUTES": {f"v0/locks/token/{id}": "false"}},
self.nodes[node].getblockcount() + 2,
)
self.nodes[node].generate(2)

# Check no collateral set
assert_equal(
self.nodes[node].gettoken("META")[f"{id}"]["collateralAddress"], ""
)

# Update DAT token. Will use owner auth.
self.nodes[node].updatetoken(
"META",
{
"name": "META",
},
)
self.nodes[node].generate(1)

# Check loan token renamed
assert_equal(self.nodes[node].gettoken("META")[id]["name"], "META")

def test_setting_governance(self):
# Rollback block
self.rollback_to_start()

Expand Down Expand Up @@ -940,24 +993,17 @@ def governance_oracles(self):
self.nodes[1].setoracledata(oracle_tx, int(time.time()), oracle_prices)
self.nodes[1].generate(1)

def governance_loans(self):

# Rollback block
self.rollback_to_start()

# Enable Governance
self.enable_governance(self.governance_member)

def create_meta_loan_token(self, node):
# Price feeds
price_feeds = [
{"currency": "USD", "token": "META"},
{"currency": "USD", "token": "DFI"},
]

# Appoint Oracle
oracle_address = self.nodes[1].getnewaddress()
oracle_tx = self.nodes[1].appointoracle(oracle_address, price_feeds, 10)
self.nodes[1].generate(1)
oracle_address = self.nodes[node].getnewaddress()
oracle_tx = self.nodes[node].appointoracle(oracle_address, price_feeds, 10)
self.nodes[node].generate(1)

# Feed oracle
oracle_prices = [
Expand All @@ -966,17 +1012,17 @@ def governance_loans(self):
]

# Set Oracle data
self.nodes[1].setoracledata(oracle_tx, int(time.time()), oracle_prices)
self.nodes[1].generate(1)
self.nodes[node].setoracledata(oracle_tx, int(time.time()), oracle_prices)
self.nodes[node].generate(1)

# Set collateral token
self.nodes[1].setcollateraltoken(
self.nodes[node].setcollateraltoken(
{"token": 0, "factor": 1, "fixedIntervalPriceId": "DFI/USD"}
)
self.nodes[1].generate(1)
self.nodes[node].generate(1)

# Set loan token
self.nodes[1].setloantoken(
self.nodes[node].setloantoken(
{
"symbol": "META",
"name": "Facebook",
Expand All @@ -985,10 +1031,22 @@ def governance_loans(self):
"interest": 0,
}
)
self.nodes[1].generate(1)
self.nodes[node].generate(1)

return list(self.nodes[node].gettoken("META").keys())[0]

def governance_loans(self):
# Rollback block
self.rollback_to_start()

# Enable Governance
self.enable_governance(self.governance_member)

# Create loan token
id = self.create_meta_loan_token(1)

# Check loan token created
assert_equal(self.nodes[1].gettoken("META")["2"]["name"], "Facebook")
# Check loan token name
assert_equal(self.nodes[1].gettoken("META")[f"{id}"]["name"], "Facebook")

# Update loan token
self.nodes[1].updateloantoken(
Expand All @@ -1000,7 +1058,7 @@ def governance_loans(self):
self.nodes[1].generate(1)

# Check loan token updated
assert_equal(self.nodes[1].gettoken("META")["2"]["name"], "META")
assert_equal(self.nodes[1].gettoken("META")[f"{id}"]["name"], "META")

# Create loan scheme
self.nodes[1].createloanscheme(150, 1, "LOAN1")
Expand Down

0 comments on commit bd5782f

Please sign in to comment.