Skip to content
Open
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
24 changes: 16 additions & 8 deletions contracts/BasicMultiToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,20 @@ contract BasicMultiToken is Ownable, StandardToken, DetailedERC20, ERC1003Token,

// Internal methods

function _mint(address beneficiary, uint256 amount) internal {
totalSupply_ = totalSupply_.add(amount);
balances[beneficiary] = balances[beneficiary].add(amount);
emit Bundle(msg.sender, beneficiary, amount);
emit Transfer(0, beneficiary, amount);
}

function _burn(address spender, uint256 amount) internal {
balances[spender] = balances[spender].sub(amount);
totalSupply_ = totalSupply_.sub(amount);
emit Unbundle(msg.sender, spender, amount);
emit Transfer(spender, 0, amount);
}

function _bundle(address beneficiary, uint256 amount, uint256[] tokenAmounts) internal {
require(amount != 0, "Bundling amount should be non-zero");
require(_tokens.length == tokenAmounts.length, "Lenghts of _tokens and tokenAmounts array should be equal");
Expand All @@ -114,20 +128,14 @@ contract BasicMultiToken is Ownable, StandardToken, DetailedERC20, ERC1003Token,
_tokens[i].checkedTransferFrom(msg.sender, this, tokenAmounts[i]);
}

totalSupply_ = totalSupply_.add(amount);
balances[beneficiary] = balances[beneficiary].add(amount);
emit Bundle(msg.sender, beneficiary, amount);
emit Transfer(0, beneficiary, amount);
_mint(beneficiary, amount);
}

