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

Fix MesonStates._removeExpiredSwaps() #13

Merged
merged 1 commit into from
Dec 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
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
27 changes: 27 additions & 0 deletions contracts/test/MesonStatesTest.sol
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
// SPDX-License-Identifier: MIT
pragma solidity =0.8.6;

import "../libraries/List.sol";
import "../utils/MesonHelpers.sol";
import "../utils/MesonStates.sol";

contract MesonStatesTest is MesonStates {
using List for List.Bytes32List;

constructor(address token) {
_addTokenToSwapList(token);
}
Expand All @@ -15,4 +19,27 @@ contract MesonStatesTest is MesonStates {
function decreaseSupply(address token, uint256 amount) public {
_decreaseSupply(token, amount);
}

function updateDemand(address token, uint256 metaAmount) public {
_updateDemand(token, metaAmount);
}

function removeExpiredSwaps(address token) public {
_removeExpiredSwaps(token);
}

function addRecentSwap(address token, bytes32 id, uint256 metaAmount, uint256 ts) public {
Swap memory swap = Swap(id, metaAmount, ts);
_recentSwaps[token][id] = swap;
_recentSwapLists[token].addItem(id);
_tokenDemand[token] = LowGasSafeMath.add(_tokenDemand[token], metaAmount);
}

function getRecentSwap(address token, bytes32 id) public view returns (Swap memory) {
return _recentSwaps[token][id];
}

function getRecentSwapList(address token) public view returns (List.Bytes32List memory) {
return _recentSwapLists[token];
}
}
14 changes: 6 additions & 8 deletions contracts/utils/MesonStates.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ contract MesonStates is MesonHelpers {

mapping(address => bool) public supportedTokens;

mapping(address => mapping(bytes32 => Swap)) private _swaps;
mapping(address => List.Bytes32List) private _recentSwapLists;
mapping(address => mapping(bytes32 => Swap)) internal _recentSwaps;
mapping(address => List.Bytes32List) internal _recentSwapLists;

mapping(address => uint256) internal _tokenSupply;
mapping(address => uint256) internal _tokenDemand;
Expand Down Expand Up @@ -60,7 +60,7 @@ contract MesonStates is MesonHelpers {
uint256 ts = block.timestamp;
bytes32 id = keccak256(abi.encodePacked(ts, token, metaAmount)); // TODO something else
Swap memory swap = Swap(id, metaAmount, ts);
_swaps[token][id] = swap;
_recentSwaps[token][id] = swap;
_recentSwapLists[token].addItem(id);
_tokenDemand[token] = LowGasSafeMath.add(_tokenDemand[token], metaAmount);
}
Expand All @@ -72,15 +72,13 @@ contract MesonStates is MesonHelpers {
List.Bytes32List storage list = _recentSwapLists[token];

(bool success, bytes32 id) = list.getTail();
if (!success) return; // list is empty, ignore

while (_swaps[token][id].ts + TOTAL_DEMAND_CALC_PERIOD < current) {
while (success && (_recentSwaps[token][id].ts + TOTAL_DEMAND_CALC_PERIOD < current)) {
_tokenDemand[token] = LowGasSafeMath.sub(
_tokenDemand[token],
_swaps[token][id].metaAmount
_recentSwaps[token][id].metaAmount
);
list.popItem();
delete _swaps[token][id];
delete _recentSwaps[token][id];
(success, id) = list.getTail();
}
}
Expand Down
62 changes: 62 additions & 0 deletions test/MesonStates.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,66 @@ describe('MesonStates', () => {
await expect(contract.decreaseSupply(token, 200)).to.be.revertedWith('overdrawn')
})
})

describe('#updateDemand', () => {
it('update demand', async () => {
await contract.updateDemand(token, 100)

// Verify it's added to the list
const list = await contract.getRecentSwapList(token)
expect(list._items).has.lengthOf(1)
// Verify it's added to the mapping
const swap = await contract.getRecentSwap(token, list._items[0])
expect(swap.id).to.not.equal(0)
// Verify demand/supply
expect(await contract.totalDemandFor(token)).to.equal(100);
expect(await contract.totalSupplyFor(token)).to.equal(0);
})
})

describe('#removeExpiredSwaps', () => {
const id0 = '0x0000000000000000000000000000000000000000000000000000000000000000';
const id1 = "0x464f9a206dee56c06e8f668bc1933f6286aa952f7cea9d677e18b5f089555fa1";
const id2 = "0x464f9a206dee56c06e8f668bc1933f6286aa952f7cea9d677e18b5f089555fa2";
const amount = 100;
const expiredTs = 1;
const validTs = Math.floor(Date.now() / 1000);

async function verifySwapRecords(remainingIds: string[], removedIds: string[]) {
const list = await contract.getRecentSwapList(token)
expect(list._length).to.equal(remainingIds.length)
// TODO: removed ones should be GCed
expect(list._items).has.lengthOf(remainingIds.length + removedIds.length)
for (const id of remainingIds) {
expect((await contract.getRecentSwap(token, id)).id).to.equal(id)
}
for (const id of removedIds) {
expect((await contract.getRecentSwap(token, id)).id).to.equal(id0)
}
}

it('remove expired with no swap request', async () => {
await contract.removeExpiredSwaps(token)
await verifySwapRecords([], [])
})

it('remove expired with one expired request', async () => {
await contract.addRecentSwap(token, id1, amount, expiredTs)
await contract.removeExpiredSwaps(token)
await verifySwapRecords([], [id1])
})

it('remove expired with one non-expired request', async () => {
await contract.addRecentSwap(token, id1, amount, validTs)
await contract.removeExpiredSwaps(token)
await verifySwapRecords([id1], [])
})

it('remove expired with one expired and one non-expired requests', async () => {
await contract.addRecentSwap(token, id1, amount, expiredTs)
await contract.addRecentSwap(token, id2, amount, validTs)
await contract.removeExpiredSwaps(token)
await verifySwapRecords([id2], [id1])
})
})
})