codex-contracts-eth/contracts/Collateral.sol

73 lines
1.9 KiB
Solidity
Raw Normal View History

2022-02-14 14:47:01 +00:00
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "./AccountLocks.sol";
2022-02-14 14:47:01 +00:00
contract Collateral is AccountLocks {
2022-02-14 14:47:01 +00:00
IERC20 private immutable token;
2022-02-14 15:43:56 +00:00
Totals private totals;
2022-02-14 14:47:01 +00:00
mapping(address => uint256) private balances;
2022-02-14 15:19:47 +00:00
constructor(IERC20 _token) invariant {
2022-02-14 14:47:01 +00:00
token = _token;
}
function balanceOf(address account) public view returns (uint256) {
return balances[account];
}
function add(address account, uint256 amount) private {
balances[account] += amount;
totals.balance += amount;
}
function subtract(address account, uint256 amount) private {
balances[account] -= amount;
totals.balance -= amount;
}
function transferFrom(address sender, uint256 amount) private {
address receiver = address(this);
require(token.transferFrom(sender, receiver, amount), "Transfer failed");
}
2022-02-14 15:19:47 +00:00
function deposit(uint256 amount) public invariant {
transferFrom(msg.sender, amount);
2022-02-14 15:43:56 +00:00
totals.deposited += amount;
add(msg.sender, amount);
2022-02-14 15:43:56 +00:00
}
function withdraw() public invariant {
_unlockAccount();
uint256 amount = balanceOf(msg.sender);
2022-02-14 15:43:56 +00:00
totals.withdrawn += amount;
subtract(msg.sender, amount);
2022-02-14 15:43:56 +00:00
assert(token.transfer(msg.sender, amount));
2022-02-14 15:19:47 +00:00
}
2022-02-14 16:19:00 +00:00
function _slash(address account, uint256 percentage) internal invariant {
uint256 amount = (balanceOf(account) * percentage) / 100;
totals.slashed += amount;
subtract(account, amount);
}
2022-02-14 15:19:47 +00:00
modifier invariant() {
2022-02-14 15:43:56 +00:00
Totals memory oldTotals = totals;
2022-02-14 15:19:47 +00:00
_;
2022-02-14 15:43:56 +00:00
assert(totals.deposited >= oldTotals.deposited);
assert(totals.withdrawn >= oldTotals.withdrawn);
2022-02-14 16:19:00 +00:00
assert(totals.slashed >= oldTotals.slashed);
assert(
totals.deposited == totals.balance + totals.withdrawn + totals.slashed
);
2022-02-14 15:43:56 +00:00
}
struct Totals {
uint256 balance;
uint256 deposited;
uint256 withdrawn;
2022-02-14 16:19:00 +00:00
uint256 slashed;
2022-02-14 14:47:01 +00:00
}
}