function _unbundle(address beneficiary, uint256 value, ERC20[] someTokens) internal {
require(someTokens.length > 0, "Array of someTokens can't be empty");

uint256 totalSupply = totalSupply_;
balances[msg.sender] = balances[msg.sender].sub(value);
totalSupply_ = totalSupply.sub(value);
emit Unbundle(msg.sender, beneficiary, value);
emit Transfer(msg.sender, 0, value);
_burn(msg.sender, value);

for (uint i = 0; i < someTokens.length; i++) {
for (uint j = 0; j < i; j++) {
Expand Down
78 changes: 78 additions & 0 deletions contracts/FeeFundMultiToken.sol
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,82 @@ import "./FeeMultiToken.sol";


contract FeeFundMultiToken is FundMultiToken, FeeMultiToken {
bool private _transfersEnabled = true;
uint256 private _managementFee;
bool private _managementFeeLocked;
uint256 private _managementFeeLastPayment;

event TransfersDisabled();
event TransfersEnabled();
event ManagementFeeLocked();

constructor() public {
_managementFeeLastPayment = now;
}

// Public methods

function transfersEnabled() public view returns(bool) {
return _transfersEnabled;
}

function managementFee() public view returns(uint256) {
return _managementFee;
}

function managementFeeLocked() public view returns(bool) {
return _managementFeeLocked;
}

function payManagementFee() public {
uint256 period = now.sub(_managementFeeLastPayment);

uint256 totalSupplyExcludingManagerShare = totalSupply().sub(balanceOf(manager()));
uint256 feeShare = totalSupplyExcludingManagerShare
.mul(_managementFee).mul(period).div(TOTAL_PERCENTS).div(365 days);
if (feeShare > 0) {
_mint(manager(), feeShare);
}

_managementFeeLastPayment = now;
}

// Admin methods

function enableTransfers() public onlyManager {
require(_transfersEnabled, "Transfers are already enabled");
_transfersEnabled = true;
emit TransfersEnabled();
}

function disableTransfers() public onlyManager {
require(!_transfersEnabled, "Transfers are already disabled");
_transfersEnabled = false;
emit TransfersDisabled();
}

function setManagementFee(uint256 theManagementFee) public onlyManager {
require(!_managementFeeLocked, "setManagementFee: management fee was locked");
require(theManagementFee <= 100000, "setManagementFee: fee should be not greater than 10% per year");
payManagementFee();
_managementFee = theManagementFee;
}

function lockManagementFee() public onlyManager {
require(!_managementFeeLocked, "lockManagementFee: already locked");
_managementFeeLocked = true;
emit ManagementFeeLocked();
}

// Internal methods

function _bundle(address beneficiary, uint256 amount, uint256[] tokenAmounts) internal {
payManagementFee();
super._bundle(beneficiary, amount, tokenAmounts);
}

function _unbundle(address beneficiary, uint256 value, ERC20[] someTokens) internal {
payManagementFee();
super._unbundle(beneficiary, value, someTokens);
}
}
4 changes: 2 additions & 2 deletions contracts/ext/CheckedERC20.sol
Original file line number Diff line number Diff line change
Expand Up @@ -79,15 +79,15 @@ library CheckedERC20 {
function checkedTransfer(ERC20 token, address to, uint256 value) internal {
if (value > 0) {
uint256 balance = token.balanceOf(this);
asmTransfer(token, to, value);
require(asmTransfer(token, to, value), "asmTransfer failed");
require(token.balanceOf(this) == balance.sub(value), "checkedTransfer: Final balance didn't match");
}
}

function checkedTransferFrom(ERC20 token, address from, address to, uint256 value) internal {
if (value > 0) {
uint256 toBalance = token.balanceOf(to);
asmTransferFrom(token, from, to, value);
require(asmTransferFrom(token, from, to, value), "asmTransferFrom failed");
require(token.balanceOf(to) == toBalance.add(value), "checkedTransfer: Final balance didn't match");
}
}
Expand Down
10 changes: 10 additions & 0 deletions contracts/implementation/AstraFundMultiToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
pragma solidity ^0.4.24;

import "../FeeFundMultiToken.sol";


contract AstraFundMultiToken is FeeFundMultiToken {
function init(ERC20[] tokens, uint256[] tokenWeights, string theName, string theSymbol, uint8 /*theDecimals*/) public {
super.init(tokens, tokenWeights, theName, theSymbol, 18);
}
}
8 changes: 4 additions & 4 deletions contracts/network/MultiBuyer.sol
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ contract MultiBuyer is MultiShopper {
for (uint i = mtkn.tokensCount(); i > 0; i--) {
ERC20 token = mtkn.tokens(i - 1);
if (token.allowance(this, mtkn) == 0) {
token.asmApprove(mtkn, uint256(-1));
require(token.asmApprove(mtkn, uint256(-1)), "asmApprove failed");
}

uint256 amount = mtknTotalSupply.mul(token.balanceOf(this)).div(token.balanceOf(mtkn));
Expand All @@ -42,7 +42,7 @@ contract MultiBuyer is MultiShopper {
for (i = mtkn.tokensCount(); i > 0; i--) {
token = mtkn.tokens(i - 1);
if (token.balanceOf(this) > 0) {
token.asmTransfer(msg.sender, token.balanceOf(this));
require(token.asmTransfer(msg.sender, token.balanceOf(this)), "asmTransfer failed");
}
}
}
Expand All @@ -65,7 +65,7 @@ contract MultiBuyer is MultiShopper {
ERC20 token = mtkn.tokens(i);
amounts[i] = token.balanceOf(this);
if (token.allowance(this, mtkn) == 0) {
token.asmApprove(mtkn, uint256(-1));
require(token.asmApprove(mtkn, uint256(-1)), "asmApprove failed");
}
}

Expand All @@ -76,7 +76,7 @@ contract MultiBuyer is MultiShopper {
for (i = mtkn.tokensCount(); i > 0; i--) {
token = mtkn.tokens(i - 1);
if (token.balanceOf(this) > 0) {
token.asmTransfer(msg.sender, token.balanceOf(this));
require(token.asmTransfer(msg.sender, token.balanceOf(this)), "asmTransfer failed");
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion contracts/network/MultiChanger.sol
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ contract MultiChanger {

function multitokenChangeAmount(IMultiToken mtkn, ERC20 fromToken, ERC20 toToken, uint256 minReturn, uint256 amount) external {
if (fromToken.allowance(this, mtkn) == 0) {
fromToken.asmApprove(mtkn, uint256(-1));
require(fromToken.asmApprove(mtkn, uint256(-1)), "asmApprove failed");
}
mtkn.change(fromToken, toToken, amount, minReturn);
}
Expand Down
11 changes: 9 additions & 2 deletions contracts/network/MultiSeller.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pragma solidity ^0.4.24;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import { IMultiToken } from "../interface/IMultiToken.sol";
import "../interface/IMultiToken.sol";
import "../ext/CheckedERC20.sol";
import "./MultiShopper.sol";

Expand Down Expand Up @@ -42,9 +42,16 @@ contract MultiSeller is MultiShopper {
)
public
{
mtkn.asmTransferFrom(msg.sender, this, amount);
require(mtkn.asmTransferFrom(msg.sender, this, amount), "asmTransferFrom failed");
mtkn.unbundle(this, amount);
change(callDatas, starts);
to.transfer(address(this).balance);

for (uint i = mtkn.tokensCount(); i > 0; i--) {
ERC20 token = mtkn.tokens(i - 1);
if (token.balanceOf(this) > 0) {
require(token.asmTransfer(to, token.balanceOf(this)), "asmTransfer failed");
}
}
}
}
6 changes: 3 additions & 3 deletions contracts/network/MultiShopper.sol
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ contract MultiShopper is CanReclaimToken {

function approveTokenAmount(address target, bytes data, ERC20 fromToken, uint256 amount) external {
if (fromToken.allowance(this, target) != 0) {
fromToken.asmApprove(target, 0);
fromToken.asmApprove(target, 0);
}
fromToken.asmApprove(target, amount);
// solium-disable-next-line security/no-low-level-calls
Expand Down Expand Up @@ -167,13 +167,13 @@ contract MultiShopper is CanReclaimToken {
}

function bancorTransferTokenAmount(IBancorNetwork bancor, address[] path, uint256 amount) external {
ERC20(path[0]).asmTransfer(bancor, amount);
require(ERC20(path[0]).asmTransfer(bancor, amount), "asmTransfer failed");
bancor.convert(path, amount, 1);
}

function bancorTransferTokenProportion(IBancorNetwork bancor, address[] path, uint256 mul, uint256 div) external {
uint256 amount = ERC20(path[0]).balanceOf(this).mul(mul).div(div);
ERC20(path[0]).asmTransfer(bancor, amount);
require(ERC20(path[0]).asmTransfer(bancor, amount), "asmTransfer failed");
bancor.convert(path, amount, 1);
}

Expand Down
Loading