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

Collateral increases in value and should be able to be withdrawn #988

Merged
merged 24 commits into from
Jan 21, 2022
Merged
Show file tree
Hide file tree
Changes from 15 commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
d558f46
Scenario where BTC increase and price and should be able to be withdrawn
Jouzo Dec 14, 2021
866b94e
Check that 50% of the collateralization comes from DFI only when DFI …
Jouzo Dec 14, 2021
dd3cc25
Remove unused var
Jouzo Dec 14, 2021
8ce3833
Merge branch 'master' into fix/withdraw_collateral
Jouzo Dec 20, 2021
a513f26
Adds guard against fortcanninghill height
Jouzo Dec 22, 2021
9864ee1
Merge branch 'master' into fix/withdraw_collateral
Jouzo Dec 22, 2021
cbc911d
Add other test scenario
Jouzo Dec 22, 2021
24dc3a8
Check that DFI is 50% of collateralized value of loans in withdrawfro…
Jouzo Dec 23, 2021
819c831
Add test for takeloan
Jouzo Dec 23, 2021
151130d
Use MultiplyAmounts to guard against overflow
Jouzo Dec 23, 2021
0e3d6b6
Fix MultiplyAmounts call
Jouzo Dec 23, 2021
41c6cc6
Withdraw more DFI in test
Jouzo Dec 23, 2021
75f6d21
Merge branch 'master' into fix/withdraw_collateral
Jouzo Dec 23, 2021
301a8ca
Merge branch 'master' into fix/withdraw_collateral
Jouzo Dec 24, 2021
6f388d6
Merge branch 'master' into fix/withdraw_collateral
Jouzo Dec 28, 2021
2bed180
Merge branch 'master' into fix/withdraw_collateral
Jouzo Jan 6, 2022
c565aaa
Add collateral value overflow test
Jouzo Jan 12, 2022
5ae120f
Merge branch 'master' into fix/withdraw_collateral
Jouzo Jan 12, 2022
fb43b3a
Merge branch 'master' into fix/withdraw_collateral
prasannavl Jan 17, 2022
addd633
Merge branch 'master' into fix/withdraw_collateral
Jouzo Jan 18, 2022
a9ad091
Update error message
Jouzo Jan 18, 2022
97c819b
Merge branch 'master' of https://github.com/DeFiCh/ain into fix/withd…
Jouzo Jan 19, 2022
621b8f8
Use arith_uint256 instead of MultiplyAmounts
Jouzo Jan 19, 2022
6f467ec
Merge branch 'master' into fix/withdraw_collateral
prasannavl Jan 20, 2022
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
9 changes: 7 additions & 2 deletions src/chainparams.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,7 @@ class CMainParams : public CChainParams {
consensus.EunosPayaHeight = 1072000; // Aug 05, 2021.
consensus.FortCanningHeight = 1367000; // Nov 15, 2021.
consensus.FortCanningMuseumHeight = 1430640;
consensus.FortCanningHillHeight = std::numeric_limits<int>::max();

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
// consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
Expand Down Expand Up @@ -348,6 +349,7 @@ class CTestNetParams : public CChainParams {
consensus.EunosPayaHeight = 463300;
consensus.FortCanningHeight = 686200;
consensus.FortCanningMuseumHeight = 724000;
consensus.FortCanningHillHeight = std::numeric_limits<int>::max();

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
// consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
Expand Down Expand Up @@ -530,6 +532,7 @@ class CDevNetParams : public CChainParams {
consensus.EunosPayaHeight = 300;
consensus.FortCanningHeight = std::numeric_limits<int>::max();
consensus.FortCanningMuseumHeight = std::numeric_limits<int>::max();
consensus.FortCanningHillHeight = std::numeric_limits<int>::max();

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.pos.nTargetTimespan = 5 * 60; // 5 min == 10 blocks
Expand Down Expand Up @@ -704,6 +707,7 @@ class CRegTestParams : public CChainParams {
consensus.EunosPayaHeight = 10000000;
consensus.FortCanningHeight = 10000000;
consensus.FortCanningMuseumHeight = 10000000;
consensus.FortCanningHillHeight = 10000000;

consensus.pos.diffLimit = uint256S("00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");
consensus.pos.nTargetTimespan = 14 * 24 * 60 * 60; // two weeks
Expand Down Expand Up @@ -915,8 +919,9 @@ void CRegTestParams::UpdateActivationParametersFromArgs(const ArgsManager& args)
consensus.EunosKampungHeight = static_cast<int>(eunosHeight.get());
}
UpdateHeightValidation("Eunos Paya", "-eunospayaheight", consensus.EunosPayaHeight);
UpdateHeightValidation("Fork canning", "-fortcanningheight", consensus.FortCanningHeight);
UpdateHeightValidation("Fork canning museum", "-fortcanningmuseumheight", consensus.FortCanningMuseumHeight);
UpdateHeightValidation("Fort canning", "-fortcanningheight", consensus.FortCanningHeight);
UpdateHeightValidation("Fort canning museum", "-fortcanningmuseumheight", consensus.FortCanningMuseumHeight);
UpdateHeightValidation("Fort canning hill", "-fortcanninghillheight", consensus.FortCanningHillHeight);

if (!args.IsArgSet("-vbparams")) return;

Expand Down
1 change: 1 addition & 0 deletions src/consensus/params.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ struct Params {
int EunosPayaHeight;
int FortCanningHeight;
int FortCanningMuseumHeight;
int FortCanningHillHeight;

/** Foundation share after AMK, normalized to COIN = 100% */
CAmount foundationShareDFIP1;
Expand Down
1 change: 1 addition & 0 deletions src/init.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,7 @@ void SetupServerArgs()
gArgs.AddArg("-eunospayaheight", "EunosPaya fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanningheight", "Fort Canning fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanningmuseumheight", "Fort Canning Museum fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-fortcanninghillheight", "Fort Canning Hill fork activation height (regtest only)", ArgsManager::ALLOW_ANY, OptionsCategory::CHAINPARAMS);
gArgs.AddArg("-jellyfish_regtest", "Configure the regtest network for jellyfish testing", ArgsManager::ALLOW_ANY, OptionsCategory::OPTIONS);
#ifdef USE_UPNP
#if USE_UPNP
Expand Down
18 changes: 14 additions & 4 deletions src/masternodes/mn_checks.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2505,8 +2505,13 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (col.nTokenId == DCT_ID{0})
totalDFI += col.nValue;

if (totalDFI < collateralsLoans.val->totalCollaterals / 2)
return Res::Err("At least 50%% of the vault must be in DFI");
if (static_cast<int>(height) < consensus.FortCanningHillHeight) {
if (totalDFI < collateralsLoans.val->totalCollaterals / 2)
return Res::Err("At least 50%% of the vault must be in DFI");
} else {
if (MultiplyAmounts(totalDFI, 100) < MultiplyAmounts(collateralsLoans.val->totalLoans, scheme->ratio) / 2)
return Res::Err("At least 50%% of the vault must be in DFI");
Jouzo marked this conversation as resolved.
Show resolved Hide resolved
}

if (collateralsLoans.val->ratio() < scheme->ratio)
return Res::Err("Vault does not have enough collateralization ratio defined by loan scheme - %d < %d", collateralsLoans.val->ratio(), scheme->ratio);
Expand Down Expand Up @@ -2611,8 +2616,13 @@ class CCustomTxApplyVisitor : public CCustomTxVisitor
if (col.nTokenId == DCT_ID{0})
totalDFI += col.nValue;

if (totalDFI < collateralsLoans.val->totalCollaterals / 2)
return Res::Err("At least 50%% of the vault must be in DFI when taking a loan");
if (static_cast<int>(height) < consensus.FortCanningHillHeight) {
if (totalDFI < collateralsLoans.val->totalCollaterals / 2)
return Res::Err("At least 50%% of the vault must be in DFI when taking a loan.");
Jouzo marked this conversation as resolved.
Show resolved Hide resolved
} else {
if (MultiplyAmounts(totalDFI, 100) < MultiplyAmounts(collateralsLoans.val->totalLoans, scheme->ratio) / 2)
return Res::Err("At least 50%% of the vault must be in DFI when taking a loan.");
Jouzo marked this conversation as resolved.
Show resolved Hide resolved
}

if (collateralsLoans.val->ratio() < scheme->ratio)
return Res::Err("Vault does not have enough collateralization ratio defined by loan scheme - %d < %d", collateralsLoans.val->ratio(), scheme->ratio);
Expand Down
1 change: 1 addition & 0 deletions src/rpc/blockchain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,7 @@ UniValue getblockchaininfo(const JSONRPCRequest& request)
BuriedForkDescPushBack(softforks, "eunospaya", consensusParams.EunosPayaHeight);
BuriedForkDescPushBack(softforks, "fortcanning", consensusParams.FortCanningHeight);
BuriedForkDescPushBack(softforks, "fortcanningmuseum", consensusParams.FortCanningMuseumHeight);
BuriedForkDescPushBack(softforks, "fortcanninghill", consensusParams.FortCanningHillHeight);
BIP9SoftForkDescPushBack(softforks, "testdummy", consensusParams, Consensus::DEPLOYMENT_TESTDUMMY);
obj.pushKV("softforks", softforks);

Expand Down
64 changes: 58 additions & 6 deletions test/functional/feature_loan_vault.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ def set_test_params(self):
self.num_nodes = 2
self.setup_clean_chain = True
self.extra_args = [
['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1'],
['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1']
['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=1'],
['-txnotokens=0', '-amkheight=1', '-bayfrontheight=1', '-bayfrontgardensheight=1', '-eunosheight=1', '-txindex=1', '-fortcanningheight=1', '-fortcanninghillheight=1']
]

def run_test(self):
Expand Down Expand Up @@ -424,28 +424,24 @@ def run_test(self):
estimatevault = self.nodes[0].estimatevault('3.00000000@DFI', '3.00000000@TSLAA')
except JSONRPCException as e:
errorString = e.error['message']
print("errorString", errorString)
assert("Invalid Defi token: TSLAA" in errorString)
# Invalid collateral token
try:
estimatevault = self.nodes[0].estimatevault('3.00000000@DFII', '3.00000000@TSLA')
except JSONRPCException as e:
errorString = e.error['message']
print("errorString", errorString)
assert("Invalid Defi token: DFII" in errorString)
# Token not set as a collateral
try:
estimatevault = self.nodes[0].estimatevault('3.00000000@TSLA', '3.00000000@TSLA')
except JSONRPCException as e:
errorString = e.error['message']
print("errorString", errorString)
assert("Token with id (2) is not a valid collateral!" in errorString)
# Token not set as loan token
try:
estimatevault = self.nodes[0].estimatevault('3.00000000@DFI', '3.00000000@DFI')
except JSONRPCException as e:
errorString = e.error['message']
print("errorString", errorString)
assert("Token with id (0) is not a loan token!" in errorString)

vault = self.nodes[0].getvault(vaultId2)
Expand All @@ -455,5 +451,61 @@ def run_test(self):
assert_equal(estimatevault["informativeRatio"], vault["informativeRatio"])
assert_equal(estimatevault["collateralRatio"], vault["collateralRatio"])


# Test BTC price increase and remove some BTC from collateral

# Reset price
oracle1_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "1@BTC"}]
timestamp = calendar.timegm(time.gmtime())
self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices)
self.nodes[0].generate(11)

# Deposit collaterals. 50% of BTC
address = self.nodes[0].getnewaddress()
self.nodes[1].sendtokenstoaddress({}, { address: '1.50@BTC'})
self.nodes[1].generate(1)
self.sync_all()
vaultId4 = self.nodes[0].createvault(address, 'LOAN000A')
self.nodes[0].generate(1)
self.nodes[0].deposittovault(vaultId4, address, '1.25@BTC') # 1.25@BTC as collateral factor 0.8
self.nodes[0].deposittovault(vaultId4, accountDFI, '1@DFI')
self.nodes[0].generate(1)

self.nodes[0].takeloan({
'vaultId': vaultId4,
'amounts': "1@TSLA"
})
self.nodes[0].generate(1)

self.nodes[0].deposittovault(vaultId4, address, '0.2@BTC')
self.nodes[0].generate(1)

# Should be able to withdraw extra BTC
self.nodes[0].withdrawfromvault(vaultId4, address, "0.1@BTC")
self.nodes[0].generate(1)

# BTC doubles in price
oracle1_prices = [{"currency": "USD", "tokenAmount": "1@DFI"}, {"currency": "USD", "tokenAmount": "1@TSLA"}, {"currency": "USD", "tokenAmount": "2@BTC"}]
timestamp = calendar.timegm(time.gmtime())
self.nodes[0].setoracledata(oracle_id1, timestamp, oracle1_prices)
self.nodes[0].generate(20)

# Should be able to withdraw part of BTC after BTC appreciation in price
self.nodes[0].withdrawfromvault(vaultId4, address, "0.5@BTC")
self.nodes[0].generate(1)

# Should not be able to withdraw if DFI lower than 50% of collateralized loan value
try:
self.nodes[0].withdrawfromvault(vaultId4, accountDFI, "0.26@DFI")
except JSONRPCException as e:
errorString = e.error['message']
assert("At least 50% of the vault must be in DFI" in errorString)

# Should be able to take 0.33@TSLA and respect 50% DFI ratio
self.nodes[0].takeloan({
'vaultId': vaultId4,
'amounts': "0.33@TSLA"
})

if __name__ == '__main__':
VaultTest().main()
1 change: 1 addition & 0 deletions test/functional/rpc_blockchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ def _test_getblockchaininfo(self):
'eunospaya': {'type': 'buried', 'active': False, 'height': 10000000},
'fortcanning': {'type': 'buried', 'active': False, 'height': 10000000},
'fortcanningmuseum': {'type': 'buried', 'active': False, 'height': 10000000},
'fortcanninghill': {'type': 'buried', 'active': False, 'height': 10000000},
'testdummy': {
'type': 'bip9',
'bip9': {
Expand Down