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

Structs #11

Merged
merged 6 commits into from
Sep 3, 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
40 changes: 19 additions & 21 deletions contracts/Foundry.sol
Original file line number Diff line number Diff line change
Expand Up @@ -41,22 +41,22 @@ contract Foundry is IFoundry, Ownable, Initializable {
/// @inheritdoc IFoundry
function mint(address _meToken, uint256 _collateralDeposited, address _recipient) external override {

IMeTokenRegistry.Details memory meTokenDetails = meTokenRegistry.getDetails(_meToken);
HubDetails memory hubDetails = hub.getDetails(meTokenDetails.id);
MeTokenDetails memory meTokenDetails = meTokenRegistry.getDetails(_meToken);
HubDetails memory hubDetails = hub.getDetails(meTokenDetails.hubId);
require(hubDetails.active, "Hub inactive");

uint256 fee = _collateralDeposited * fees.mintFee() / PRECISION;
uint256 collateralDepositedAfterFees = _collateralDeposited - fee;

uint256 meTokensMinted = ICurveValueSet(hubDetails.curve).calculateMintReturn(
collateralDepositedAfterFees,
meTokenDetails.id,
IERC20(meToken).totalSupply(),
meTokenDetails.hubId,
IERC20(_meToken).totalSupply(),
meTokenDetails.balancePooled
);

// Send collateral to vault and update balance pooled
address collateralToken = IVault(hubDetails.vault).getCollateralAsset());
address collateralToken = IVault(hubDetails.vault).getCollateralAsset();
IERC20(collateralToken).transferFrom(msg.sender, address(this), _collateralDeposited);

meTokenRegistry.incrementBalancePooled(
Expand All @@ -69,41 +69,39 @@ contract Foundry is IFoundry, Ownable, Initializable {
if (fee > 0) {IVault(hubDetails.vault).addFee(fee);}

// Mint meToken to user
meToken.mint(_recipient, meTokensMinted);
IERC20(_meToken).mint(_recipient, meTokensMinted);
}


/// @inheritdoc IFoundry
function burn(address _meToken, uint256 _meTokensBurned , address _recipient) external override {

IMeTokenRegistry.Details memory details = meTokenRegistry.getDetails(_meToken);

require(hub.isActive(details.id), "Hub inactive");

ICurveValueSet curve = ICurveValueSet(hub.getCurve(details.id));
IVault vault = IVault(hub.getVault(details.id));
MeTokenDetails memory meTokenDetails = meTokenRegistry.getDetails(_meToken);
HubDetails memory hubDetails = hub.getDetails(meTokenDetails.hubId);
require(hubDetails.active, "Hub inactive");

// Calculate how many collateral tokens are returned
uint256 collateralReturned = curve.calculateBurnReturn(
uint256 collateralReturned = ICurveValueSet(hubDetails.curve).calculateBurnReturn(
_meTokensBurned,
details.id,
meTokenDetails.hubId,
IERC20(_meToken).totalSupply(),
details.balancePooled
meTokenDetails.balancePooled
);

uint256 feeRate;
uint256 collateralMultiplier;
// If msg.sender == owner, give owner the sell rate.
// If msg.sender != owner, give msg.sender the burn rate
if (msg.sender == details.owner) {
if (msg.sender == meTokenDetails.owner) {
feeRate = fees.burnOwnerFee();
collateralMultiplier = PRECISION + PRECISION * details.balanceLocked / IERC20(_meToken).totalSupply();
collateralMultiplier = PRECISION + PRECISION * meTokenDetails.balanceLocked / IERC20(_meToken).totalSupply();
} else {
feeRate = fees.burnBuyerFee();
collateralMultiplier = PRECISION;
}

uint256 collateralReturnedWeighted = collateralReturned * collateralMultiplier / PRECISION;
// uint256 collateralReturnedAfterFees = collateralReturnedWeighted - (collateralReturnedWeighted * feeRate / PRECISION);
uint256 collateralReturnedAfterFees = collateralReturnedWeighted - (collateralReturnedWeighted * feeRate / PRECISION);

// Burn metoken from user
IERC20(_meToken).burn(msg.sender, _meTokensBurned);
Expand Down Expand Up @@ -134,11 +132,11 @@ contract Foundry is IFoundry, Ownable, Initializable {
// Transfer fees - TODO
if ((collateralReturnedWeighted * feeRate / PRECISION) > 0) {
uint256 fee = collateralReturnedWeighted * feeRate / PRECISION;
vault.addFee(fee);
IVault(hubDetails.vault).addFee(fee);
}

// Send collateral from vault
// IERC20 collateralToken = IERC20(vault.getCollateralAsset());
// collateralAsset.transferFrom(address(vault), _recipient, collateralReturnedAfterFees);
address collateralToken = IVault(hubDetails.vault).getCollateralAsset();
IERC20(collateralToken).transferFrom(hubDetails.vault, _recipient, collateralReturnedAfterFees);
}
}
76 changes: 25 additions & 51 deletions contracts/Hub.sol
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import "./interfaces/ICurveRegistry.sol";
import "./interfaces/ICurveValueSet.sol";
// import "./interfaces/IUpdater.sol";

import "./libs/Details.sol";
import {HubDetails, MeTokenDetails} from "./libs/Details.sol";


/// @title meToken hub
Expand All @@ -33,15 +33,6 @@ contract Hub is Ownable, Initializable {
ICurveRegistry public curveRegistry;
// IUpdater public updater;

struct Details {
string name;
address owner;
address vault;
address curve;
uint refundRatio;
bool active;
}

mapping(uint => HubDetails) private hubs;

constructor() {}
Expand Down Expand Up @@ -87,15 +78,13 @@ contract Hub is Ownable, Initializable {
address vault = IVaultFactory(_vaultFactory).create(_vaultName, _collateralAsset, _encodedVaultAdditionalArgs);

// Save the hub to the registry
HubDetails storage hubDetails = HubDetails({
name:_name,
owner:_owner,
active: true,
vault:address(vault),
curve:_curve,
refundRatio:_refundRatio
});
hubs[count++] = hubDetails;
HubDetails storage newHubDetails = hubs[count++];
newHubDetails.name = _name;
newHubDetails.owner = _owner;
newHubDetails.active = true;
newHubDetails.vault = address(vault);
newHubDetails.curve = _curve;
newHubDetails.refundRatio = _refundRatio;
}


Expand All @@ -104,58 +93,45 @@ contract Hub is Ownable, Initializable {
// emit Deactivate(id);
}

// TODO: is this needed?
// function reactivateHub() returns (uint) {}

// function startUpdate(uint id) external override {
// require(msg.sender == address(updater), "!updater");
// Details storage details = hubs[id];
// details.status = Status.QUEUED;
// }


function finishUpdate(
uint id,
address migrating,
address recollateralizing,
uint shifting
) external {
// require(msg.sender == address(updater), "!updater");
Details storage details = hubs[id];
HubDetails storage hubDetails = hubs[id];

if (migrating != address(0)) {
details.curve = migrating;
hubDetails.curve = migrating;
}

if (recollateralizing != address(0)) {
details.vault = recollateralizing;
hubDetails.vault = recollateralizing;
}

if (shifting != 0) {
details.refundRatio = shifting;
hubDetails.refundRatio = shifting;
}
}

function getCount() external view returns (uint) {return count;}

function getOwner(uint id) public view exists(id) returns (address) {
Details memory details = hubs[id];
return details.owner;
HubDetails memory hubDetails = hubs[id];
return hubDetails.owner;
}


function isActive(uint id) public view returns (bool) {
Details memory details = hubs[id];
return details.active;
HubDetails memory hubDetails = hubs[id];
return hubDetails.active;
}


function getRefundRatio(uint id) public view returns (uint) {
Details memory details = hubs[id];
return details.refundRatio;
function getRefundRatio(uint id) external view exists(id) returns (uint) {
HubDetails memory hubDetails = hubs[id];
return hubDetails.refundRatio;
}


function getDetails(
uint id
) external view exists(id) returns (
Expand All @@ -164,16 +140,14 @@ contract Hub is Ownable, Initializable {
hubDetails = hubs[id];
}

function getCurve(uint id) external view returns (address) {
require(id < count, "id > count");
Details memory details = hubs[id];
return details.curve;
function getCurve(uint id) external view exists(id) returns (address) {
HubDetails memory hubDetails = hubs[id];
return hubDetails.curve;
}

function getVault(uint id) external view returns (address) {
require(id < count, "id > count");
Details memory details = hubs[id];
return details.vault;
function getVault(uint id) external view exists(id) returns (address) {
HubDetails memory hubDetails = hubs[id];
return hubDetails.vault;
}

}
98 changes: 0 additions & 98 deletions contracts/curves/formulas/BancorZeroFormula.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,104 +10,6 @@ import "../../utils/Power.sol";
/// and to You under the Apache License, Version 2.0. "
contract BancorZeroFormula is Power {

uint32 public MAX_WEIGHT = 1000000;
uint256 public PRECISION = 10**18;

/// @notice Given a deposit amount (in the connector token), connector weight, meToken supply and
/// calculates the return for a given conversion (in the meToken)
/// @dev _supply * ((1 + _depositAmount / _balancePooled) ^ (_reserveWeight / 1000000) - 1)
/// @param _depositAmount amount of collateral tokens to deposit
/// @param _reserveWeight connector weight, represented in ppm, 1 - 1,000,000
/// @param _supply current meToken supply
/// @param _balancePooled total connector balance
/// @return meTokenAmount amount of meTokens minted
function _calculateMintReturn(
uint256 _depositAmount,
uint32 _reserveWeight,
uint256 _supply,
uint256 _balancePooled
) internal view returns (uint256 meTokenAmount) {
// validate input
require(_balancePooled > 0 && _reserveWeight > 0 && _reserveWeight <= MAX_WEIGHT);
// special case for 0 deposit amount
if (_depositAmount == 0) {
return 0;
}
// special case if the weight = 100%
if (_reserveWeight == MAX_WEIGHT) {
return _supply * _depositAmount / _balancePooled;
}

uint8 precision;
uint256 result;
uint256 baseN = _depositAmount + _balancePooled;
(result, precision) = power(
baseN, _balancePooled, _reserveWeight, MAX_WEIGHT
);
uint256 newTokenSupply = _supply * result >> precision;
meTokenAmount = newTokenSupply - _supply;
}


/// @notice Given a deposit amount (in the collateral token,) meToken supply of 0, connector weight,
/// constant x and constant y, calculates the return for a given conversion (in the meToken)
/// @dev _baseX and _baseY are needed as Bancor formula breaks from a divide-by-0 when supply = 0
/// @param _depositAmount amount of collateral tokens to deposit
/// @param _reserveWeight connector weight, represented in ppm, 1 - 1,000,000
/// @param _baseX constant X
/// @param _baseY constant y
/// @return returnedAmount amount of meTokens minted
function _calculateMintReturnFromZero(
uint256 _depositAmount,
uint256 _reserveWeight,
uint256 _baseX,
uint256 _baseY
) internal view returns (uint256 returnedAmount) {
uint256 numerator = _baseY;
uint256 exponent = (PRECISION/_reserveWeight - PRECISION);
uint256 denominator = _baseX ** exponent;
returnedAmount = numerator/denominator * _depositAmount** exponent;
}


/// @notice Given an amount of meTokens to burn, connector weight, supply and collateral pooled,
/// calculates the return for a given conversion (in the collateral token)
/// @dev _balancePooled * (1 - (1 - _burnAmount / _supply) ^ (1 / (_reserveWeight / 1000000)))
/// @param _burnAmount amount of meTokens to burn
/// @param _reserveWeight connector weight, represented in ppm, 1 - 1,000,000
/// @param _supply current meToken supply
/// @param _balancePooled total connector balance
/// @return reserveTokenAmount amount of collateral tokens received
function _calculateBurnReturn(
uint256 _burnAmount,
uint32 _reserveWeight,
uint256 _supply,
uint256 _balancePooled
) internal view returns (uint256 reserveTokenAmount) {
// validate input
require(_supply > 0 && _balancePooled > 0 && _reserveWeight > 0 && _reserveWeight <= MAX_WEIGHT && _burnAmount <= _supply);
// special case for 0 sell amount
if (_burnAmount == 0) {
return 0;
}
// special case for selling the entire supply
if (_burnAmount == _supply) {
return _balancePooled;
}
// special case if the weight = 100%
if (_reserveWeight == MAX_WEIGHT) {
return _balancePooled * _burnAmount / _supply;
}

uint256 result;
uint8 precision;
uint256 baseD = _supply - _burnAmount;
(result, precision) = power(
_supply, baseD, MAX_WEIGHT, _reserveWeight
);
uint256 oldBalance = _balancePooled * result;
uint256 newBalance = _balancePooled << precision;

reserveTokenAmount = (oldBalance - newBalance) / result;
}
}
Loading