Updates to the VariableDebtToken spec

This commit is contained in:
pistiner 2020-11-22 22:20:43 +02:00
parent 5ad4182508
commit dd0e3064e3
2 changed files with 88 additions and 87 deletions

View File

@ -1,10 +1,7 @@
using LendingPoolHarnessForVariableDebtToken as POOL using LendingPoolHarnessForVariableDebtToken as POOL
/** /**
TotalSupply is the sum of all users balances Checks that each possible opertaion changes the balance of at most one user.
totalSupply(t) = Σaddress u. balanceOf(u,t)
Check that each possible opertaion changes the balance of at most one user
*/ */
rule balanceOfChange(address a, address b, method f) rule balanceOfChange(address a, address b, method f)
{ {
@ -22,10 +19,10 @@ rule balanceOfChange(address a, address b, method f)
assert (balanceABefore == balanceAAfter || balanceBBefore == balanceBAfter); assert (balanceABefore == balanceAAfter || balanceBBefore == balanceBAfter);
} }
/* /**
Check that the changed to total supply is coherent with the changes to balance Checks that the change to total supply is coherent with the change to the balance due to an operation
(which is neither a burn nor a mint).
*/ */
rule integirtyBalanceOfTotalSupply(address a, method f) rule integirtyBalanceOfTotalSupply(address a, method f)
{ {
env e; env e;
@ -36,17 +33,17 @@ rule integirtyBalanceOfTotalSupply(address a, method f )
calldataarg arg; calldataarg arg;
sinvoke f(e, arg); sinvoke f(e, arg);
require (f.selector != burn(address, uint256, uint256).selector && require (f.selector != burn(address, uint256, uint256).selector &&
f.selector != mint(address, uint256, uint256).selector ) ; f.selector != mint(address, address, uint256, uint256).selector);
uint256 balanceAAfter = balanceOf(e, a); uint256 balanceAAfter = balanceOf(e, a);
uint256 totalSupplyAfter = totalSupply(e); uint256 totalSupplyAfter = totalSupply(e);
assert (balanceAAfter != balanceABefore => ( balanceAAfter - balanceABefore == totalSupplyAfter - totalSupplyBefore)); assert (balanceAAfter != balanceABefore => ( balanceAAfter - balanceABefore == totalSupplyAfter - totalSupplyBefore));
} }
/* Burn behaves deferently and due to accumulation errors might hace less total supply then the balance /**
Checks that the change to total supply is coherent with the change to the balance due to a burn operation.
*/ */
rule integirtyBalanceOfTotalSupplyOnBurn(address a)
rule integirtyBalanceOfTotalSupplyOnBurn(address a, method f )
{ {
env e; env e;
@ -62,64 +59,72 @@ rule integirtyBalanceOfTotalSupplyOnBurn(address a, method f )
assert (balanceAAfter != balanceABefore => (balanceAAfter - balanceABefore == totalSupplyAfter - totalSupplyBefore)); assert (balanceAAfter != balanceABefore => (balanceAAfter - balanceABefore == totalSupplyAfter - totalSupplyBefore));
} }
rule integirtyBalanceOfTotalSupplyOnMint(address a, method f ) /**
Checks that the change to total supply is coherent with the change to the balance due to a mint operation.
*/
rule integirtyBalanceOfTotalSupplyOnMint(address u, address delegatedUser)
{ {
env e; env e;
uint256 balanceABefore = balanceOf(e, a); uint256 balanceUBefore = balanceOf(e, u);
uint256 totalSupplyBefore = totalSupply(e); uint256 totalSupplyBefore = totalSupply(e);
uint256 x; uint256 x;
address asset; address asset;
uint256 index = POOL.getReserveNormalizedVariableDebt(e, asset); uint256 index = POOL.getReserveNormalizedVariableDebt(e, asset);
sinvoke mint(e, a, x, index); sinvoke mint(e, delegatedUser, u, x, index);
uint256 balanceAAfter = balanceOf(e, a); uint256 balanceUAfter = balanceOf(e, u);
uint256 totalSupplyAfter = totalSupply(e); uint256 totalSupplyAfter = totalSupply(e);
assert (balanceAAfter != balanceABefore => ( balanceAAfter - balanceABefore == totalSupplyAfter - totalSupplyBefore)); assert (balanceUAfter != balanceUBefore => (balanceUAfter - balanceUBefore == totalSupplyAfter - totalSupplyBefore));
} }
/** /**
Minting an amount of x tokens for user u increases their balance by x, up to rounding errors. Minting an amount of x tokens for user u increases her balance by x, up to rounding errors.
{ b = balanceOf(u,t) } { b = balanceOf(u,t) }
mint(u,x,index) mint(delegatedUser, u, x, index)
{ balanceOf(u,t) = b + x } { balanceOf(u,t) = b + x }.
Also, if the minting is done by a user delegatedUser different than u, the balance of delegatedUser
remains unchanged.
*/ */
rule integrityMint(address a, uint256 x) { rule integrityMint(address u, address delegatedUser, uint256 x) {
env e; env e;
address asset; address asset;
uint256 index = POOL.getReserveNormalizedVariableDebt(e,asset); uint256 index = POOL.getReserveNormalizedVariableDebt(e,asset);
uint256 balancebefore = balanceOf(e, a); uint256 balanceUBefore = balanceOf(e, u);
sinvoke mint(e, a, x, index); uint256 balanceDelegatedUBefore = balanceOf(e, delegatedUser);
sinvoke mint(e, delegatedUser, u, x, index);
uint256 balanceAfter = balanceOf(e, a); uint256 balanceUAfter = balanceOf(e, u);
assert balanceAfter == balancebefore+x; uint256 balanceDelegatedUAfter = balanceOf(e, delegatedUser);
assert balanceUAfter == balanceUBefore + x && (u != delegatedUser => (balanceDelegatedUAfter == balanceDelegatedUBefore));
} }
/** /**
Mint is additive, can performed either all at once or gradually Mint is additive, namely it can performed either all at once or gradually:
mint(u,x); mint(u,y) ~ mint(u,x+y) at the same timestamp mint(delegatedUser, u, x, index); mint(delegatedUser, u, y, index) ~ mint(delegatedUser, u, x+y, index) at the same timestamp.
*/ */
rule additiveMint(address a, uint256 x, uint256 y) { rule additiveMint(address a, address delegatedUser, uint256 x, uint256 y) {
env e; env e;
address asset; address asset;
uint256 index = POOL.getReserveNormalizedVariableDebt(e, asset); uint256 index = POOL.getReserveNormalizedVariableDebt(e, asset);
storage initialStorage = lastStorage; storage initialStorage = lastStorage;
sinvoke mint(e, a, x, index); sinvoke mint(e, delegatedUser, a, x, index);
sinvoke mint(e, a, y, index); sinvoke mint(e, delegatedUser, a, y, index);
uint256 balanceScenario1 = balanceOf(e, a); uint256 balanceScenario1 = balanceOf(e, a);
uint t = x + y; uint256 t = x + y;
sinvoke mint(e, a, t ,index) at initialStorage; sinvoke mint(e, delegatedUser, a, t ,index) at initialStorage;
uint256 balanceScenario2 = balanceOf(e, a); uint256 balanceScenario2 = balanceOf(e, a);
assert balanceScenario1 == balanceScenario2, "mint is not additive"; assert balanceScenario1 == balanceScenario2, "mint is not additive";
} }
/** /**
Transfer of x amount of tokens from user u where receiver is user u Burning an amount of x tokens for user u decreases her balance by x, up to rounding errors.
{ bu = balanceOf(u) } { bu = balanceOf(u) }
burn(u, u, x) burn(u, x)
{balanceOf(u) = bu - x } { balanceOf(u) = bu - x }.
*/ */
rule integrityBurn(address a, uint256 x) { rule integrityBurn(address a, uint256 x) {
env e; env e;
@ -132,9 +137,8 @@ rule integrityBurn(address a, uint256 x) {
assert balanceAfter == balancebefore - x; assert balanceAfter == balancebefore - x;
} }
/** /**
Minting is additive, i.e., it can be performed either all at once or in steps. Minting is additive, i.e., it can be performed either all at once or in steps:
burn(u, x); burn(u, y) ~ burn(u, x+y) at the same timestamp.
burn(u, u, x); burn(u, u, y) ~ burn(u, u, x+y)
*/ */
rule additiveBurn(address a, uint256 x, uint256 y) { rule additiveBurn(address a, uint256 x, uint256 y) {
env e; env e;
@ -144,7 +148,7 @@ rule additiveBurn(address a, uint256 x, uint256 y) {
sinvoke burn(e, a, x, index); sinvoke burn(e, a, x, index);
sinvoke burn(e, a, y, index); sinvoke burn(e, a, y, index);
uint256 balanceScenario1 = balanceOf(e, a); uint256 balanceScenario1 = balanceOf(e, a);
uint t = x + y; uint256 t = x + y;
sinvoke burn(e, a, t ,index) at initialStorage; sinvoke burn(e, a, t ,index) at initialStorage;
uint256 balanceScenario2 = balanceOf(e, a); uint256 balanceScenario2 = balanceOf(e, a);
@ -152,22 +156,19 @@ rule additiveBurn(address a, uint256 x, uint256 y) {
} }
/** /**
Minting and burning are inverse operations. Minting and burning are inverse operations:
{ bu = balanceOf(u) } { bu = balanceOf(u) }
mint(u,x); burn(u, u, x) mint(u,x); burn(u, u, x)
{balanceOf(u) = bu } { balanceOf(u) = bu }.
*/ */
rule inverseMintBurn(address a, uint256 x) { rule inverseMintBurn(address a, uint256 x) {
env e; env e;
address asset; address asset;
address delegatedUser;
uint256 index = POOL.getReserveNormalizedVariableDebt(e, asset); uint256 index = POOL.getReserveNormalizedVariableDebt(e, asset);
uint256 balancebefore = balanceOf(e, a); uint256 balancebefore = balanceOf(e, a);
sinvoke mint(e, a, x, index); sinvoke mint(e, delegatedUser, a, x, index);
sinvoke burn(e, a, x, index); sinvoke burn(e, a, x, index);
uint256 balanceAfter = balanceOf(e, a); uint256 balanceAfter = balanceOf(e, a);
assert balancebefore == balanceAfter, "burn is not inverse of mint"; assert balancebefore == balanceAfter, "burn is not the inverse of mint";
} }