Fixed swap rate tests

This commit is contained in:
The3D 2020-07-07 12:07:31 +02:00
parent 0d182d6436
commit dd1982010c
20 changed files with 188 additions and 832 deletions

View File

@ -245,16 +245,17 @@ library ValidationLogic {
) external view {
require(_reserve.isActive, 'Action requires an active reserve');
require(!_reserve.isFreezed, 'Action requires an unfreezed reserve');
require(
_currentRateMode == CoreLibrary.InterestRateMode.STABLE && _stableBorrowBalance > 0,
'User does not have a stable rate loan in progress on this reserve'
);
require(
_currentRateMode == CoreLibrary.InterestRateMode.VARIABLE && _variableBorrowBalance > 0,
'User does not have a variable rate loan in progress on this reserve'
);
if (_currentRateMode == CoreLibrary.InterestRateMode.VARIABLE) {
if (_currentRateMode == CoreLibrary.InterestRateMode.STABLE) {
require(
_stableBorrowBalance > 0,
'User does not have a stable rate loan in progress on this reserve'
);
} else if (_currentRateMode == CoreLibrary.InterestRateMode.VARIABLE) {
require(
_variableBorrowBalance > 0,
'User does not have a variable rate loan in progress on this reserve'
);
/**
* user wants to swap to stable, before swapping we need to ensure that
* 1. stable borrow rate is enabled on the reserve
@ -272,6 +273,9 @@ library ValidationLogic {
'12'
);
}
else {
revert("Invalid interest rate mode selected");
}
}
/**

View File

@ -92,7 +92,7 @@ contract StableDebtToken is IStableDebtToken, DebtTokenBase {
) public override onlyLendingPool {
MintLocalVars memory vars;
(
uint256 previousBalance,
uint256 currentBalance,

673
package-lock.json generated
View File

@ -4213,679 +4213,6 @@
"integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=",
"dev": true
},
"ganache-cli": {
"version": "6.9.1",
"resolved": "https://registry.npmjs.org/ganache-cli/-/ganache-cli-6.9.1.tgz",
"integrity": "sha512-VPBumkNUZzXDRQwVOby5YyQpd5t1clkr06xMgB28lZdEIn5ht1GMwUskOTFOAxdkQ4J12IWP0gdeacVRGowqbA==",
"dev": true,
"requires": {
"ethereumjs-util": "6.1.0",
"source-map-support": "0.5.12",
"yargs": "13.2.4"
},
"dependencies": {
"ansi-regex": {
"version": "4.1.0",
"bundled": true,
"dev": true
},
"ansi-styles": {
"version": "3.2.1",
"bundled": true,
"dev": true,
"requires": {
"color-convert": "^1.9.0"
}
},
"bindings": {
"version": "1.5.0",
"bundled": true,
"dev": true,
"requires": {
"file-uri-to-path": "1.0.0"
}
},
"bip66": {
"version": "1.1.5",
"bundled": true,
"dev": true,
"requires": {
"safe-buffer": "^5.0.1"
}
},
"bn.js": {
"version": "4.11.8",
"bundled": true,
"dev": true
},
"brorand": {
"version": "1.1.0",
"bundled": true,
"dev": true
},
"browserify-aes": {
"version": "1.2.0",
"bundled": true,
"dev": true,
"requires": {
"buffer-xor": "^1.0.3",
"cipher-base": "^1.0.0",
"create-hash": "^1.1.0",
"evp_bytestokey": "^1.0.3",
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"buffer-from": {
"version": "1.1.1",
"bundled": true,
"dev": true
},
"buffer-xor": {
"version": "1.0.3",
"bundled": true,
"dev": true
},
"camelcase": {
"version": "5.3.1",
"bundled": true,
"dev": true
},
"cipher-base": {
"version": "1.0.4",
"bundled": true,
"dev": true,
"requires": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"cliui": {
"version": "5.0.0",
"bundled": true,
"dev": true,
"requires": {
"string-width": "^3.1.0",
"strip-ansi": "^5.2.0",
"wrap-ansi": "^5.1.0"
}
},
"color-convert": {
"version": "1.9.3",
"bundled": true,
"dev": true,
"requires": {
"color-name": "1.1.3"
}
},
"color-name": {
"version": "1.1.3",
"bundled": true,
"dev": true
},
"create-hash": {
"version": "1.2.0",
"bundled": true,
"dev": true,
"requires": {
"cipher-base": "^1.0.1",
"inherits": "^2.0.1",
"md5.js": "^1.3.4",
"ripemd160": "^2.0.1",
"sha.js": "^2.4.0"
}
},
"create-hmac": {
"version": "1.1.7",
"bundled": true,
"dev": true,
"requires": {
"cipher-base": "^1.0.3",
"create-hash": "^1.1.0",
"inherits": "^2.0.1",
"ripemd160": "^2.0.0",
"safe-buffer": "^5.0.1",
"sha.js": "^2.4.8"
}
},
"cross-spawn": {
"version": "6.0.5",
"bundled": true,
"dev": true,
"requires": {
"nice-try": "^1.0.4",
"path-key": "^2.0.1",
"semver": "^5.5.0",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"decamelize": {
"version": "1.2.0",
"bundled": true,
"dev": true
},
"drbg.js": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"requires": {
"browserify-aes": "^1.0.6",
"create-hash": "^1.1.2",
"create-hmac": "^1.1.4"
}
},
"elliptic": {
"version": "6.5.0",
"bundled": true,
"dev": true,
"requires": {
"bn.js": "^4.4.0",
"brorand": "^1.0.1",
"hash.js": "^1.0.0",
"hmac-drbg": "^1.0.0",
"inherits": "^2.0.1",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.0"
}
},
"emoji-regex": {
"version": "7.0.3",
"bundled": true,
"dev": true
},
"end-of-stream": {
"version": "1.4.1",
"bundled": true,
"dev": true,
"requires": {
"once": "^1.4.0"
}
},
"ethereumjs-util": {
"version": "6.1.0",
"bundled": true,
"dev": true,
"requires": {
"bn.js": "^4.11.0",
"create-hash": "^1.1.2",
"ethjs-util": "0.1.6",
"keccak": "^1.0.2",
"rlp": "^2.0.0",
"safe-buffer": "^5.1.1",
"secp256k1": "^3.0.1"
}
},
"ethjs-util": {
"version": "0.1.6",
"bundled": true,
"dev": true,
"requires": {
"is-hex-prefixed": "1.0.0",
"strip-hex-prefix": "1.0.0"
}
},
"evp_bytestokey": {
"version": "1.0.3",
"bundled": true,
"dev": true,
"requires": {
"md5.js": "^1.3.4",
"safe-buffer": "^5.1.1"
}
},
"execa": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"requires": {
"cross-spawn": "^6.0.0",
"get-stream": "^4.0.0",
"is-stream": "^1.1.0",
"npm-run-path": "^2.0.0",
"p-finally": "^1.0.0",
"signal-exit": "^3.0.0",
"strip-eof": "^1.0.0"
}
},
"file-uri-to-path": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"find-up": {
"version": "3.0.0",
"bundled": true,
"dev": true,
"requires": {
"locate-path": "^3.0.0"
}
},
"get-caller-file": {
"version": "2.0.5",
"bundled": true,
"dev": true
},
"get-stream": {
"version": "4.1.0",
"bundled": true,
"dev": true,
"requires": {
"pump": "^3.0.0"
}
},
"hash-base": {
"version": "3.0.4",
"bundled": true,
"dev": true,
"requires": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"hash.js": {
"version": "1.1.7",
"bundled": true,
"dev": true,
"requires": {
"inherits": "^2.0.3",
"minimalistic-assert": "^1.0.1"
}
},
"hmac-drbg": {
"version": "1.0.1",
"bundled": true,
"dev": true,
"requires": {
"hash.js": "^1.0.3",
"minimalistic-assert": "^1.0.0",
"minimalistic-crypto-utils": "^1.0.1"
}
},
"inherits": {
"version": "2.0.4",
"bundled": true,
"dev": true
},
"invert-kv": {
"version": "2.0.0",
"bundled": true,
"dev": true
},
"is-fullwidth-code-point": {
"version": "2.0.0",
"bundled": true,
"dev": true
},
"is-hex-prefixed": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"is-stream": {
"version": "1.1.0",
"bundled": true,
"dev": true
},
"isexe": {
"version": "2.0.0",
"bundled": true,
"dev": true
},
"keccak": {
"version": "1.4.0",
"bundled": true,
"dev": true,
"requires": {
"bindings": "^1.2.1",
"inherits": "^2.0.3",
"nan": "^2.2.1",
"safe-buffer": "^5.1.0"
}
},
"lcid": {
"version": "2.0.0",
"bundled": true,
"dev": true,
"requires": {
"invert-kv": "^2.0.0"
}
},
"locate-path": {
"version": "3.0.0",
"bundled": true,
"dev": true,
"requires": {
"p-locate": "^3.0.0",
"path-exists": "^3.0.0"
}
},
"map-age-cleaner": {
"version": "0.1.3",
"bundled": true,
"dev": true,
"requires": {
"p-defer": "^1.0.0"
}
},
"md5.js": {
"version": "1.3.5",
"bundled": true,
"dev": true,
"requires": {
"hash-base": "^3.0.0",
"inherits": "^2.0.1",
"safe-buffer": "^5.1.2"
}
},
"mem": {
"version": "4.3.0",
"bundled": true,
"dev": true,
"requires": {
"map-age-cleaner": "^0.1.1",
"mimic-fn": "^2.0.0",
"p-is-promise": "^2.0.0"
}
},
"mimic-fn": {
"version": "2.1.0",
"bundled": true,
"dev": true
},
"minimalistic-assert": {
"version": "1.0.1",
"bundled": true,
"dev": true
},
"minimalistic-crypto-utils": {
"version": "1.0.1",
"bundled": true,
"dev": true
},
"nan": {
"version": "2.14.0",
"bundled": true,
"dev": true
},
"nice-try": {
"version": "1.0.5",
"bundled": true,
"dev": true
},
"npm-run-path": {
"version": "2.0.2",
"bundled": true,
"dev": true,
"requires": {
"path-key": "^2.0.0"
}
},
"once": {
"version": "1.4.0",
"bundled": true,
"dev": true,
"requires": {
"wrappy": "1"
}
},
"os-locale": {
"version": "3.1.0",
"bundled": true,
"dev": true,
"requires": {
"execa": "^1.0.0",
"lcid": "^2.0.0",
"mem": "^4.0.0"
}
},
"p-defer": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"p-finally": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"p-is-promise": {
"version": "2.1.0",
"bundled": true,
"dev": true
},
"p-limit": {
"version": "2.2.0",
"bundled": true,
"dev": true,
"requires": {
"p-try": "^2.0.0"
}
},
"p-locate": {
"version": "3.0.0",
"bundled": true,
"dev": true,
"requires": {
"p-limit": "^2.0.0"
}
},
"p-try": {
"version": "2.2.0",
"bundled": true,
"dev": true
},
"path-exists": {
"version": "3.0.0",
"bundled": true,
"dev": true
},
"path-key": {
"version": "2.0.1",
"bundled": true,
"dev": true
},
"pump": {
"version": "3.0.0",
"bundled": true,
"dev": true,
"requires": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"require-directory": {
"version": "2.1.1",
"bundled": true,
"dev": true
},
"require-main-filename": {
"version": "2.0.0",
"bundled": true,
"dev": true
},
"ripemd160": {
"version": "2.0.2",
"bundled": true,
"dev": true,
"requires": {
"hash-base": "^3.0.0",
"inherits": "^2.0.1"
}
},
"rlp": {
"version": "2.2.3",
"bundled": true,
"dev": true,
"requires": {
"bn.js": "^4.11.1",
"safe-buffer": "^5.1.1"
}
},
"safe-buffer": {
"version": "5.2.0",
"bundled": true,
"dev": true
},
"secp256k1": {
"version": "3.7.1",
"bundled": true,
"dev": true,
"requires": {
"bindings": "^1.5.0",
"bip66": "^1.1.5",
"bn.js": "^4.11.8",
"create-hash": "^1.2.0",
"drbg.js": "^1.0.1",
"elliptic": "^6.4.1",
"nan": "^2.14.0",
"safe-buffer": "^5.1.2"
}
},
"semver": {
"version": "5.7.0",
"bundled": true,
"dev": true
},
"set-blocking": {
"version": "2.0.0",
"bundled": true,
"dev": true
},
"sha.js": {
"version": "2.4.11",
"bundled": true,
"dev": true,
"requires": {
"inherits": "^2.0.1",
"safe-buffer": "^5.0.1"
}
},
"shebang-command": {
"version": "1.2.0",
"bundled": true,
"dev": true,
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"signal-exit": {
"version": "3.0.2",
"bundled": true,
"dev": true
},
"source-map": {
"version": "0.6.1",
"bundled": true,
"dev": true
},
"source-map-support": {
"version": "0.5.12",
"bundled": true,
"dev": true,
"requires": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"string-width": {
"version": "3.1.0",
"bundled": true,
"dev": true,
"requires": {
"emoji-regex": "^7.0.1",
"is-fullwidth-code-point": "^2.0.0",
"strip-ansi": "^5.1.0"
}
},
"strip-ansi": {
"version": "5.2.0",
"bundled": true,
"dev": true,
"requires": {
"ansi-regex": "^4.1.0"
}
},
"strip-eof": {
"version": "1.0.0",
"bundled": true,
"dev": true
},
"strip-hex-prefix": {
"version": "1.0.0",
"bundled": true,
"dev": true,
"requires": {
"is-hex-prefixed": "1.0.0"
}
},
"which": {
"version": "1.3.1",
"bundled": true,
"dev": true,
"requires": {
"isexe": "^2.0.0"
}
},
"which-module": {
"version": "2.0.0",
"bundled": true,
"dev": true
},
"wrap-ansi": {
"version": "5.1.0",
"bundled": true,
"dev": true,
"requires": {
"ansi-styles": "^3.2.0",
"string-width": "^3.0.0",
"strip-ansi": "^5.0.0"
}
},
"wrappy": {
"version": "1.0.2",
"bundled": true,
"dev": true
},
"y18n": {
"version": "4.0.0",
"bundled": true,
"dev": true
},
"yargs": {
"version": "13.2.4",
"bundled": true,
"dev": true,
"requires": {
"cliui": "^5.0.0",
"find-up": "^3.0.0",
"get-caller-file": "^2.0.1",
"os-locale": "^3.1.0",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^3.0.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^13.1.0"
}
},
"yargs-parser": {
"version": "13.1.1",
"bundled": true,
"dev": true,
"requires": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
}
}
}
},
"ganache-core": {
"version": "2.10.2",
"resolved": "https://registry.npmjs.org/ganache-core/-/ganache-core-2.10.2.tgz",

View File

@ -350,6 +350,10 @@ export const borrow = async (
timestamp,
txCost
);
console.log(userDataAfter.stableBorrowRate.toFixed(), expectedUserData.stableBorrowRate.toFixed());
console.log(userDataAfter.principalStableBorrowBalance.toFixed(), expectedUserData.principalStableBorrowBalance.toFixed());
expectEqual(reserveDataAfter, expectedReserveData);
expectEqual(userDataAfter, expectedUserData);
@ -555,6 +559,7 @@ export const setUseAsCollateral = async (
export const swapBorrowRateMode = async (
reserveSymbol: string,
user: SignerWithAddress,
rateMode: string,
expectedResult: string,
testEnv: TestEnv,
revertMessage?: string
@ -570,7 +575,7 @@ export const swapBorrowRateMode = async (
);
if (expectedResult === 'success') {
const txResult = await waitForTx(await pool.connect(user.signer).swapBorrowRateMode(reserve));
const txResult = await waitForTx(await pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode));
const {txCost, txTimestamp} = await getTxCostAndTimestamp(txResult);
@ -583,6 +588,7 @@ export const swapBorrowRateMode = async (
const expectedReserveData = calcExpectedReserveDataAfterSwapRateMode(
reserveDataBefore,
userDataBefore,
rateMode,
txTimestamp
);
@ -590,6 +596,7 @@ export const swapBorrowRateMode = async (
reserveDataBefore,
expectedReserveData,
userDataBefore,
rateMode,
txCost,
txTimestamp
);
@ -607,7 +614,7 @@ export const swapBorrowRateMode = async (
// );
// });
} else if (expectedResult === 'revert') {
await expect(pool.connect(user.signer).swapBorrowRateMode(reserve), revertMessage).to.be
await expect(pool.connect(user.signer).swapBorrowRateMode(reserve, rateMode), revertMessage).to.be
.reverted;
}
};

View File

@ -45,7 +45,7 @@ const executeAction = async (
users: SignerWithAddress[],
testEnv: TestEnv
) => {
const {reserve, user: userIndex} = action.args;
const {reserve, user: userIndex, borrowRateMode} = action.args;
const {name, expected, revertMessage} = action;
if (!name || name === "") {
@ -62,6 +62,21 @@ const executeAction = async (
throw `An expected resut for action ${name} is required`;
}
let rateMode: string = RateMode.None;
if(borrowRateMode) {
if (borrowRateMode === "none") {
RateMode.None;
} else if (borrowRateMode === "stable") {
rateMode = RateMode.Stable;
} else if (borrowRateMode === "variable") {
rateMode = RateMode.Variable;
} else {
//random value, to test improper selection of the parameter
rateMode = "4";
}
}
const user = users[parseInt(userIndex)];
switch (name) {
@ -112,25 +127,12 @@ const executeAction = async (
break;
case "borrow":
{
const {amount, borrowRateMode, timeTravel} = action.args;
const {amount, timeTravel} = action.args;
if (!amount || amount === "") {
throw `Invalid amount to borrow from the ${reserve} reserve`;
}
let rateMode: string = RateMode.None;
if (borrowRateMode === "none") {
RateMode.None;
} else if (borrowRateMode === "stable") {
rateMode = RateMode.Stable;
} else if (borrowRateMode === "variable") {
rateMode = RateMode.Variable;
} else {
//random value, to test improper selection of the parameter
rateMode = "4";
}
await borrow(
reserve,
amount,
@ -152,19 +154,7 @@ const executeAction = async (
if (!amount || amount === "") {
throw `Invalid amount to repay into the ${reserve} reserve`;
}
let rateMode: string = RateMode.None;
if (borrowRateMode === "none") {
rateMode = RateMode.None;
} else if (borrowRateMode === "stable") {
rateMode = RateMode.Stable;
} else if (borrowRateMode === "variable") {
rateMode = RateMode.Variable;
} else {
//random value, to test improper selection of the parameter
rateMode = "4";
}
let userToRepayOnBehalf: SignerWithAddress;
if (!onBehalfOfIndex || onBehalfOfIndex === "") {
console.log(
@ -175,8 +165,6 @@ const executeAction = async (
userToRepayOnBehalf = users[parseInt(onBehalfOfIndex)];
}
console.log(user.address, userToRepayOnBehalf.address)
await repay(
reserve,
amount,
@ -210,7 +198,7 @@ const executeAction = async (
break;
case "swapBorrowRateMode":
await swapBorrowRateMode(reserve, user, expected, testEnv, revertMessage);
await swapBorrowRateMode(reserve, user, rateMode, expected, testEnv, revertMessage);
break;
case "rebalanceStableBorrowRate":

View File

@ -10,10 +10,11 @@
"args": {
"reserve": "DAI",
"user": "0",
"target": "1"
"target": "1",
"borrowRateMode": "variable"
},
"expected": "revert",
"revertMessage": "User does not have any borrow for this reserve"
"revertMessage": "User does not have any stable rate loan for this reserve"
}
]
},
@ -86,7 +87,8 @@
"name": "swapBorrowRateMode",
"args": {
"reserve": "DAI",
"user": "1"
"user": "1",
"borrowRateMode": "variable"
},
"expected": "success"
},

View File

@ -3,16 +3,33 @@
"description": "Test cases for the swapBorrowRateMode() function.",
"stories": [
{
"description": "User 0 tries to swap rate mode without any borrow in progress (revert expected)",
"description": "User 0 tries to swap rate mode without any variable rate loan in progress (revert expected)",
"actions": [
{
"name": "swapBorrowRateMode",
"args": {
"reserve": "DAI",
"user": "1"
"user": "1",
"borrowRateMode": "variable"
},
"expected": "revert",
"revertMessage": "User does not have a borrow in progress on this reserve"
"revertMessage": "User does not have a variable rate loan in progress on this reserve"
}
]
},
{
"description": "User 0 tries to swap rate mode without any stable rate loan in progress (revert expected)",
"actions": [
{
"name": "swapBorrowRateMode",
"args": {
"reserve": "DAI",
"user": "1",
"borrowRateMode": "stable"
},
"expected": "revert",
"revertMessage": "User does not have a stable rate loan in progress on this reserve"
}
]
},
@ -70,7 +87,8 @@
"name": "swapBorrowRateMode",
"args": {
"reserve": "DAI",
"user": "1"
"user": "1",
"borrowRateMode": "variable"
},
"expected": "success"
}
@ -94,7 +112,8 @@
"name": "swapBorrowRateMode",
"args": {
"reserve": "DAI",
"user": "1"
"user": "1",
"borrowRateMode": "stable"
},
"expected": "success"
},
@ -122,7 +141,8 @@
"reserve": "DAI",
"amount": "-1",
"user": "1",
"onBehalfOf": "1"
"onBehalfOf": "1",
"borrowRateMode": "variable"
},
"expected": "success"
}

View File

@ -326,6 +326,8 @@ export const calcExpectedReserveDataAfterBorrow = (
): ReserveData => {
const expectedReserveData = <ReserveData>{};
console.log('Computing borrow, amountBorrowed: ', amountBorrowed, ' Rate mode: ', borrowRateMode);
expectedReserveData.address = reserveDataBeforeAction.address;
const amountBorrowedBN = new BigNumber(amountBorrowed);
@ -354,8 +356,8 @@ export const calcExpectedReserveDataAfterBorrow = (
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
reserveDataBeforeAction.totalBorrowsStable,
userStableBorrowBalance.plus(amountBorrowedBN),
reserveDataBeforeAction.totalBorrowsStable.plus(debtAccrued),
amountBorrowedBN,
reserveDataBeforeAction.stableBorrowRate
);
expectedReserveData.totalBorrowsVariable = reserveDataBeforeAction.totalBorrowsVariable;
@ -417,6 +419,8 @@ export const calcExpectedReserveDataAfterRepay = (
txTimestamp: BigNumber,
currentTimestamp: BigNumber
): ReserveData => {
console.log('Computing repay, amount repaid: ', amountRepaid, ' Rate mode: ', borrowRateMode);
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
@ -551,37 +555,40 @@ export const calcExpectedUserDataAfterBorrow = (
);
if (interestRateMode == RateMode.Stable) {
expectedUserData.principalStableBorrowBalance = currentStableBorrowBalance.plus(
amountBorrowed
const debtAccrued = currentStableBorrowBalance.minus(
userDataBeforeAction.principalStableBorrowBalance
);
expectedUserData.principalVariableBorrowBalance = userDataBeforeAction.principalVariableBorrowBalance;
expectedUserData.stableBorrowRate = reserveDataBeforeAction.stableBorrowRate;
expectedUserData.principalStableBorrowBalance = currentStableBorrowBalance.plus(amountBorrowed);
expectedUserData.principalVariableBorrowBalance =
userDataBeforeAction.principalVariableBorrowBalance;
expectedUserData.stableBorrowRate = calcExpectedUserStableRate(
userDataBeforeAction.principalStableBorrowBalance.plus(debtAccrued),
userDataBeforeAction.stableBorrowRate,
new BigNumber(amountBorrowed),
reserveDataBeforeAction.stableBorrowRate
);
expectedUserData.stableRateLastUpdated = txTimestamp;
} else {
expectedUserData.principalVariableBorrowBalance = currentVariableBorrowBalance.plus(
amountBorrowed
);
expectedUserData.principalStableBorrowBalance = userDataBeforeAction.principalStableBorrowBalance;
expectedUserData.principalStableBorrowBalance =
userDataBeforeAction.principalStableBorrowBalance;
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
expectedUserData.stableBorrowRate = userDataBeforeAction.stableBorrowRate;
expectedUserData.stableRateLastUpdated = userDataBeforeAction.stableRateLastUpdated;
}
//calculate also the accrued balance after the time passed
expectedUserData.currentStableBorrowBalance = calcExpectedStableDebtTokenBalance(
{
...userDataBeforeAction,
currentStableBorrowBalance: expectedUserData.principalStableBorrowBalance,
principalStableBorrowBalance: expectedUserData.principalStableBorrowBalance,
stableBorrowRate:
interestRateMode == RateMode.Stable
? reserveDataBeforeAction.stableBorrowRate
: userDataBeforeAction.stableBorrowRate,
stableRateLastUpdated: expectedUserData.stableRateLastUpdated,
stableBorrowRate: expectedUserData.stableBorrowRate,
stableRateLastUpdated: expectedUserData.stableRateLastUpdated,
},
currentTimestamp
);
@ -595,7 +602,7 @@ export const calcExpectedUserDataAfterBorrow = (
variableBorrowIndex:
interestRateMode == RateMode.Variable
? expectedDataAfterAction.variableBorrowIndex
: userDataBeforeAction.variableBorrowIndex
: userDataBeforeAction.variableBorrowIndex,
},
currentTimestamp
);
@ -669,7 +676,6 @@ export const calcExpectedUserDataAfterRepay = (
}
if (rateMode == RateMode.Stable) {
expectedUserData.principalVariableBorrowBalance =
userDataBeforeAction.principalVariableBorrowBalance;
expectedUserData.currentVariableBorrowBalance = variableBorrowBalance;
@ -681,7 +687,9 @@ export const calcExpectedUserDataAfterRepay = (
if (expectedUserData.currentStableBorrowBalance.eq('0')) {
//user repaid everything
expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber('0');
expectedUserData.stableBorrowRate = expectedUserData.stableRateLastUpdated = new BigNumber(
'0'
);
}
} else {
expectedUserData.currentStableBorrowBalance = stableBorrowBalance;
@ -716,7 +724,7 @@ export const calcExpectedUserDataAfterRepay = (
expectedUserData.interestRedirectionAddress = userDataBeforeAction.interestRedirectionAddress;
expectedUserData.redirectionAddressRedirectedBalance =
userDataBeforeAction.redirectionAddressRedirectedBalance;
expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex;
expectedUserData.currentATokenUserIndex = userDataBeforeAction.currentATokenUserIndex;
if (user === onBehalfOf) {
//if user repaid for himself, update the wallet balances
@ -755,29 +763,27 @@ export const calcExpectedUserDataAfterSetUseAsCollateral = (
export const calcExpectedReserveDataAfterSwapRateMode = (
reserveDataBeforeAction: ReserveData,
userDataBeforeAction: UserReserveData,
rateMode: string,
txTimestamp: BigNumber
): ReserveData => {
console.log('Computing swap, Rate mode: ', rateMode);
const expectedReserveData: ReserveData = <ReserveData>{};
expectedReserveData.address = reserveDataBeforeAction.address;
let userBalanceIncrease: BigNumber = new BigNumber(0);
const variableBorrowBalance = calcExpectedVariableDebtTokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
const stableBorrowBalance = calcExpectedStableDebtTokenBalance(
userDataBeforeAction,
txTimestamp
);
const stableBorrowBalance = calcExpectedStableDebtTokenBalance(userDataBeforeAction, txTimestamp);
expectedReserveData.availableLiquidity = reserveDataBeforeAction.availableLiquidity;
if (userDataBeforeAction.borrowRateMode === RateMode.Stable) {
//swap to variable
if (rateMode === RateMode.Stable) {
//swap user stable debt to variable
const debtAccrued = stableBorrowBalance.minus(
userDataBeforeAction.principalStableBorrowBalance
);
@ -786,22 +792,27 @@ export const calcExpectedReserveDataAfterSwapRateMode = (
expectedReserveData.averageStableBorrowRate = calcExpectedAverageStableBorrowRate(
reserveDataBeforeAction.averageStableBorrowRate,
reserveDataBeforeAction.totalBorrowsStable.plus(userBalanceIncrease),
reserveDataBeforeAction.totalBorrowsStable.plus(debtAccrued),
stableBorrowBalance.negated(),
userDataBeforeAction.stableBorrowRate
);
expectedReserveData.totalBorrowsVariable = reserveDataBeforeAction.totalBorrowsVariable.plus(
stableBorrowBalance
);
} else {
const debtAccrued = stableBorrowBalance.minus(
expectedReserveData.totalBorrowsStable = reserveDataBeforeAction.totalBorrowsStable.minus(
userDataBeforeAction.principalStableBorrowBalance
);
} else {
const debtAccrued = variableBorrowBalance.minus(
userDataBeforeAction.principalVariableBorrowBalance
);
expectedReserveData.totalLiquidity = reserveDataBeforeAction.totalLiquidity.plus(debtAccrued);
expectedReserveData.totalBorrowsVariable = reserveDataBeforeAction.totalBorrowsVariable
.plus(debtAccrued)
.minus(variableBorrowBalance);
expectedReserveData.totalBorrowsVariable = reserveDataBeforeAction.totalBorrowsVariable.minus(
userDataBeforeAction.principalVariableBorrowBalance
);
expectedReserveData.totalBorrowsStable = reserveDataBeforeAction.totalBorrowsStable.plus(
variableBorrowBalance
@ -850,6 +861,7 @@ export const calcExpectedUserDataAfterSwapRateMode = (
reserveDataBeforeAction: ReserveData,
expectedDataAfterAction: ReserveData,
userDataBeforeAction: UserReserveData,
rateMode: string,
txCost: BigNumber,
txTimestamp: BigNumber
): UserReserveData => {
@ -861,16 +873,14 @@ export const calcExpectedUserDataAfterSwapRateMode = (
txTimestamp
);
const stableBorrowBalance = calcExpectedStableDebtTokenBalance(
userDataBeforeAction,
txTimestamp
);
const stableBorrowBalance = calcExpectedStableDebtTokenBalance(userDataBeforeAction, txTimestamp);
expectedUserData.currentATokenBalance = calcExpectedATokenBalance(
reserveDataBeforeAction,
userDataBeforeAction,
txTimestamp
);
expectedUserData.principalATokenBalance = userDataBeforeAction.principalATokenBalance;
expectedUserData.redirectedBalance = userDataBeforeAction.redirectedBalance;
expectedUserData.interestRedirectionAddress = userDataBeforeAction.interestRedirectionAddress;
@ -883,31 +893,38 @@ export const calcExpectedUserDataAfterSwapRateMode = (
txTimestamp
);
if (userDataBeforeAction.borrowRateMode === RateMode.Stable) {
expectedUserData.currentStableBorrowBalance = new BigNumber(0);
if (rateMode === RateMode.Stable) {
// swap to variable
expectedUserData.currentStableBorrowBalance = expectedUserData.principalStableBorrowBalance = new BigNumber(
0
);
expectedUserData.stableBorrowRate = new BigNumber(0);
expectedUserData.currentVariableBorrowBalance = userDataBeforeAction.currentVariableBorrowBalance.plus(
expectedUserData.principalVariableBorrowBalance = expectedUserData.currentVariableBorrowBalance = userDataBeforeAction.currentVariableBorrowBalance.plus(
stableBorrowBalance
);
expectedUserData.variableBorrowIndex = expectedDataAfterAction.variableBorrowIndex;
expectedUserData.stableRateLastUpdated = new BigNumber(0);
} else {
expectedUserData.currentStableBorrowBalance = userDataBeforeAction.currentStableBorrowBalance.plus(
expectedUserData.principalStableBorrowBalance = expectedUserData.currentStableBorrowBalance = userDataBeforeAction.currentStableBorrowBalance.plus(
variableBorrowBalance
);
expectedUserData.principalStableBorrowBalance = expectedUserData.currentStableBorrowBalance;
//weighted average of the previous and the current
expectedUserData.stableBorrowRate = userDataBeforeAction.currentVariableBorrowBalance
.times(userDataBeforeAction.stableBorrowRate)
.plus(variableBorrowBalance.times(reserveDataBeforeAction.stableBorrowRate))
.div(expectedUserData.currentStableBorrowBalance);
expectedUserData.currentVariableBorrowBalance = userDataBeforeAction.currentVariableBorrowBalance.plus(
stableBorrowBalance
expectedUserData.stableBorrowRate = calcExpectedUserStableRate(
userDataBeforeAction.principalStableBorrowBalance,
userDataBeforeAction.stableBorrowRate,
variableBorrowBalance,
reserveDataBeforeAction.stableBorrowRate
);
expectedUserData.stableRateLastUpdated = txTimestamp;
expectedUserData.currentVariableBorrowBalance = expectedUserData.principalVariableBorrowBalance = new BigNumber(
0
);
expectedUserData.variableBorrowIndex = expectedDataAfterAction.variableBorrowIndex;
expectedUserData.borrowRate = reserveDataBeforeAction.stableBorrowRate;
expectedUserData.variableBorrowIndex = new BigNumber(0);
}
@ -928,10 +945,7 @@ export const calcExpectedReserveDataAfterStableRateRebalance = (
expectedReserveData.address = reserveDataBeforeAction.address;
const stableBorrowBalance = calcExpectedStableDebtTokenBalance(
userDataBeforeAction,
txTimestamp
);
const stableBorrowBalance = calcExpectedStableDebtTokenBalance(userDataBeforeAction, txTimestamp);
const debtAccrued = stableBorrowBalance.minus(userDataBeforeAction.principalStableBorrowBalance);
@ -1249,7 +1263,11 @@ const calcExpectedStableDebtTokenBalance = (
stableRateLastUpdated,
} = userDataBeforeAction;
if (stableBorrowRate.eq(0) || currentTimestamp.eq(stableRateLastUpdated) || stableRateLastUpdated.eq(0)) {
if (
stableBorrowRate.eq(0) ||
currentTimestamp.eq(stableRateLastUpdated) ||
stableRateLastUpdated.eq(0)
) {
return principalStableBorrowBalance;
}
@ -1427,6 +1445,18 @@ const calcExpectedReserveNormalizedDebt = (
return debt;
};
const calcExpectedUserStableRate = (
balanceBefore: BigNumber,
rateBefore: BigNumber,
amount: BigNumber,
rateNew: BigNumber
) => {
return balanceBefore
.times(rateBefore)
.plus(amount.times(rateNew))
.div(balanceBefore.plus(amount));
};
const calcExpectedLiquidityIndex = (reserveData: ReserveData, timestamp: BigNumber) => {
//if utilization rate is 0, nothing to compound
if (reserveData.utilizationRate.eq('0')) {

View File

@ -12,7 +12,7 @@ BigNumber.config({DECIMAL_PLACES: 0, ROUNDING_MODE: BigNumber.ROUND_DOWN});
const scenarioFolder = './test/helpers/scenarios/';
const selectedScenarios: string[] = ['rebalance-stable-rate.json'];
const selectedScenarios: string[] = ['swap-rate-mode.json'];
fs.readdirSync(scenarioFolder).forEach((file) => {
if (selectedScenarios.length > 0 && !selectedScenarios.includes(file)) return;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -187,7 +187,7 @@ interface LendingPoolInterface extends Interface {
}>;
swapBorrowRateMode: TypedFunctionDescription<{
encode([_reserve]: [string]): string;
encode([_reserve, _rateMode]: [string, BigNumberish]): string;
}>;
};
@ -276,13 +276,11 @@ interface LendingPoolInterface extends Interface {
}>;
RebalanceStableBorrowRate: TypedEventDescription<{
encodeTopics([
_reserve,
_user,
_newStableRate,
_borrowBalanceIncrease,
_timestamp
]: [string | null, string | null, null, null, null]): string[];
encodeTopics([_reserve, _user, _timestamp]: [
string | null,
string | null,
null
]): string[];
}>;
RedeemUnderlying: TypedEventDescription<{
@ -313,11 +311,9 @@ interface LendingPoolInterface extends Interface {
}>;
Swap: TypedEventDescription<{
encodeTopics([_reserve, _user, _newRateMode, _newRate, _timestamp]: [
encodeTopics([_reserve, _user, _timestamp]: [
string | null,
string | null,
null,
null,
null
]): string[];
}>;
@ -598,6 +594,7 @@ export class LendingPool extends Contract {
swapBorrowRateMode(
_reserve: string,
_rateMode: BigNumberish,
overrides?: TransactionOverrides
): Promise<ContractTransaction>;
};
@ -862,6 +859,7 @@ export class LendingPool extends Contract {
swapBorrowRateMode(
_reserve: string,
_rateMode: BigNumberish,
overrides?: TransactionOverrides
): Promise<ContractTransaction>;
@ -917,8 +915,6 @@ export class LendingPool extends Contract {
RebalanceStableBorrowRate(
_reserve: string | null,
_user: string | null,
_newStableRate: null,
_borrowBalanceIncrease: null,
_timestamp: null
): EventFilter;
@ -950,8 +946,6 @@ export class LendingPool extends Contract {
Swap(
_reserve: string | null,
_user: string | null,
_newRateMode: null,
_newRate: null,
_timestamp: null
): EventFilter;
};
@ -1097,6 +1091,9 @@ export class LendingPool extends Contract {
_useAsCollateral: boolean
): Promise<BigNumber>;
swapBorrowRateMode(_reserve: string): Promise<BigNumber>;
swapBorrowRateMode(
_reserve: string,
_rateMode: BigNumberish
): Promise<BigNumber>;
};
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -134,4 +134,4 @@ const _abi = [
];
const _bytecode =
"0x608060405234801561001057600080fd5b5060405161099e38038061099e8339818101604052602081101561003357600080fd5b5051600080546001600160a01b039092166001600160a01b0319909216919091179055610939806100656000396000f3fe6080604052600436106100385760003560e01c80639e3c930914610083578063b59b28ef1461014f578063f7888aec146102d35761007e565b3661007e5761004633610320565b61007c576040805162461bcd60e51b8152602060048201526002602482015261191960f11b604482015290519081900360640190fd5b005b600080fd5b34801561008f57600080fd5b506100b6600480360360208110156100a657600080fd5b50356001600160a01b031661035c565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100fa5781810151838201526020016100e2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610139578181015183820152602001610121565b5050505090500194505050505060405180910390f35b34801561015b57600080fd5b506102836004803603604081101561017257600080fd5b81019060208101813564010000000081111561018d57600080fd5b82018360208201111561019f57600080fd5b803590602001918460208302840111640100000000831117156101c157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561021157600080fd5b82018360208201111561022357600080fd5b8035906020019184602083028401116401000000008311171561024557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506106a9945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102bf5781810151838201526020016102a7565b505050509050019250505060405180910390f35b3480156102df57600080fd5b5061030e600480360360408110156102f657600080fd5b506001600160a01b0381358116916020013516610841565b60408051918252519081900360200190f35b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061035457508115155b949350505050565b60608060008060009054906101000a90046001600160a01b03166001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ae57600080fd5b505afa1580156103c2573d6000803e3d6000fd5b505050506040513d60208110156103d857600080fd5b505160408051630240bc6b60e21b815290519192506060916001600160a01b03841691630902f1ac916004808301926000929190829003018186803b15801561042057600080fd5b505afa158015610434573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561045d57600080fd5b810190808051604051939291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82518660208202830111640100000000821117156104af57600080fd5b82525081516020918201928201910280838360005b838110156104dc5781810151838201526020016104c4565b5050505090500160405250505090506060815167ffffffffffffffff8111801561050557600080fd5b5060405190808252806020026020018201604052801561052f578160200160208202803683370190505b50905060005b825181101561069d576000846001600160a01b0316633e15014185848151811061055b57fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b031681526020019150506101406040518083038186803b1580156105aa57600080fd5b505afa1580156105be573d6000803e3d6000fd5b505050506040513d6101408110156105d557600080fd5b5061010001519050806106025760008383815181106105f057fe5b60200260200101818152505050610695565b61060a6108eb565b6001600160a01b031684838151811061061f57fe5b60200260200101516001600160a01b03161461066f576106528885848151811061064557fe5b6020026020010151610841565b83838151811061065e57fe5b602002602001018181525050610693565b876001600160a01b03163183838151811061068657fe5b6020026020010181815250505b505b600101610535565b50909350915050915091565b606080825184510267ffffffffffffffff811180156106c757600080fd5b506040519080825280602002602001820160405280156106f1578160200160208202803683370190505b50905060005b84518110156108375760005b845181101561082e57845182026107186108eb565b6001600160a01b031686838151811061072d57fe5b60200260200101516001600160a01b031614156107815786838151811061075057fe5b60200260200101516001600160a01b031631848383018151811061077057fe5b602002602001018181525050610825565b6107a686838151811061079057fe5b60200260200101516001600160a01b0316610320565b6107e7576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b61080a8784815181106107f657fe5b602002602001015187848151811061064557fe5b848383018151811061081857fe5b6020026020010181815250505b50600101610703565b506001016106f7565b5090505b92915050565b6000610855826001600160a01b0316610320565b156108e357816001600160a01b03166370a08231846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156108b057600080fd5b505afa1580156108c4573d6000803e3d6000fd5b505050506040513d60208110156108da57600080fd5b5051905061083b565b50600061083b565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee9056fea2646970667358221220a16f16f49f57c03b454cd00ccd40b73de3ab4b7744715128843b1ab47bc4873664736f6c63430006080033";
"0x608060405234801561001057600080fd5b5060405161099e38038061099e8339818101604052602081101561003357600080fd5b5051600080546001600160a01b039092166001600160a01b0319909216919091179055610939806100656000396000f3fe6080604052600436106100385760003560e01c80639e3c930914610083578063b59b28ef1461014f578063f7888aec146102d35761007e565b3661007e5761004633610320565b61007c576040805162461bcd60e51b8152602060048201526002602482015261191960f11b604482015290519081900360640190fd5b005b600080fd5b34801561008f57600080fd5b506100b6600480360360208110156100a657600080fd5b50356001600160a01b031661035c565b604051808060200180602001838103835285818151815260200191508051906020019060200280838360005b838110156100fa5781810151838201526020016100e2565b50505050905001838103825284818151815260200191508051906020019060200280838360005b83811015610139578181015183820152602001610121565b5050505090500194505050505060405180910390f35b34801561015b57600080fd5b506102836004803603604081101561017257600080fd5b81019060208101813564010000000081111561018d57600080fd5b82018360208201111561019f57600080fd5b803590602001918460208302840111640100000000831117156101c157600080fd5b919080806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250929594936020810193503591505064010000000081111561021157600080fd5b82018360208201111561022357600080fd5b8035906020019184602083028401116401000000008311171561024557600080fd5b9190808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152509295506106a9945050505050565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156102bf5781810151838201526020016102a7565b505050509050019250505060405180910390f35b3480156102df57600080fd5b5061030e600480360360408110156102f657600080fd5b506001600160a01b0381358116916020013516610841565b60408051918252519081900360200190f35b6000813f7fc5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a47081811480159061035457508115155b949350505050565b60608060008060009054906101000a90046001600160a01b03166001600160a01b0316630261bf8b6040518163ffffffff1660e01b815260040160206040518083038186803b1580156103ae57600080fd5b505afa1580156103c2573d6000803e3d6000fd5b505050506040513d60208110156103d857600080fd5b505160408051630240bc6b60e21b815290519192506060916001600160a01b03841691630902f1ac916004808301926000929190829003018186803b15801561042057600080fd5b505afa158015610434573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f19168201604052602081101561045d57600080fd5b810190808051604051939291908464010000000082111561047d57600080fd5b90830190602082018581111561049257600080fd5b82518660208202830111640100000000821117156104af57600080fd5b82525081516020918201928201910280838360005b838110156104dc5781810151838201526020016104c4565b5050505090500160405250505090506060815167ffffffffffffffff8111801561050557600080fd5b5060405190808252806020026020018201604052801561052f578160200160208202803683370190505b50905060005b825181101561069d576000846001600160a01b0316633e15014185848151811061055b57fe5b60200260200101516040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b031681526020019150506101406040518083038186803b1580156105aa57600080fd5b505afa1580156105be573d6000803e3d6000fd5b505050506040513d6101408110156105d557600080fd5b5061010001519050806106025760008383815181106105f057fe5b60200260200101818152505050610695565b61060a6108eb565b6001600160a01b031684838151811061061f57fe5b60200260200101516001600160a01b03161461066f576106528885848151811061064557fe5b6020026020010151610841565b83838151811061065e57fe5b602002602001018181525050610693565b876001600160a01b03163183838151811061068657fe5b6020026020010181815250505b505b600101610535565b50909350915050915091565b606080825184510267ffffffffffffffff811180156106c757600080fd5b506040519080825280602002602001820160405280156106f1578160200160208202803683370190505b50905060005b84518110156108375760005b845181101561082e57845182026107186108eb565b6001600160a01b031686838151811061072d57fe5b60200260200101516001600160a01b031614156107815786838151811061075057fe5b60200260200101516001600160a01b031631848383018151811061077057fe5b602002602001018181525050610825565b6107a686838151811061079057fe5b60200260200101516001600160a01b0316610320565b6107e7576040805162461bcd60e51b815260206004820152600d60248201526c24a72b20a624a22faa27a5a2a760991b604482015290519081900360640190fd5b61080a8784815181106107f657fe5b602002602001015187848151811061064557fe5b848383018151811061081857fe5b6020026020010181815250505b50600101610703565b506001016106f7565b5090505b92915050565b6000610855826001600160a01b0316610320565b156108e357816001600160a01b03166370a08231846040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b1580156108b057600080fd5b505afa1580156108c4573d6000803e3d6000fd5b505050506040513d60208110156108da57600080fd5b5051905061083b565b50600061083b565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee9056fea2646970667358221220690f7ecb9ab912f052e8d44a9a4f27007b3b6f0119cdc6270033c06dbc83a4e664736f6c63430006080033";