Contract Name:
DRCWalletManager
Contract Source Code:
File 1 of 1 : DRCWalletManager
pragma solidity ^0.4.24;
interface IDRCWalletMgrParams {
function singleWithdrawMin() external returns (uint256); // min value of single withdraw
function singleWithdrawMax() external returns (uint256); // Max value of single withdraw
function dayWithdraw() external returns (uint256); // Max value of one day of withdraw
function monthWithdraw() external returns (uint256); // Max value of one month of withdraw
function dayWithdrawCount() external returns (uint256); // Max number of withdraw counting
function chargeFee() external returns (uint256); // the charge fee for withdraw
function chargeFeePool() external returns (address); // the address that will get the returned charge fees.
}
interface IDRCWalletStorage {
// get the deposit address for this _wallet address
function walletDeposits(address _wallet) external view returns (address);
// get frozen status for the deposit address
function frozenDeposits(address _deposit) external view returns (bool);
// get a wallet address by the deposit address and the index
function wallet(address _deposit, uint256 _ind) external view returns (address);
// get a wallet name by the deposit address and the index
function walletName(address _deposit, uint256 _ind) external view returns (bytes32);
// get the wallets number of a deposit address
function walletsNumber(address _deposit) external view returns (uint256);
// get the frozen amount of the deposit address
function frozenAmount(address _deposit) external view returns (uint256);
// get the balance of the deposit address
function balanceOf(address _deposit) external view returns (uint256);
// get the deposit address by index
function depositAddressByIndex(uint256 _ind) external view returns (address);
// get the frozen amount of the deposit address
function size() external view returns (uint256);
// judge if the _deposit address exsisted.
function isExisted(address _deposit) external view returns (bool);
// add one deposit address for that wallet
function addDeposit(address _wallet, address _depositAddr) external returns (bool);
// change the default wallet address for the deposit address
function changeDefaultWallet(address _oldWallet, address _newWallet) external returns (bool);
// freeze or release the tokens that has been deposited in the deposit address.
function freezeTokens(address _deposit, bool _freeze, uint256 _value) external returns (bool);
// increase balance of this deposit address
function increaseBalance(address _deposit, uint256 _value) external returns (bool);
// decrease balance of this deposit address
function decreaseBalance(address _deposit, uint256 _value) external returns (bool);
// add withdraw address for one deposit addresss
function addWithdraw(address _deposit, bytes32 _name, address _withdraw) external returns (bool);
// change the withdraw wallet name
function changeWalletName(address _deposit, bytes32 _newName, address _wallet) external returns (bool);
// remove deposit contract address from storage
function removeDeposit(address _depositAddr) external returns (bool);
// withdraw tokens from this contract
function withdrawToken(address _token, address _to, uint256 _value) external returns (bool);
}
library SafeMath {
/**
* @dev Multiplies two numbers, throws on overflow.
*/
function mul(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
// Gas optimization: this is cheaper than asserting 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
if (_a == 0) {
return 0;
}
c = _a * _b;
assert(c / _a == _b);
return c;
}
/**
* @dev Integer division of two numbers, truncating the quotient.
*/
function div(uint256 _a, uint256 _b) internal pure returns (uint256) {
// assert(_b > 0); // Solidity automatically throws when dividing by 0
// uint256 c = _a / _b;
// assert(_a == _b * c + _a % _b); // There is no case in which this doesn't hold
return _a / _b;
}
/**
* @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend).
*/
function sub(uint256 _a, uint256 _b) internal pure returns (uint256) {
assert(_b <= _a);
return _a - _b;
}
/**
* @dev Adds two numbers, throws on overflow.
*/
function add(uint256 _a, uint256 _b) internal pure returns (uint256 c) {
c = _a + _b;
assert(c >= _a);
return c;
}
}
contract Ownable {
address public owner;
event OwnershipRenounced(address indexed previousOwner);
event OwnershipTransferred(
address indexed previousOwner,
address indexed newOwner
);
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
constructor() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
/**
* @dev Allows the current owner to relinquish control of the contract.
* @notice Renouncing to ownership will leave the contract without an owner.
* It will not be possible to call the functions with the `onlyOwner`
* modifier anymore.
*/
function renounceOwnership() public onlyOwner {
emit OwnershipRenounced(owner);
owner = address(0);
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function transferOwnership(address _newOwner) public onlyOwner {
_transferOwnership(_newOwner);
}
/**
* @dev Transfers control of the contract to a newOwner.
* @param _newOwner The address to transfer ownership to.
*/
function _transferOwnership(address _newOwner) internal {
require(_newOwner != address(0));
emit OwnershipTransferred(owner, _newOwner);
owner = _newOwner;
}
}
contract Withdrawable is Ownable {
event ReceiveEther(address _from, uint256 _value);
event WithdrawEther(address _to, uint256 _value);
event WithdrawToken(address _token, address _to, uint256 _value);
/**
* @dev recording receiving ether from msn.sender
*/
function () payable public {
emit ReceiveEther(msg.sender, msg.value);
}
/**
* @dev withdraw,send ether to target
* @param _to is where the ether will be sent to
* _amount is the number of the ether
*/
function withdraw(address _to, uint _amount) public onlyOwner returns (bool) {
require(_to != address(0));
_to.transfer(_amount);
emit WithdrawEther(_to, _amount);
return true;
}
/**
* @dev withdraw tokens, send tokens to target
*
* @param _token the token address that will be withdraw
* @param _to is where the tokens will be sent to
* _value is the number of the token
*/
function withdrawToken(address _token, address _to, uint256 _value) public onlyOwner returns (bool) {
require(_to != address(0));
require(_token != address(0));
ERC20 tk = ERC20(_token);
tk.transfer(_to, _value);
emit WithdrawToken(_token, _to, _value);
return true;
}
/**
* @dev receive approval from an ERC20 token contract, and then gain the tokens,
* then take a record
*
* @param _from address The address which you want to send tokens from
* @param _value uint256 the amounts of tokens to be sent
* @param _token address the ERC20 token address
* @param _extraData bytes the extra data for the record
*/
// function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) public {
// require(_token != address(0));
// require(_from != address(0));
// ERC20 tk = ERC20(_token);
// require(tk.transferFrom(_from, this, _value));
// emit ReceiveDeposit(_from, _value, _token, _extraData);
// }
}
contract TokenDestructible is Ownable {
constructor() public payable { }
/**
* @notice Terminate contract and refund to owner
* @param _tokens List of addresses of ERC20 or ERC20Basic token contracts to
refund.
* @notice The called token contracts could try to re-enter this contract. Only
supply token contracts you trust.
*/
function destroy(address[] _tokens) public onlyOwner {
// Transfer tokens to owner
for (uint256 i = 0; i < _tokens.length; i++) {
ERC20Basic token = ERC20Basic(_tokens[i]);
uint256 balance = token.balanceOf(this);
token.transfer(owner, balance);
}
// Transfer Eth to owner and terminate contract
selfdestruct(owner);
}
}
contract Claimable is Ownable {
address public pendingOwner;
/**
* @dev Modifier throws if called by any account other than the pendingOwner.
*/
modifier onlyPendingOwner() {
require(msg.sender == pendingOwner);
_;
}
/**
* @dev Allows the current owner to set the pendingOwner address.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
pendingOwner = newOwner;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer.
*/
function claimOwnership() public onlyPendingOwner {
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
}
}
contract DepositWithdraw is Claimable, Withdrawable, TokenDestructible {
using SafeMath for uint256;
/**
* transaction record
*/
struct TransferRecord {
uint256 timeStamp;
address account;
uint256 value;
}
/**
* accumulated transferring amount record
*/
struct accumulatedRecord {
uint256 mul;
uint256 count;
uint256 value;
}
TransferRecord[] deposRecs; // record all the deposit tx data
TransferRecord[] withdrRecs; // record all the withdraw tx data
accumulatedRecord dayWithdrawRec; // accumulated amount record for one day
accumulatedRecord monthWithdrawRec; // accumulated amount record for one month
address wallet; // the binded withdraw address
event ReceiveDeposit(address _from, uint256 _value, address _token, bytes _extraData);
/**
* @dev constructor of the DepositWithdraw contract
* @param _wallet the binded wallet address to this depositwithdraw contract
*/
constructor(address _wallet) public {
require(_wallet != address(0));
wallet = _wallet;
}
/**
* @dev set the default wallet address
* @param _wallet the default wallet address binded to this deposit contract
*/
function setWithdrawWallet(address _wallet) onlyOwner public returns (bool) {
require(_wallet != address(0));
wallet = _wallet;
return true;
}
/**
* @dev util function to change bytes data to bytes32 data
* @param _data the bytes data to be converted
*/
function bytesToBytes32(bytes _data) public pure returns (bytes32 result) {
assembly {
result := mload(add(_data, 32))
}
}
/**
* @dev receive approval from an ERC20 token contract, take a record
*
* @param _from address The address which you want to send tokens from
* @param _value uint256 the amounts of tokens to be sent
* @param _token address the ERC20 token address
* @param _extraData bytes the extra data for the record
*/
function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) onlyOwner public {
require(_token != address(0));
require(_from != address(0));
ERC20 tk = ERC20(_token);
require(tk.transferFrom(_from, this, _value));
bytes32 timestamp = bytesToBytes32(_extraData);
deposRecs.push(TransferRecord(uint256(timestamp), _from, _value));
emit ReceiveDeposit(_from, _value, _token, _extraData);
}
// function authorize(address _token, address _spender, uint256 _value) onlyOwner public returns (bool) {
// ERC20 tk = ERC20(_token);
// require(tk.approve(_spender, _value));
// return true;
// }
/**
* @dev record withdraw into this contract
*
* @param _time the timstamp of the withdraw time
* @param _to is where the tokens will be sent to
* @param _value is the number of the token
*/
function recordWithdraw(uint256 _time, address _to, uint256 _value) onlyOwner public {
withdrRecs.push(TransferRecord(_time, _to, _value));
}
/**
* @dev check if withdraw amount is not valid
*
* @param _params the limitation parameters for withdraw
* @param _value is the number of the token
* @param _time the timstamp of the withdraw time
*/
function checkWithdrawAmount(address _params, uint256 _value, uint256 _time) public returns (bool) {
IDRCWalletMgrParams params = IDRCWalletMgrParams(_params);
require(_value <= params.singleWithdrawMax());
require(_value >= params.singleWithdrawMin());
uint256 daysCount = _time.div(86400); // one day of seconds
if (daysCount <= dayWithdrawRec.mul) {
dayWithdrawRec.count = dayWithdrawRec.count.add(1);
dayWithdrawRec.value = dayWithdrawRec.value.add(_value);
require(dayWithdrawRec.count <= params.dayWithdrawCount());
require(dayWithdrawRec.value <= params.dayWithdraw());
} else {
dayWithdrawRec.mul = daysCount;
dayWithdrawRec.count = 1;
dayWithdrawRec.value = _value;
}
uint256 monthsCount = _time.div(86400 * 30);
if (monthsCount <= monthWithdrawRec.mul) {
monthWithdrawRec.count = monthWithdrawRec.count.add(1);
monthWithdrawRec.value = monthWithdrawRec.value.add(_value);
require(monthWithdrawRec.value <= params.monthWithdraw());
} else {
monthWithdrawRec.mul = monthsCount;
monthWithdrawRec.count = 1;
monthWithdrawRec.value = _value;
}
return true;
}
/**
* @dev withdraw tokens, send tokens to target
*
* @param _token the token address that will be withdraw
* @param _params the limitation parameters for withdraw
* @param _time the timstamp of the withdraw time
* @param _to is where the tokens will be sent to
* _value is the number of the token
* _fee is the amount of the transferring costs
* _tokenReturn is the address that return back the tokens of the _fee
*/
function withdrawToken(address _token, address _params, uint256 _time, address _to, uint256 _value, uint256 _fee, address _tokenReturn) public onlyOwner returns (bool) {
require(_to != address(0));
require(_token != address(0));
require(_value > _fee);
// require(_tokenReturn != address(0));
require(checkWithdrawAmount(_params, _value, _time));
ERC20 tk = ERC20(_token);
uint256 realAmount = _value.sub(_fee);
require(tk.transfer(_to, realAmount));
if (_tokenReturn != address(0) && _fee > 0) {
require(tk.transfer(_tokenReturn, _fee));
}
recordWithdraw(_time, _to, realAmount);
emit WithdrawToken(_token, _to, realAmount);
return true;
}
/**
* @dev withdraw tokens, send tokens to target default wallet
*
* @param _token the token address that will be withdraw
* @param _params the limitation parameters for withdraw
* @param _time the timestamp occur the withdraw record
* @param _value is the number of the token
* _fee is the amount of the transferring costs
* —tokenReturn is the address that return back the tokens of the _fee
*/
function withdrawTokenToDefault(address _token, address _params, uint256 _time, uint256 _value, uint256 _fee, address _tokenReturn) public onlyOwner returns (bool) {
return withdrawToken(_token, _params, _time, wallet, _value, _fee, _tokenReturn);
}
/**
* @dev get the Deposit records number
*
*/
function getDepositNum() public view returns (uint256) {
return deposRecs.length;
}
/**
* @dev get the one of the Deposit records
*
* @param _ind the deposit record index
*/
function getOneDepositRec(uint256 _ind) public view returns (uint256, address, uint256) {
require(_ind < deposRecs.length);
return (deposRecs[_ind].timeStamp, deposRecs[_ind].account, deposRecs[_ind].value);
}
/**
* @dev get the withdraw records number
*
*/
function getWithdrawNum() public view returns (uint256) {
return withdrRecs.length;
}
/**
* @dev get the one of the withdraw records
*
* @param _ind the withdraw record index
*/
function getOneWithdrawRec(uint256 _ind) public view returns (uint256, address, uint256) {
require(_ind < withdrRecs.length);
return (withdrRecs[_ind].timeStamp, withdrRecs[_ind].account, withdrRecs[_ind].value);
}
}
contract DelayedClaimable is Claimable {
uint256 public end;
uint256 public start;
/**
* @dev Used to specify the time period during which a pending
* owner can claim ownership.
* @param _start The earliest time ownership can be claimed.
* @param _end The latest time ownership can be claimed.
*/
function setLimits(uint256 _start, uint256 _end) public onlyOwner {
require(_start <= _end);
end = _end;
start = _start;
}
/**
* @dev Allows the pendingOwner address to finalize the transfer, as long as it is called within
* the specified start and end time.
*/
function claimOwnership() public onlyPendingOwner {
require((block.number <= end) && (block.number >= start));
emit OwnershipTransferred(owner, pendingOwner);
owner = pendingOwner;
pendingOwner = address(0);
end = 0;
}
}
contract OwnerContract is DelayedClaimable {
Claimable public ownedContract;
address public pendingOwnedOwner;
// address internal origOwner;
/**
* @dev bind a contract as its owner
*
* @param _contract the contract address that will be binded by this Owner Contract
*/
function bindContract(address _contract) onlyOwner public returns (bool) {
require(_contract != address(0));
ownedContract = Claimable(_contract);
// origOwner = ownedContract.owner();
// take ownership of the owned contract
if (ownedContract.owner() != address(this)) {
ownedContract.claimOwnership();
}
return true;
}
/**
* @dev change the owner of the contract from this contract address to the original one.
*
*/
// function transferOwnershipBack() onlyOwner public {
// ownedContract.transferOwnership(origOwner);
// ownedContract = Claimable(address(0));
// origOwner = address(0);
// }
/**
* @dev change the owner of the contract from this contract address to another one.
*
* @param _nextOwner the contract address that will be next Owner of the original Contract
*/
function changeOwnershipto(address _nextOwner) onlyOwner public {
require(ownedContract != address(0));
if (ownedContract.owner() != pendingOwnedOwner) {
ownedContract.transferOwnership(_nextOwner);
pendingOwnedOwner = _nextOwner;
// ownedContract = Claimable(address(0));
// origOwner = address(0);
} else {
// the pending owner has already taken the ownership
ownedContract = Claimable(address(0));
pendingOwnedOwner = address(0);
}
}
/**
* @dev to confirm the owner of the owned contract has already been transferred.
*
*/
function ownedOwnershipTransferred() onlyOwner public returns (bool) {
require(ownedContract != address(0));
if (ownedContract.owner() == pendingOwnedOwner) {
// the pending owner has already taken the ownership
ownedContract = Claimable(address(0));
pendingOwnedOwner = address(0);
return true;
} else {
return false;
}
}
}
contract DRCWalletManager is OwnerContract, Withdrawable, TokenDestructible {
using SafeMath for uint256;
/**
* withdraw wallet description
*/
// struct WithdrawWallet {
// bytes32 name;
// address walletAddr;
// }
/**
* Deposit data storage
*/
// struct DepositRepository {
// // uint256 balance;
// uint256 frozen;
// WithdrawWallet[] withdrawWallets;
// // mapping (bytes32 => address) withdrawWallets;
// }
// mapping (address => DepositRepository) depositRepos;
// mapping (address => address) public walletDeposits;
// mapping (address => bool) public frozenDeposits;
ERC20 public tk; // the token will be managed
IDRCWalletMgrParams public params; // the parameters that the management needs
IDRCWalletStorage public walletStorage; // the deposits and wallets data stored in a contract
event CreateDepositAddress(address indexed _wallet, address _deposit);
event FrozenTokens(address indexed _deposit, bool _freeze, uint256 _value);
event ChangeDefaultWallet(address indexed _oldWallet, address _newWallet);
/**
* @dev initialize this contract with token, parameters and storage address
*
* @param _token the token address that will be withdraw
* @param _walletParams the wallet management parameters
*/
function initialize(address _token, address _walletParams, address _walletStorage) onlyOwner public returns (bool) {
require(_token != address(0));
require(_walletParams != address(0));
tk = ERC20(_token);
params = IDRCWalletMgrParams(_walletParams);
walletStorage = IDRCWalletStorage(_walletStorage);
return true;
}
/**
* @dev create deposit contract address for the default withdraw wallet
*
* @param _wallet the binded default withdraw wallet address
*/
function createDepositContract(address _wallet) onlyOwner public returns (address) {
require(_wallet != address(0));
DepositWithdraw deposWithdr = new DepositWithdraw(_wallet); // new contract for deposit
address _deposit = address(deposWithdr);
// walletDeposits[_wallet] = _deposit;
// WithdrawWallet[] storage withdrawWalletList = depositRepos[_deposit].withdrawWallets;
// withdrawWalletList.push(WithdrawWallet("default wallet", _wallet));
// // depositRepos[_deposit].balance = 0;
// depositRepos[_deposit].frozen = 0;
walletStorage.addDeposit(_wallet, _deposit);
// deposWithdr.authorize(address(tk), this, 1e27); // give authorization to owner contract
emit CreateDepositAddress(_wallet, _deposit);
return _deposit;
}
/**
* @dev deposit a value of funds to the deposit address
*
* @param _deposit the deposit address
* @param _increase increase or decrease the value
* @param _value the deposit funds value
*/
function doDeposit(address _deposit, bool _increase, uint256 _value) onlyOwner public returns (bool) {
return (_increase
? walletStorage.increaseBalance(_deposit, _value)
: walletStorage.decreaseBalance(_deposit, _value));
}
/**
* @dev get deposit contract address by using the default withdraw wallet
*
* @param _wallet the binded default withdraw wallet address
*/
function getDepositAddress(address _wallet) onlyOwner public view returns (address) {
require(_wallet != address(0));
// address deposit = walletDeposits[_wallet];
// return deposit;
return walletStorage.walletDeposits(_wallet);
}
/**
* @dev get deposit balance and frozen amount by using the deposit address
*
* @param _deposit the deposit contract address
*/
function getDepositInfo(address _deposit) onlyOwner public view returns (uint256, uint256) {
require(_deposit != address(0));
uint256 _balance = walletStorage.balanceOf(_deposit);
// uint256 frozenAmount = depositRepos[_deposit].frozen;
uint256 frozenAmount = walletStorage.frozenAmount(_deposit);
// depositRepos[_deposit].balance = _balance;
return (_balance, frozenAmount);
}
/**
* @dev get the number of withdraw wallet addresses bindig to the deposit contract address
*
* @param _deposit the deposit contract address
*/
function getDepositWithdrawCount(address _deposit) onlyOwner public view returns (uint) {
require(_deposit != address(0));
// WithdrawWallet[] storage withdrawWalletList = depositRepos[_deposit].withdrawWallets;
// uint len = withdrawWalletList.length;
uint len = walletStorage.walletsNumber(_deposit);
return len;
}
/**
* @dev get the withdraw wallet addresses list binding to the deposit contract address
*
* @param _deposit the deposit contract address
* @param _indices the array of indices of the withdraw wallets
*/
function getDepositWithdrawList(address _deposit, uint[] _indices) onlyOwner public view returns (bytes32[], address[]) {
require(_indices.length != 0);
bytes32[] memory names = new bytes32[](_indices.length);
address[] memory wallets = new address[](_indices.length);
for (uint i = 0; i < _indices.length; i = i.add(1)) {
// WithdrawWallet storage wallet = depositRepos[_deposit].withdrawWallets[_indices[i]];
// names[i] = wallet.name;
// wallets[i] = wallet.walletAddr;
names[i] = walletStorage.walletName(_deposit, i);
wallets[i] = walletStorage.wallet(_deposit, i);
}
return (names, wallets);
}
/**
* @dev change the default withdraw wallet address binding to the deposit contract address
*
* @param _oldWallet the previous default withdraw wallet
* @param _newWallet the new default withdraw wallet
*/
function changeDefaultWithdraw(address _oldWallet, address _newWallet) onlyOwner public returns (bool) {
require(_oldWallet != address(0));
require(_newWallet != address(0));
address deposit = walletStorage.walletDeposits(_oldWallet);
DepositWithdraw deposWithdr = DepositWithdraw(deposit);
require(deposWithdr.setWithdrawWallet(_newWallet));
// WithdrawWallet[] storage withdrawWalletList = depositRepos[deposit].withdrawWallets;
// withdrawWalletList[0].walletAddr = _newWallet;
bool res = walletStorage.changeDefaultWallet(_oldWallet, _newWallet);
emit ChangeDefaultWallet(_oldWallet, _newWallet);
return res;
}
/**
* @dev freeze the tokens in the deposit address
*
* @param _deposit the deposit address
* @param _freeze to freeze or release
* @param _value the amount of tokens need to be frozen
*/
function freezeTokens(address _deposit, bool _freeze, uint256 _value) onlyOwner public returns (bool) {
// require(_deposit != address(0));
// frozenDeposits[_deposit] = _freeze;
// if (_freeze) {
// depositRepos[_deposit].frozen = depositRepos[_deposit].frozen.add(_value);
// } else {
// require(_value <= depositRepos[_deposit].frozen);
// depositRepos[_deposit].frozen = depositRepos[_deposit].frozen.sub(_value);
// }
bool res = walletStorage.freezeTokens(_deposit, _freeze, _value);
emit FrozenTokens(_deposit, _freeze, _value);
return res;
}
/**
* @dev withdraw the tokens from the deposit address to default wallet with charge fee
*
* @param _deposit the deposit address
* @param _time the timestamp the withdraw occurs
* @param _value the amount of tokens need to be frozen
* @param _check if we will check the value is valid or meet the limit condition
*/
function withdrawWithFee(address _deposit, uint256 _time, uint256 _value, bool _check) onlyOwner public returns (bool) {
// WithdrawWallet[] storage withdrawWalletList = depositRepos[_deposit].withdrawWallets;
// return withdrawWithFee(_deposit, _time, withdrawWalletList[0].name, withdrawWalletList[0].walletAddr, _value, _check);
bytes32 defaultWalletName = walletStorage.walletName(_deposit, 0);
address defaultWallet = walletStorage.wallet(_deposit, 0);
return withdrawWithFee(_deposit, _time, defaultWalletName, defaultWallet, _value, _check);
}
/**
* @dev check if the wallet name is not matching the expected wallet address
*
* @param _deposit the deposit address
* @param _name the withdraw wallet name
* @param _to the withdraw wallet address
*/
function checkWithdrawAddress(address _deposit, bytes32 _name, address _to) public view returns (bool, bool) {
// uint len = depositRepos[_deposit].withdrawWallets.length;
uint len = walletStorage.walletsNumber(_deposit);
for (uint i = 0; i < len; i = i.add(1)) {
// WithdrawWallet memory wallet = depositRepos[_deposit].withdrawWallets[i];
// if (_name == wallet.name) {
// return(true, (_to == wallet.walletAddr));
// }
// if (_to == wallet.walletAddr) {
// return(true, true);
// }
bytes32 walletName = walletStorage.walletName(_deposit, i);
address walletAddr = walletStorage.wallet(_deposit, i);
if (_name == walletName) {
return(true, (_to == walletAddr));
}
if (_to == walletAddr) {
return(false, true);
}
}
return (false, false);
}
/**
* @dev withdraw tokens from this contract, send tokens to target withdraw wallet
*
* @param _deposWithdr the deposit contract that will record withdrawing
* @param _time the timestamp occur the withdraw record
* @param _to the address the token will be transfer to
* @param _value the token transferred value
*/
function withdrawFromThis(DepositWithdraw _deposWithdr, uint256 _time, address _to, uint256 _value) private returns (bool) {
uint256 fee = params.chargeFee();
uint256 realAmount = _value.sub(fee);
address tokenReturn = params.chargeFeePool();
if (tokenReturn != address(0) && fee > 0) {
// require(tk.transfer(tokenReturn, fee));
require(walletStorage.withdrawToken(tk, tokenReturn, fee));
}
// require (tk.transfer(_to, realAmount));
require(walletStorage.withdrawToken(tk, _to, realAmount));
_deposWithdr.recordWithdraw(_time, _to, realAmount);
return true;
}
/**
* @dev withdraw tokens, send tokens to target withdraw wallet
*
* @param _deposit the deposit address that will be withdraw from
* @param _time the timestamp occur the withdraw record
* @param _name the withdraw address alias name to verify
* @param _to the address the token will be transfer to
* @param _value the token transferred value
* @param _check if we will check the value is valid or meet the limit condition
*/
function withdrawWithFee(address _deposit,
uint256 _time,
bytes32 _name,
address _to,
uint256 _value,
bool _check) onlyOwner public returns (bool) {
require(_deposit != address(0));
require(_to != address(0));
uint256 totalBalance = walletStorage.balanceOf(_deposit);
uint256 frozen = walletStorage.frozenAmount(_deposit);
// uint256 available = totalBalance.sub(frozen);
// require(_value <= available);
if (_check) {
require(_value <= totalBalance.sub(frozen));
}
uint256 _balance = tk.balanceOf(_deposit);
bool exist;
bool correct;
// WithdrawWallet[] storage withdrawWalletList = depositRepos[_deposit].withdrawWallets;
(exist, correct) = checkWithdrawAddress(_deposit, _name, _to);
if(!exist) {
// withdrawWalletList.push(WithdrawWallet(_name, _to));
if (!correct) {
walletStorage.addWithdraw(_deposit, _name, _to);
} else {
walletStorage.changeWalletName(_deposit, _name, _to);
}
} else {
require(correct, "wallet address must be correct with wallet name!");
}
DepositWithdraw deposWithdr = DepositWithdraw(_deposit);
/**
* if deposit address doesn't have enough tokens to withdraw,
* then withdraw from this contract. Record this in the independent deposit contract.
*/
if (_value > _balance) {
require(deposWithdr.checkWithdrawAmount(address(params), _value, _time));
if(_balance > 0) {
require(deposWithdr.withdrawToken(address(tk), address(walletStorage), _balance));
}
require(withdrawFromThis(deposWithdr, _time, _to, _value));
// return true;
} else {
require(deposWithdr.withdrawToken(address(tk), address(params), _time, _to, _value, params.chargeFee(), params.chargeFeePool()));
}
return walletStorage.decreaseBalance(_deposit, _value);
}
/**
* @dev destory the old depoist contract and take back the tokens
*
* @param _deposit the deposit address
*/
function destroyDepositContract(address _deposit) onlyOwner public returns (bool) {
require(_deposit != address(0));
DepositWithdraw deposWithdr = DepositWithdraw(_deposit);
address[] memory tokens = new address[](1);
tokens[0] = address(tk);
deposWithdr.destroy(tokens);
return walletStorage.removeDeposit(_deposit);
}
}
contract ERC20Basic {
function totalSupply() public view returns (uint256);
function balanceOf(address _who) public view returns (uint256);
function transfer(address _to, uint256 _value) public returns (bool);
event Transfer(address indexed from, address indexed to, uint256 value);
}
contract ERC20 is ERC20Basic {
function allowance(address _owner, address _spender)
public view returns (uint256);
function transferFrom(address _from, address _to, uint256 _value)
public returns (bool);
function approve(address _spender, uint256 _value) public returns (bool);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
}