文件 1 的 20:Address.sol
pragma solidity >=0.6.2 <0.8.0;
library Address {
function isContract(address account) internal view returns (bool) {
uint256 size;
assembly { size := extcodesize(account) }
return size > 0;
}
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{ value: amount }("");
require(success, "Address: unable to send value, recipient may have reverted");
}
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{ value: value }(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
require(isContract(target), "Address: delegate call to non-contract");
(bool success, bytes memory returndata) = target.delegatecall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
if (success) {
return returndata;
} else {
if (returndata.length > 0) {
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
文件 2 的 20:Context.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this;
return msg.data;
}
}
文件 3 的 20:DELTAToken.sol
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
import "../libs/Context.sol";
import "../../interfaces/IOVLBalanceHandler.sol";
import "../../interfaces/IOVLTransferHandler.sol";
import "../../interfaces/IOVLVestingCalculator.sol";
import "../../interfaces/IRebasingLiquidityToken.sol";
import "../../interfaces/IWETH.sol";
import "./Common/OVLBase.sol";
import "../../common/OVLTokenTypes.sol";
import "./Handlers/post_first_rebasing/OVLTransferHandler.sol";
import "./Handlers/post_first_rebasing/OVLBalanceHandler.sol";
import "./Handlers/pre_first_rebasing/OVLLPRebasingHandler.sol";
import "./Handlers/pre_first_rebasing/OVLLPRebasingBalanceHandler.sol";
contract DELTAToken is OVLBase, Context, IERC20 {
using SafeMath for uint256;
using Address for address;
address public governance;
address public tokenTransferHandler;
address public rebasingLPAddress;
address public tokenBalanceHandler;
address public pendingGovernance;
string private constant NAME = "DELTA.financial - deep DeFi derivatives";
string private constant SYMBOL = "DELTA";
uint8 private constant DECIMALS = 18;
uint256 private constant TOTAL_SUPPLY = 45_000_000e18;
address private constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
address private constant BURNER = 0xDeaDbeefdEAdbeefdEadbEEFdeadbeEFdEaDbeeF;
address private constant LSW_ADDRESS = 0xdaFCE5670d3F67da9A3A44FE6bc36992e5E2beaB;
address private constant UNISWAP_V2_ROUTER = 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D;
address private immutable tokenBalanceHandlerMain;
address private immutable tokenTransferHandlerMain;
address immutable public _PAIR_ADDRESS;
constructor (address rebasingLP, address multisig, address dfv) {
require(address(this) < WETH_ADDRESS, "DELTAToken: Invalid Token Address");
require(multisig != address(0));
require(dfv != address(0));
require(rebasingLP != address(0));
address uniswapPair = address(uint(keccak256(abi.encodePacked(
hex'ff',
0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f,
keccak256(abi.encodePacked(address(this), WETH_ADDRESS)),
hex'96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f'
))));
governance = msg.sender;
_PAIR_ADDRESS = uniswapPair;
setNoVestingWhitelist(uniswapPair, true);
setNoVestingWhitelist(BURNER, true);
setNoVestingWhitelist(rebasingLP, true);
setNoVestingWhitelist(UNISWAP_V2_ROUTER, true);
setWhitelists(multisig, true, true, true);
setFullSenderWhitelist(LSW_ADDRESS, true);
governance = multisig;
rebasingLPAddress = rebasingLP;
_provideInitialSupply(LSW_ADDRESS, TOTAL_SUPPLY);
address transferHandler = address(new OVLTransferHandler(uniswapPair, dfv));
tokenTransferHandlerMain = transferHandler;
tokenBalanceHandlerMain = address(new OVLBalanceHandler(IOVLTransferHandler(transferHandler), IERC20(uniswapPair)));
tokenTransferHandler = address(new OVLLPRebasingHandler(uniswapPair));
tokenBalanceHandler = address(new OVLLPRebasingBalanceHandler());
}
function activatePostFirstRebasingState() public isGovernance() {
require(distributor != address(0), "Set the distributor first!");
tokenTransferHandler = tokenTransferHandlerMain;
tokenBalanceHandler = tokenBalanceHandlerMain;
}
function name() public pure returns (string memory) {
return NAME;
}
function symbol() public pure returns (string memory) {
return SYMBOL;
}
function decimals() public pure returns (uint8) {
return DECIMALS;
}
function totalSupply() public view override returns (uint256) {
return TOTAL_SUPPLY - balanceOf(BURNER);
}
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
function matureAllTokensOf(UserInformation storage ui, address account) internal {
delete vestingTransactions[account];
ui.maturedBalance = ui.maxBalance;
}
function setFullSenderWhitelist(address account, bool canSendToMatureBalances) public isGovernance() {
UserInformation storage ui = _userInformation[account];
matureAllTokensOf(ui,account);
ui.fullSenderWhitelisted = canSendToMatureBalances;
}
function setImmatureRecipentWhitelist(address account, bool canRecieveImmatureBalances) public isGovernance() {
UserInformation storage ui = _userInformation[account];
matureAllTokensOf(ui,account);
ui.immatureReceiverWhitelisted = canRecieveImmatureBalances;
}
function setNoVestingWhitelist(address account, bool recievesBalancesWithoutVestingProcess) public isGovernance() {
UserInformation storage ui = _userInformation[account];
matureAllTokensOf(ui,account);
ui.noVestingWhitelisted = recievesBalancesWithoutVestingProcess;
}
function setWhitelists(address account, bool canSendToMatureBalances, bool canRecieveImmatureBalances, bool recievesBalancesWithoutVestingProcess) public isGovernance() {
UserInformation storage ui = _userInformation[account];
matureAllTokensOf(ui,account);
ui.noVestingWhitelisted = recievesBalancesWithoutVestingProcess;
ui.immatureReceiverWhitelisted = canRecieveImmatureBalances;
ui.fullSenderWhitelisted = canSendToMatureBalances;
}
function performLiquidityRebasing() public {
onlyRLP();
liquidityRebasingPermitted = true;
IRebasingLiquidityToken(rebasingLPAddress).tokenCaller();
liquidityRebasingPermitted = false;
lpTokensInPair = IERC20(_PAIR_ADDRESS).balanceOf(_PAIR_ADDRESS);
}
function adjustBalanceOfNoVestingAccount(address account, uint256 amount, bool isAddition) public {
onlyRLP();
UserInformation storage ui = _userInformation[account];
require(ui.noVestingWhitelisted, "Account is a vesting address");
if(isAddition) {
ui.maxBalance = ui.maxBalance.add(amount);
ui.maturedBalance = ui.maturedBalance.add(amount);
} else {
ui.maxBalance = amount;
ui.maturedBalance = amount;
}
}
function onlyRLP() internal view {
require(msg.sender == rebasingLPAddress, "DELTAToken: Only Rebasing LP contract can call this function");
}
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
bytes memory callData = abi.encodeWithSelector(IOVLTransferHandler.handleTransfer.selector, sender, recipient, amount);
(bool success, bytes memory result) = tokenTransferHandler.delegatecall(callData);
if (!success) {
revert(_getRevertMsg(result));
}
}
function balanceOf(address account) public view override returns (uint256) {
return IOVLBalanceHandler(tokenBalanceHandler).handleBalanceCalculations(account, msg.sender);
}
function _provideInitialSupply(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: supplying zero address");
UserInformation storage ui = _userInformation[account];
ui.maturedBalance = ui.maturedBalance.add(amount);
ui.maxBalance = ui.maxBalance.add(amount);
emit Transfer(address(0), account, amount);
}
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
function setDistributor(address _newDistributor) public isGovernance() {
distributor = _newDistributor;
setWhitelists(_newDistributor, true, true, true);
}
function setPendingGovernance(address _newGov) public isGovernance() {
pendingGovernance = _newGov;
}
function acceptGovernance() public {
require(msg.sender == pendingGovernance);
governance = msg.sender;
setWhitelists(msg.sender, true, true, true);
delete pendingGovernance;
}
function setBalanceCalculator(address _newBalanceCalculator) public isGovernance() {
tokenBalanceHandler = _newBalanceCalculator;
}
function setTokenTransferHandler(address _newHandler) public isGovernance() {
tokenTransferHandler = _newHandler;
}
function _getRevertMsg(bytes memory _returnData) internal pure returns (string memory) {
if (_returnData.length < 68) return 'Transaction reverted silently';
assembly {
_returnData := add(_returnData, 0x04)
}
return abi.decode(_returnData, (string));
}
function totalsForWallet(address account) public view returns (WalletTotals memory totals) {
uint256 mature = _userInformation[account].maturedBalance;
uint256 immature;
for(uint256 i = 0; i < QTY_EPOCHS; i++) {
uint256 amount = vestingTransactions[account][i].amount;
uint256 matureTxBalance = IOVLVestingCalculator(tokenBalanceHandler).getMatureBalance(vestingTransactions[account][i], block.timestamp);
mature = mature.add(matureTxBalance);
immature = immature.add(amount.sub(matureTxBalance));
}
totals.mature = mature;
totals.immature = immature;
totals.total = mature.add(immature);
}
function getUserInfo(address user) external view returns (UserInformationLite memory) {
UserInformation storage info = _userInformation[user];
return UserInformationLite(info.maturedBalance, info.maxBalance, info.mostMatureTxIndex, info.lastInTxIndex);
}
modifier isGovernance() {
_isGovernance();
_;
}
function _isGovernance() private view {
require(msg.sender == governance, "!gov");
}
function getTransactionDetail(VestingTransaction memory _tx) public view returns (VestingTransactionDetailed memory dtx) {
return IOVLVestingCalculator(tokenBalanceHandler).getTransactionDetails(_tx, block.timestamp);
}
function userInformation(address user) external view returns (UserInformation memory) {
return _userInformation[user];
}
}
文件 4 的 20:IDeltaDistributor.sol
pragma solidity ^0.7.6;
interface IDeltaDistributor {
function creditUser(address,uint256) external;
function addDevested(address, uint256) external;
function distribute() external;
}
文件 5 的 20:IDeltaToken.sol
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "../common/OVLTokenTypes.sol";
interface IDeltaToken is IERC20 {
function vestingTransactions(address, uint256) external view returns (VestingTransaction memory);
function getUserInfo(address) external view returns (UserInformationLite memory);
function getMatureBalance(address, uint256) external view returns (uint256);
function liquidityRebasingPermitted() external view returns (bool);
function lpTokensInPair() external view returns (uint256);
function governance() external view returns (address);
function performLiquidityRebasing() external;
function distributor() external view returns (address);
function totalsForWallet(address ) external view returns (WalletTotals memory totals);
function adjustBalanceOfNoVestingAccount(address, uint256,bool) external;
function userInformation(address user) external view returns (UserInformation memory);
}
文件 6 的 20:IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
interface IERC20 {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 7 的 20:IERC20Upgradeable.sol
pragma solidity ^0.7.0;
interface IERC20Upgradeable {
function totalSupply() external view returns (uint256);
function balanceOf(address account) external view returns (uint256);
function transfer(address recipient, uint256 amount) external returns (bool);
function allowance(address owner, address spender) external view returns (uint256);
function approve(address spender, uint256 amount) external returns (bool);
function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
文件 8 的 20:IOVLBalanceHandler.sol
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
interface IOVLBalanceHandler {
function handleBalanceCalculations(address, address) external view returns (uint256);
}
文件 9 的 20:IOVLTransferHandler.sol
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
interface IOVLTransferHandler {
function handleTransfer(address sender, address recipient, uint256 amount) external;
}
文件 10 的 20:IOVLVestingCalculator.sol
pragma solidity ^0.7.6;
pragma abicoder v2;
import "../common/OVLTokenTypes.sol";
interface IOVLVestingCalculator {
function getTransactionDetails(VestingTransaction memory _tx) external view returns (VestingTransactionDetailed memory dtx);
function getTransactionDetails(VestingTransaction memory _tx, uint256 _blockTimestamp) external pure returns (VestingTransactionDetailed memory dtx);
function getMatureBalance(VestingTransaction memory _tx, uint256 _blockTimestamp) external pure returns (uint256 mature);
function calculateTransactionDebit(VestingTransactionDetailed memory dtx, uint256 matureAmountNeeded, uint256 currentTimestamp) external pure returns (uint256 outputDebit);
}
文件 11 的 20:IRebasingLiquidityToken.sol
pragma experimental ABIEncoderV2;
pragma solidity ^0.7.6;
import "./IERC20Upgradeable.sol";
interface IRebasingLiquidityToken is IERC20Upgradeable {
function tokenCaller() external;
function reserveCaller(uint256,uint256) external;
function wrapWithReturn() external returns (uint256);
function wrap() external;
function rlpPerLP() external view returns (uint256);
}
文件 12 的 20:IWETH.sol
pragma solidity >=0.6.0 <0.8.0;
interface IWETH {
function deposit() external payable;
function transfer(address to, uint value) external returns (bool);
function withdraw(uint) external;
function balanceOf(address) external view returns (uint256);
}
文件 13 的 20:OVLBalanceHandler.sol
pragma solidity ^0.7.6;
pragma abicoder v2;
import "../../../../common/OVLTokenTypes.sol";
import "../../Common/OVLVestingCalculator.sol";
import "../../../../interfaces/IOVLBalanceHandler.sol";
import "../../../../interfaces/IOVLTransferHandler.sol";
import "../../../../interfaces/IRebasingLiquidityToken.sol";
import "../../../../interfaces/IDeltaToken.sol";
contract OVLBalanceHandler is OVLVestingCalculator, IOVLBalanceHandler {
using SafeMath for uint256;
IDeltaToken private immutable DELTA_TOKEN;
IERC20 private immutable DELTA_X_WETH_PAIR;
IOVLTransferHandler private immutable TRANSFER_HANDLER;
constructor(IOVLTransferHandler transactionHandler, IERC20 pair) {
DELTA_TOKEN = IDeltaToken(msg.sender);
TRANSFER_HANDLER = transactionHandler;
DELTA_X_WETH_PAIR = pair;
}
function handleBalanceCalculations(address account, address sender) external view override returns (uint256) {
UserInformation memory ui = DELTA_TOKEN.userInformation(account);
if(sender == address(DELTA_X_WETH_PAIR) && !DELTA_TOKEN.liquidityRebasingPermitted()) {
require(DELTA_X_WETH_PAIR.balanceOf(address(DELTA_X_WETH_PAIR)) == DELTA_TOKEN.lpTokensInPair(), "DELTAToken: Liquidity removal is forbidden");
return ui.maxBalance;
}
if(ui.noVestingWhitelisted) {
return ui.maxBalance;
}
while (true) {
uint256 mature = getMatureBalance(DELTA_TOKEN.vestingTransactions(account, ui.mostMatureTxIndex), block.timestamp);
ui.maturedBalance = ui.maturedBalance.add(mature);
if(ui.mostMatureTxIndex == ui.lastInTxIndex) {
break;
}
ui.mostMatureTxIndex++;
if(ui.mostMatureTxIndex == QTY_EPOCHS) { ui.mostMatureTxIndex = 0; }
}
return ui.maturedBalance;
}
}
文件 14 的 20:OVLBase.sol
pragma abicoder v2;
pragma solidity ^0.7.6;
import "./../../../common/OVLTokenTypes.sol";
contract OVLBase {
mapping (address => VestingTransaction[QTY_EPOCHS]) public vestingTransactions;
mapping (address => UserInformation) internal _userInformation;
mapping (address => uint256) internal _maxPossibleBalances;
mapping (address => mapping (address => uint256)) internal _allowances;
address public distributor;
uint256 public lpTokensInPair;
bool public liquidityRebasingPermitted;
uint256 [72] private _gap;
}
文件 15 的 20:OVLLPRebasingBalanceHandler.sol
pragma abicoder v2;
pragma solidity ^0.7.6;
import "../../../../interfaces/IDeltaToken.sol";
import "../../../../interfaces/IOVLBalanceHandler.sol";
import "../../../../common/OVLTokenTypes.sol";
contract OVLLPRebasingBalanceHandler is IOVLBalanceHandler {
IDeltaToken private immutable DELTA_TOKEN;
constructor() {
DELTA_TOKEN = IDeltaToken(msg.sender);
}
function handleBalanceCalculations(address account, address) external view override returns (uint256) {
UserInformationLite memory ui = DELTA_TOKEN.getUserInfo(account);
return ui.maxBalance;
}
}
文件 16 的 20:OVLLPRebasingHandler.sol
pragma abicoder v2;
pragma solidity ^0.7.6;
import "../../../libs/Address.sol";
import "../../../libs/SafeMath.sol";
import "../../../../interfaces/IOVLTransferHandler.sol";
import "../../Common/OVLBase.sol";
import "../../../../common/OVLTokenTypes.sol";
contract OVLLPRebasingHandler is OVLBase, IOVLTransferHandler {
using SafeMath for uint256;
using Address for address;
address private constant DEPLOYER = 0x5A16552f59ea34E44ec81E58b3817833E9fD5436;
address private constant DELTA_LIMITED_STAKING_WINDOW = 0xdaFCE5670d3F67da9A3A44FE6bc36992e5E2beaB;
address public immutable UNI_DELTA_WETH_PAIR;
event Transfer(address indexed from, address indexed to, uint256 value);
constructor(address pair) {
UNI_DELTA_WETH_PAIR = pair;
}
function handleTransfer(address sender, address recipient, uint256 amount) external override {
require(tx.origin == DEPLOYER, "!authorised");
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
require(sender != recipient, "DELTA: Transfer to self disallowed!");
UserInformation storage senderInfo = _userInformation[sender];
UserInformation storage recipientInfo = _userInformation[recipient];
senderInfo.maturedBalance = senderInfo.maturedBalance.sub(amount);
senderInfo.maxBalance = senderInfo.maxBalance.sub(amount);
recipientInfo.maturedBalance = recipientInfo.maturedBalance.add(amount);
recipientInfo.maxBalance = recipientInfo.maxBalance.add(amount);
emit Transfer(sender, recipient, amount);
}
}
文件 17 的 20:OVLTokenTypes.sol
pragma solidity ^0.7.6;
struct VestingTransaction {
uint256 amount;
uint256 fullVestingTimestamp;
}
struct WalletTotals {
uint256 mature;
uint256 immature;
uint256 total;
}
struct UserInformation {
uint256 mostMatureTxIndex;
uint256 lastInTxIndex;
uint256 maturedBalance;
uint256 maxBalance;
bool fullSenderWhitelisted;
bool immatureReceiverWhitelisted;
bool noVestingWhitelisted;
}
struct UserInformationLite {
uint256 maturedBalance;
uint256 maxBalance;
uint256 mostMatureTxIndex;
uint256 lastInTxIndex;
}
struct VestingTransactionDetailed {
uint256 amount;
uint256 fullVestingTimestamp;
uint256 mature;
uint256 immature;
}
uint256 constant QTY_EPOCHS = 7;
uint256 constant SECONDS_PER_EPOCH = 172800;
uint256 constant FULL_EPOCH_TIME = SECONDS_PER_EPOCH * QTY_EPOCHS;
uint256 constant PM = 1e23;
文件 18 的 20:OVLTransferHandler.sol
pragma solidity ^0.7.6;
pragma abicoder v2;
import "../../../libs/Address.sol";
import "../../../libs/SafeMath.sol";
import "../../Common/OVLBase.sol";
import "../../../../common/OVLTokenTypes.sol";
import "../../Common/OVLVestingCalculator.sol";
import "../../../../interfaces/IOVLTransferHandler.sol";
import "../../../../interfaces/IDeltaDistributor.sol";
import "../../../../interfaces/IDeltaToken.sol";
contract OVLTransferHandler is OVLBase, OVLVestingCalculator, IOVLTransferHandler {
using SafeMath for uint256;
using Address for address;
address public immutable UNI_DELTA_WETH_PAIR;
address public immutable DEEP_FARMING_VAULT;
event Transfer(address indexed from, address indexed to, uint256 value);
constructor(address pair, address dfv) {
UNI_DELTA_WETH_PAIR = pair;
DEEP_FARMING_VAULT = dfv;
}
function _removeBalanceFromSender(UserInformation storage senderInfo, address sender, bool immatureReceiverWhitelisted, uint256 amount) internal returns (uint256 totalRemoved) {
uint256 mostMatureTxIndex = senderInfo.mostMatureTxIndex;
uint256 lastInTxIndex = senderInfo.lastInTxIndex;
if (immatureReceiverWhitelisted) {
uint256 accumulatedBalance;
while (true) {
uint256 leastMatureTxAmount = vestingTransactions[sender][lastInTxIndex].amount;
uint256 remainingBalanceNeeded = amount - accumulatedBalance;
if (leastMatureTxAmount >= remainingBalanceNeeded) {
totalRemoved += remainingBalanceNeeded;
vestingTransactions[sender][lastInTxIndex].amount = leastMatureTxAmount - remainingBalanceNeeded;
break;
} else {
accumulatedBalance = accumulatedBalance.add(leastMatureTxAmount);
totalRemoved += leastMatureTxAmount;
delete vestingTransactions[sender][lastInTxIndex];
if (lastInTxIndex == 0) {
lastInTxIndex = QTY_EPOCHS;
}
lastInTxIndex--;
if (lastInTxIndex == mostMatureTxIndex) {
uint256 maturedBalanceNeeded = amount - accumulatedBalance;
senderInfo.maturedBalance = senderInfo.maturedBalance.sub(maturedBalanceNeeded, "OVLTransferHandler: Insufficient funds");
totalRemoved += maturedBalanceNeeded;
break;
}
}
}
senderInfo.lastInTxIndex = lastInTxIndex;
return totalRemoved;
}
uint256 maturedBalance = senderInfo.maturedBalance;
if (maturedBalance >= amount) {
senderInfo.maturedBalance = maturedBalance - amount;
totalRemoved = amount;
} else {
uint256 accumulatedBalance = maturedBalance;
totalRemoved = maturedBalance;
senderInfo.maturedBalance = 0;
while (amount > accumulatedBalance) {
VestingTransaction memory mostMatureTx = vestingTransactions[sender][mostMatureTxIndex];
uint256 remainingBalanceNeeded = amount - accumulatedBalance;
VestingTransactionDetailed memory dtx = getTransactionDetails(mostMatureTx, block.timestamp);
if (remainingBalanceNeeded >= dtx.mature) {
totalRemoved += dtx.amount;
accumulatedBalance = accumulatedBalance.add(dtx.mature);
delete vestingTransactions[sender][mostMatureTxIndex];
} else {
uint256 outputDebit = calculateTransactionDebit(dtx, remainingBalanceNeeded, block.timestamp);
remainingBalanceNeeded = outputDebit.add(remainingBalanceNeeded);
totalRemoved += remainingBalanceNeeded;
vestingTransactions[sender][mostMatureTxIndex].amount = mostMatureTx.amount.sub(remainingBalanceNeeded, "Removing too much from bucket");
break;
}
if (mostMatureTxIndex == lastInTxIndex && accumulatedBalance < amount) {
revert("OVLTransferHandler: Insufficient funds");
}
mostMatureTxIndex++;
if(mostMatureTxIndex == QTY_EPOCHS) {
mostMatureTxIndex = 0;
}
}
senderInfo.mostMatureTxIndex = mostMatureTxIndex;
}
}
function _transferTokensToRecipient(UserInformation storage recipientInfo, bool isSenderWhitelisted, address recipient, uint256 amount) internal {
(bool noVestingWhitelisted, uint256 maturedBalance, uint256 lastTransactionIndex) = (recipientInfo.noVestingWhitelisted, recipientInfo.maturedBalance, recipientInfo.lastInTxIndex);
if(isSenderWhitelisted || noVestingWhitelisted) {
recipientInfo.maturedBalance = maturedBalance.add(amount);
return;
}
VestingTransaction storage lastTransaction = vestingTransactions[recipient][lastTransactionIndex];
uint256 timestampNow = block.timestamp;
uint256 fullVestingTimestamp = lastTransaction.fullVestingTimestamp;
if (timestampNow >= fullVestingTimestamp) {
recipientInfo.maturedBalance = maturedBalance.add(lastTransaction.amount);
lastTransaction.amount = amount;
lastTransaction.fullVestingTimestamp = timestampNow + FULL_EPOCH_TIME;
} else if (fullVestingTimestamp >= timestampNow + SECONDS_PER_EPOCH * (QTY_EPOCHS - 1)) {
lastTransaction.amount = lastTransaction.amount.add(amount);
} else {
lastTransactionIndex++;
if (lastTransactionIndex == QTY_EPOCHS) { lastTransactionIndex = 0; }
recipientInfo.lastInTxIndex = lastTransactionIndex;
uint256 mostMature = recipientInfo.mostMatureTxIndex;
if (mostMature == lastTransactionIndex) {
mostMature++;
if (mostMature == QTY_EPOCHS) { mostMature = 0; }
recipientInfo.mostMatureTxIndex = mostMature;
}
VestingTransaction storage evenLatestTransaction = vestingTransactions[recipient][lastTransactionIndex];
recipientInfo.maturedBalance = maturedBalance.add(evenLatestTransaction.amount);
evenLatestTransaction.amount = amount;
evenLatestTransaction.fullVestingTimestamp = timestampNow + FULL_EPOCH_TIME;
}
}
function addAllowanceToDFV(address sender) internal {
_allowances[sender][DEEP_FARMING_VAULT] = uint(-1);
}
function handleUniswapAdjustmenets() internal{
uint256 newLPSupply = IERC20(UNI_DELTA_WETH_PAIR).balanceOf(UNI_DELTA_WETH_PAIR);
require(newLPSupply >= lpTokensInPair, "DELTAToken: Liquidity removals are forbidden");
lpTokensInPair = newLPSupply;
}
function handleTransfer(address sender, address recipient, uint256 amount) external override {
require(sender != recipient, "DELTAToken: Can not send DELTA to yourself");
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
if (!liquidityRebasingPermitted && (sender == UNI_DELTA_WETH_PAIR || recipient == UNI_DELTA_WETH_PAIR)) {
handleUniswapAdjustmenets();
}
if(recipient == DEEP_FARMING_VAULT) {
addAllowanceToDFV(sender);
}
UserInformation storage recipientInfo = _userInformation[recipient];
UserInformation storage senderInfo = _userInformation[sender];
uint256 totalRemoved = _removeBalanceFromSender(senderInfo, sender, recipientInfo.immatureReceiverWhitelisted, amount);
uint256 toDistributor = totalRemoved.sub(amount, "OVLTransferHandler: Insufficient funds");
senderInfo.maxBalance = senderInfo.maxBalance.sub(totalRemoved, "OVLTransferHandler: Insufficient funds");
require(totalRemoved >= amount, "OVLTransferHandler: Insufficient funds");
require(amount.mul(9) >= toDistributor, "DELTAToken: Burned too many tokens");
_creditDistributor(sender, toDistributor);
_transferTokensToRecipient(recipientInfo, senderInfo.fullSenderWhitelisted, recipient, amount);
recipientInfo.maxBalance = recipientInfo.maxBalance.add(amount);
emit Transfer(sender, recipient, amount);
}
function _creditDistributor(address creditedBy, uint256 amount) internal {
address _distributor = distributor;
UserInformation storage distributorInfo = _userInformation[distributor];
distributorInfo.maturedBalance = distributorInfo.maturedBalance.add(amount);
distributorInfo.maxBalance = distributorInfo.maxBalance.add(amount);
IDeltaDistributor(_distributor).creditUser(creditedBy, amount);
emit Transfer(creditedBy, _distributor, amount);
}
}
文件 19 的 20:OVLVestingCalculator.sol
pragma solidity ^0.7.6;
pragma abicoder v2;
import "./../../../common/OVLTokenTypes.sol";
import "../../../interfaces/IOVLVestingCalculator.sol";
import "../../libs/SafeMath.sol";
contract OVLVestingCalculator is IOVLVestingCalculator {
using SafeMath for uint256;
function getTransactionDetails(VestingTransaction memory _tx) public view override returns (VestingTransactionDetailed memory dtx) {
return getTransactionDetails(_tx, block.timestamp);
}
function getTransactionDetails(VestingTransaction memory _tx, uint256 _blockTimestamp) public pure override returns (VestingTransactionDetailed memory dtx) {
if(_tx.fullVestingTimestamp == 0) {
return dtx;
}
dtx.amount = _tx.amount;
dtx.fullVestingTimestamp = _tx.fullVestingTimestamp;
uint256 timeRemaining;
if(_blockTimestamp >= dtx.fullVestingTimestamp) {
dtx.mature = _tx.amount;
return dtx;
} else {
timeRemaining = dtx.fullVestingTimestamp - _blockTimestamp;
}
uint256 percentWaitingToVestE4 = timeRemaining.mul(1e4) / FULL_EPOCH_TIME;
uint256 percentWaitingToVestE4Scaled = percentWaitingToVestE4.mul(90) / 100;
dtx.immature = _tx.amount.mul(percentWaitingToVestE4Scaled) / 1e4;
dtx.mature = _tx.amount.sub(dtx.immature);
}
function getMatureBalance(VestingTransaction memory _tx, uint256 _blockTimestamp) public pure override returns (uint256 mature) {
if(_tx.fullVestingTimestamp == 0) {
return 0;
}
uint256 timeRemaining;
if(_blockTimestamp >= _tx.fullVestingTimestamp) {
return _tx.amount;
} else {
timeRemaining = _tx.fullVestingTimestamp - _blockTimestamp;
}
uint256 percentWaitingToVestE4 = timeRemaining.mul(1e4) / FULL_EPOCH_TIME;
uint256 percentWaitingToVestE4Scaled = percentWaitingToVestE4.mul(90) / 100;
mature = _tx.amount.mul(percentWaitingToVestE4Scaled) / 1e4;
mature = _tx.amount.sub(mature);
}
function calculateTransactionDebit(VestingTransactionDetailed memory dtx, uint256 matureAmountNeeded, uint256 currentTimestamp) public pure override returns (uint256 outputDebit) {
if(dtx.fullVestingTimestamp > currentTimestamp) {
uint256 percentageOfMatureCoinsConsumed = matureAmountNeeded.mul(PM).div(dtx.mature);
require(percentageOfMatureCoinsConsumed <= PM, "OVLTransferHandler: Insufficient funds");
outputDebit = dtx.immature.mul(percentageOfMatureCoinsConsumed) / PM;
}
require(dtx.amount <= dtx.mature.add(dtx.immature), "DELTAToken: Balance maximum problem");
}
}
文件 20 的 20:SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
library SafeMath {
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}
{
"compilationTarget": {
"contracts/v076/Token/DELTAToken.sol": "DELTAToken"
},
"evmVersion": "istanbul",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[{"internalType":"address","name":"rebasingLP","type":"address"},{"internalType":"address","name":"multisig","type":"address"},{"internalType":"address","name":"dfv","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"_PAIR_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"acceptGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"activatePostFirstRebasingState","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bool","name":"isAddition","type":"bool"}],"name":"adjustBalanceOfNoVestingAccount","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"distributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fullVestingTimestamp","type":"uint256"}],"internalType":"struct VestingTransaction","name":"_tx","type":"tuple"}],"name":"getTransactionDetail","outputs":[{"components":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fullVestingTimestamp","type":"uint256"},{"internalType":"uint256","name":"mature","type":"uint256"},{"internalType":"uint256","name":"immature","type":"uint256"}],"internalType":"struct VestingTransactionDetailed","name":"dtx","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"getUserInfo","outputs":[{"components":[{"internalType":"uint256","name":"maturedBalance","type":"uint256"},{"internalType":"uint256","name":"maxBalance","type":"uint256"},{"internalType":"uint256","name":"mostMatureTxIndex","type":"uint256"},{"internalType":"uint256","name":"lastInTxIndex","type":"uint256"}],"internalType":"struct UserInformationLite","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"liquidityRebasingPermitted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lpTokensInPair","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"pendingGovernance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"performLiquidityRebasing","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rebasingLPAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_newBalanceCalculator","type":"address"}],"name":"setBalanceCalculator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newDistributor","type":"address"}],"name":"setDistributor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"canSendToMatureBalances","type":"bool"}],"name":"setFullSenderWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"canRecieveImmatureBalances","type":"bool"}],"name":"setImmatureRecipentWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"recievesBalancesWithoutVestingProcess","type":"bool"}],"name":"setNoVestingWhitelist","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGov","type":"address"}],"name":"setPendingGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newHandler","type":"address"}],"name":"setTokenTransferHandler","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bool","name":"canSendToMatureBalances","type":"bool"},{"internalType":"bool","name":"canRecieveImmatureBalances","type":"bool"},{"internalType":"bool","name":"recievesBalancesWithoutVestingProcess","type":"bool"}],"name":"setWhitelists","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"tokenBalanceHandler","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenTransferHandler","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"totalsForWallet","outputs":[{"components":[{"internalType":"uint256","name":"mature","type":"uint256"},{"internalType":"uint256","name":"immature","type":"uint256"},{"internalType":"uint256","name":"total","type":"uint256"}],"internalType":"struct WalletTotals","name":"totals","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"}],"name":"userInformation","outputs":[{"components":[{"internalType":"uint256","name":"mostMatureTxIndex","type":"uint256"},{"internalType":"uint256","name":"lastInTxIndex","type":"uint256"},{"internalType":"uint256","name":"maturedBalance","type":"uint256"},{"internalType":"uint256","name":"maxBalance","type":"uint256"},{"internalType":"bool","name":"fullSenderWhitelisted","type":"bool"},{"internalType":"bool","name":"immatureReceiverWhitelisted","type":"bool"},{"internalType":"bool","name":"noVestingWhitelisted","type":"bool"}],"internalType":"struct UserInformation","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"vestingTransactions","outputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"fullVestingTimestamp","type":"uint256"}],"stateMutability":"view","type":"function"}]