Problems using transfer in Solidity - ethereum

function withdraw(uint amount) public returns (bool){
uint cethAmount = amount;
uint bosAmount = cethAmount * 11;
require(bosAmount <= balances[msg.sender]);
require(address(this).balance >= cethAmount);
balances[msg.sender] -= bosAmount;
totalSupply_ -= bosAmount;
payable(msg.sender).transfer(cethAmount);
return true;
}
This piece of code aims to take an unsigned integer as an input and send that amount back to the user.
The code executes up to line 7 (totalSupply_ -= bosAmount;), but after that no cTH is transferred and the output is not true.
This throws no errors also

Related

How to add a uint T in constructor that will be a time constant inside my smart contract?

I need a time constant to calculate timestamps for deposit, withdrawal, and reward sub-pools. this time constant called T will start from contract deployment and will not be specific to one address/user. I.e rewards(R) are divided into 3 sub-pools: R1 = 20% available after 2T has passed since contract deployment, R2 = 30% available after 3T has passed since contract deployment, R3= 50% available after 4T has passed since contract deployment. I need this variable to be in minutes, for example, sender inputs 3 I want the time between each timestamp to be 3, like deposit in the first T, withdrawal after 3T. How to set it in minutes?
Here is the state variable
uint256 public T;
Here is the constructor
constructor(address stakingToken, address rewardsToken, uint256 timeConstant) {
s_stakingToken = IERC20(stakingToken);
s_rewardsToken = IERC20(rewardsToken);
initialTime = block.timestamp;
T = timeConstant;
}
My full code
error TransferFailed();
error NeedsMoreThanZero();
contract Staking is ReentrancyGuard {
IERC20 public s_rewardsToken;
IERC20 public s_stakingToken;
// This is the reward token per seco
nd
// Which will be multiplied by the tokens the user staked divided by the total
// This ensures a steady reward rate of the platform
// So the more users stake, the less for everyone who is staking.
uint256 public constant REWARD_RATE = 100;
uint256 public s_lastUpdateTime;
uint256 public s_rewardPerTokenStored;
//uint256 public constant T = 3;
uint256 public initialTime;
uint256 public T;
mapping(address => uint256) public s_userRewardPerTokenPaid;
mapping(address => uint256) public s_rewards;
uint256 private s_totalSupply;
mapping(address => uint256) public s_balances; // someones address => how much he staked
event Staked(address indexed user, uint256 indexed amount);
event WithdrewStake(address indexed user, uint256 indexed amount);
event RewardsClaimed(address indexed user, uint256 indexed amount);
constructor(address stakingToken, address rewardsToken, uint256 timeConstant) {
s_stakingToken = IERC20(stakingToken);
s_rewardsToken = IERC20(rewardsToken);
initialTime = block.timestamp;
T = timeConstant;
}
/**
* #notice How much reward a token gets based on how long it's been in and during which "snapshots"
*/
function rewardPerToken() public view returns (uint256) {
if (s_totalSupply == 0) {
return s_rewardPerTokenStored;
}
return
s_rewardPerTokenStored +
(((block.timestamp - s_lastUpdateTime) * REWARD_RATE * 1e18) / s_totalSupply);
}
/**
* #notice How much reward a user has earned
*/
function earned(address account) public view returns (uint256) {
uint256 nowTime = block.timestamp-initialTime;
require(nowTime > 2*T);
if (nowTime > 2*T && nowTime <= 3*T) {
return
((((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
1e18) + s_rewards[account]) / 5 );
} else if
(nowTime > 3*T && nowTime <= 4*T) {
return
((((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
1e18) + s_rewards[account]) / 2 );
} else {
return
(((s_balances[account] * (rewardPerToken() - s_userRewardPerTokenPaid[account])) /
1e18) + s_rewards[account]);
}
}
/**
* #notice Deposit tokens into this contract
* #param amount | How much to stake
*/
function stake(uint256 amount)
external
updateReward(msg.sender)
nonReentrant
moreThanZero(amount)
{
//from T0 to T deposit is available
uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
require(nowTime < T);
s_totalSupply += amount;
// increasing how much they are staking for how much they staked each time.
s_balances[msg.sender] += amount;
emit Staked(msg.sender, amount);
// sending an amount of token from an address to this contract
bool success = s_stakingToken.transferFrom(msg.sender, address(this), amount);
// if not successfully sent, return an error.
// using the below code instead of "require(success, "Failed")" reduces gas fees, since it doesn't output a string.
if (!success) {
revert TransferFailed(); // revert resets everything done in a failed transaction.
}
}
/**
* #notice Withdraw tokens from this contract
* #param amount | How much to withdraw
*/
function withdraw(uint256 amount) external updateReward(msg.sender) nonReentrant {
// from 2T the user can reward his tokens
uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
require(nowTime > 2* T);
s_totalSupply -= amount;
s_balances[msg.sender] -= amount;
emit WithdrewStake(msg.sender, amount);
// transfer: send tokens from contract back to msg.sender.
bool success = s_stakingToken.transfer(msg.sender, amount);
if (!success) {
revert TransferFailed(); // revert resets everything done in a failed transaction.
}
}
/**
* #notice User claims their tokens
*/
function claimReward() external updateReward(msg.sender) nonReentrant {
uint256 reward = s_rewards[msg.sender];
s_rewards[msg.sender] = 0;
emit RewardsClaimed(msg.sender, reward);
bool success = s_rewardsToken.transfer(msg.sender, reward);
if (!success) {
revert TransferFailed(); // revert resets everything done in a failed transaction.
}
}
/********************/
/* Modifiers Functions */
/********************/
modifier updateReward(address account) {
s_rewardPerTokenStored = rewardPerToken();
s_lastUpdateTime = block.timestamp;
s_rewards[account] = earned(account);
s_userRewardPerTokenPaid[account] = s_rewardPerTokenStored;
_;
}
modifier moreThanZero(uint256 amount) {
if (amount == 0) {
revert NeedsMoreThanZero();
}
_;
}
/********************/
/* Getter Functions */
/********************/
// Ideally, we'd have getter functions for all our s_ variables we want exposed, and set them all to private.
// But, for the purpose of this demo, we've left them public for simplicity.
function getStaked(address account) public view returns (uint256) {
return s_balances[account];
}
}
Firstly maintain a map for storing the time for each user. Then make functions like depositTimeSet , withdrawalTimeSet for storing different time for different user. While despositing update the variable and while withdraw check the time has exceed or not.
struct Users {
uint dipositTime;
uint withDrawTime;
uint lastDepositTime;
}
mapping(address => Users ) users;
function depositeTimeSet(uint t) {
users[msg.sender].dipositTime = t minutes;
withdrawalTimeSet(t);
}
function withdrawalTimeSet(uint t) {
users[msg.sender].withDrawTime = 3 * t minutes
}
function deposite() {
transferFrom(msg.sender,address(this));
depositeTimeSet(3); // considering sender send 3
users[msg.sender].lastDepositTime = now;
}
function withdraw() {
if(
now > users[msg.sender].lastDepositTime +
users[msg.sender].withDrawTime,"too early for withdraw
request"
)
transferFrom(address(this),msg.sender);
}
You can see THIS one might be helpful
You can see THIS resource for time unit in solidity

Large amount of wei not being processed by Solidity on Remix

U am trying to implement liquidity pools with Solidity, and had written two functions : addLiquidity() and withdraw() for it. However, the withdraw function doesn't seem to work with Remix when I try to withdraw large sums (like 0.001 ether), but works with sums like 150000 wei or something.
It doesn't seem to be an issue with Remix's IDE (i read somehere it has a problem working with large numbers), because even when I pass the 149999998499999985165 wei in double quotes (e.g. "149999998499999985165") the same error appears.
The error states: "Gas estimation errored with the following message (see below). The transaction execution will likely fail. Do you want to force sending?
execution reverted { "originalError": { "code": 3, "data": "0x4e487b710000000000000000000000000000000000000000000000000000000000000011", "message": "execution reverted" } }"
Code:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface linkStandardToken {
function transferFrom(address _from, address _to, uint256 _value) external returns (bool) ;
function balanceOf(address _owner) external returns (uint256) ;
function transfer(address to, uint tokens) external returns (bool success);
}
contract Uniswap
{
using SafeMath for uint256;
uint public totalLiquidity;
uint public balance;
address public owner;
address public tokenAddress = 0xaFF4481D10270F50f203E0763e2597776068CBc5; // REPLACE WITH ACTUAL TOKEN
linkStandardToken token;
bool public poolInit = false;
uint public protocolFees = 30; //in basis points i.e. divide by 10,000
uint public tempTokenPrice = 0;
mapping(address => uint) public liquidityBalances;
constructor()
{
owner = msg.sender;
token = linkStandardToken(tokenAddress);
}
function init(uint _tokenAmount) public payable
{
require(totalLiquidity == 0, "Already initialized");
require(_tokenAmount > 0, "Token amount must be > 0");
require(msg.value > 0, "Eth amount must be > 0");
totalLiquidity = totalLiquidity.add(_tokenAmount);
balance = balance.add(msg.value);
poolInit = true;
require(token.transferFrom(msg.sender, address(this), _tokenAmount), "Can't transfer tokens to contract");
setTokenToEthPrice();
}
fallback() payable external{}
receive() payable external{}
// _amount - input token amount, X - input token reserve, Y- output token reserve
function _swap(uint _amount, uint X , uint Y) public view returns (uint)
{
// code omitted
}
function swapEthToToken(/*uint _inputEthAmount*/) public payable
{
// code omitted
}
function swapTokenToEth(uint _tokenAmount) public payable
{
// code omitted
}
function setTokenToEthPrice() public // set to internal later
{
tempTokenPrice = _swap(1, balance , token.balanceOf(address(this))) ;
}
function addLiquidity(uint maxTokens) payable public returns (uint)
{
require(msg.value > 0, "msg.val <= 0");
require(totalLiquidity > 0, "totalLiquidity <= 0");
uint tokensBalance = getTokenBalance(address(this));
uint tokensToAdd = msg.value.mul(tokensBalance)/balance;
require(tokensToAdd <= maxTokens , "tokensToAdd > maxTokens");
balance= balance.add(msg.value);
uint mintedLiquidity = msg.value.mul(totalLiquidity)/balance;
liquidityBalances[msg.sender] = liquidityBalances[msg.sender].add(mintedLiquidity);
totalLiquidity = totalLiquidity.add(mintedLiquidity);
require(linkStandardToken(
0xaFF4481D10270F50f203E0763e2597776068CBc5)
.transferFrom(msg.sender, address(this), tokensToAdd));
return mintedLiquidity;
}
function withdraw9(uint256 amount, uint minimumEth, uint minimumTokens) public
{
require(liquidityBalances[msg.sender] >= amount, "Liquidity Balance of msg send < amount");
require(totalLiquidity > 0, "totalLiquidity <= 0");
uint tokenBalance = getTokenBalance(address(this));
uint temp = amount.mul(totalLiquidity);
uint etherToTransfer = temp.div(balance);
uint temp1 = amount.mul(totalLiquidity);
uint tokensToTransfer = temp1.div(tokenBalance);
require(minimumEth < etherToTransfer, "minimumEth >= etherToTransfer");
require(minimumTokens < tokensToTransfer, "minimumTokens >= tokensToTransfer");
balance = balance - etherToTransfer;
totalLiquidity = totalLiquidity.sub(amount);
liquidityBalances[msg.sender] = liquidityBalances[msg.sender].sub(amount);
address payable addr = payable(msg.sender);
addr.transfer(etherToTransfer);
require(linkStandardToken(
0xaFF4481D10270F50f203E0763e2597776068CBc5)
.transfer(msg.sender, tokensToTransfer), "Token transfer unsuccesful");
}
}
library SafeMath {
....// code emitted for compactness
}
As i can see in the last line of widthdraw9 function you use .transfer in order to send ether to some contract. I guess this contract have some code in receive function, so .transfer is not your choose. This function has a gas limitation and any code in receive can break it. If i correctly saw the problem then you should use .call function with enough amount of gas. More about these functions.
The "Gas estimation errored" message doesn't necessarily mean that the problem is with the amount of gas given, just that it hit some error while estimating the amount of gas needed.
The originalError.data has "0x4e487b71...". Looking up those high order 4 bytes on 4byte.directory shows that it's the signature for Panic(uint256), and the code in the low order bytes is "...00011" so the error code is 0x11 (17 decimal). The Solidity doc lists these codes, indicating:
0x11: If an arithmetic operation results in underflow or overflow outside of an unchecked { ... } block.
In the code, balance is not declared in uint etherToTransfer = temp.div(balance). If it's a state variable, could it be 0? Or is there a missing uint256 balance = liquidityBalances[msg.sender]?

Does Solidity function with payable modifier allow to perform msg.sender.call{}

Found out that there are error in my own code. Answered my own question
I am beginner of Solidity programming, and came across with reentrancy risk. I have tested script below in remix and it works per expectation.
https://solidity-by-example.org/hacks/re-entrancy/
contract EtherStore {
// Withdrawal limit = 1 ether / week
uint constant public WITHDRAWAL_LIMIT = 1 ether;
mapping(address => uint) public lastWithdrawTime;
mapping(address => uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
}
function withdraw(uint _amount) public {
require(balances[msg.sender] >= _amount);
require(_amount <= WITHDRAWAL_LIMIT);
require(block.timestamp >= lastWithdrawTime[msg.sender] + 1 weeks);
(bool sent, ) = msg.sender.call{value: _amount}("");
require(sent, "Failed to send Ether");
balances[msg.sender] -= _amount;
lastWithdrawTime[msg.sender] = block.timestamp;
}
// Helper function to check the balance of this contract
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
The attack contract stop working (return false) the moment msg.sender.call function is included at the end of deposit function (see below code)
However, if the new deposit function is called directly via remix, the msg.sender.call function will go through smoothly without any exceptions
contract EtherStore {
// Withdrawal limit = 1 ether / week
uint constant public WITHDRAWAL_LIMIT = 1 ether;
mapping(address => uint) public lastWithdrawTime;
mapping(address => uint) public balances;
function deposit() public payable {
balances[msg.sender] += msg.value;
(bool sent, ) = msg.sender.call{value: 1 ether}("");
require(sent, "Failed to send Ether");
}
function withdraw(uint _amount) public {
require(balances[msg.sender] >= _amount);
require(_amount <= WITHDRAWAL_LIMIT);
require(block.timestamp >= lastWithdrawTime[msg.sender] + 1 weeks);
(bool sent, ) = msg.sender.call{value: _amount}("");
require(sent, "Failed to send Ether");
balances[msg.sender] -= _amount;
lastWithdrawTime[msg.sender] = block.timestamp;
}
// Helper function to check the balance of this contract
function getBalance() public view returns (uint) {
return address(this).balance;
}
}
May i check if anyone know what is causing the behavioural differences in both function call.
My objective of testing the new deposit() function is to check if attacker can launch direct attack using single deposit() call, with the assumption that deposit() function will transfer small balance back to msg.sender.
According to my understanding, the expected behavior should be calling the msg.sender fallback() function. But this doesnt happen in the test (remix), instead it returns false straight away
Thanks in advance
**Found out that there are bugs in my logic, thanks for the answe
The two deposit functions are
old
function deposit() public payable {
balances[msg.sender] += msg.value;
}
new
function deposit() public payable {
balances[msg.sender] += msg.value;
(bool sent, ) = msg.sender.call{value: 1 ether}("");
require(sent, "Failed to send Ether");
}
In the second function you add a check which prevents against re-entrancy attacks with custom fallback function on msg.sender.
{value: 1 ether}("");
https://ethereum.stackexchange.com/questions/42521/what-does-msg-sender-call-do-in-solidity
https://consensys.github.io/smart-contract-best-practices/known_attacks/
https://quantstamp.com/blog/what-is-a-re-entrancy-attack

Solidity, assigning multiple values with "=" in the same line

Where can I get a detailed explaination of this weird assignment in solidity?
The one in the constructor. Multiple = = = .
Couldn't find anything in the official docs.
contract Token {
mapping(address => uint) balances;
uint public totalSupply;
uint public anotherUint = 10;
constructor(uint _initialSupply, uint _anotherUint) {
balances[msg.sender] = totalSupply = anotherUint = _initialSupply = _anotherUint;
}
function transfer(address _to, uint _value) public returns (bool) {
require(balances[msg.sender] - _value >= 0);
balances[msg.sender] -= _value;
balances[_to] += _value;
return true;
}
function balanceOf(address _owner) public view returns (uint balance) {
return balances[_owner];
}
}
It's an example of chained assignment, that is available in many other programming languages.
Example in JS:
// copy paste this to your browser devtools console to explore how it works
let _initialSupply = 5;
let _anotherUint = 10;
let anotherUint;
let totalSupply;
const balance = totalSupply = anotherUint = _initialSupply = _anotherUint;
It assignes:
value of _anotherUint to _initialSupply (overriding the value passed in constructor)
(the new) value of _initialSupply to anotherUint
value of anotherUint to totalSupply
and finally the value of totalSupply to the balances[msg.sender] (or in my JS code to balance)
Solidity docs don't seem to cover this topic, but it's not explicit to Solidity only.

why can't transfer token in the GetReward function in eqzip crowdsale?

The following is my contract after I deploy eqcoin contract and eqzip contract I have tried use account2 send ether to eqzip contract then the beneficiary can get the ether but when the crowdsale finished. I tried use account2 execute the GetReward function to get the reward but after I execute the GetReward function account2 didn't get the token why?
Could you please review my source code and tell me what's wrong with my contract?Thank you!
Eqcoin contract:
pragma solidity ^0.4.21;
interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; }
contract Eqcoin {
// Public variables of the token
// string public constant whitePaperForEqcoin = "The total supply of eqcoin is 100000 which corresponds to 1% of Eqzip stock,\
// 0.01% of Eqcoin stock and 10% of Lostk stock...\
// The decimals of Eqcoin is 18...\
// ";
string public name = "eqcoin";
string public symbol = "eqc";
uint8 public decimals = 18;
// 18 decimals is the strongly suggested default, avoid changing it
uint256 public totalSupply;
// This creates an array with all balances
mapping (address => uint256) public balanceOf;
mapping (address => mapping (address => uint256)) public allowance;
// The owner's address
// address private owner;
// This generates a public event on the blockchain that will notify clients
event Transfer(address indexed from, address indexed to, uint256 value);
// This notifies clients about the amount burnt
event Burn(address indexed from, uint256 value);
// The following is test stub comment when release
// string public ownerAddress;
event Log(string log, address _address, uint256 value);
/**
* Constructor function
*
* Initializes contract with initial supply tokens to the creator of the contract
*/
function Eqcoin(uint256 initialSupply,
string tokenName,
string tokenSymbol) public {
totalSupply = initialSupply * 10 ** uint256(decimals); // Update total supply with the decimal amount
balanceOf[msg.sender] = totalSupply; // Give the creator all initial tokens
// owner = msg.sender; // Set the owner
// ownerAddress = toAsciiString(msg.sender);
name = tokenName;
symbol = tokenSymbol;
}
/**
* Internal transfer, only can be called by this contract
*/
function _transfer(address _from, address _to, uint _value) internal {
emit Log("_transfer", _to, _value);
// Prevent transfer to 0x0 address. Use burn() instead
require(_to != 0x0);
// Check if the sender has enough
require(balanceOf[_from] >= _value);
// Check for overflows
require(balanceOf[_to] + _value >= balanceOf[_to]);
// Save this for an assertion in the future
uint previousBalances = balanceOf[_from] + balanceOf[_to];
// Subtract from the sender
balanceOf[_from] -= _value;
// Add the same to the recipient
balanceOf[_to] += _value;
emit Transfer(_from, _to, _value);
// Asserts are used to use static analysis to find bugs in your code. They should never fail
assert(balanceOf[_from] + balanceOf[_to] == previousBalances);
}
/**
* Transfer tokens
*
* Send `_value` tokens to `_to` from your account
*
* #param _to The address of the recipient
* #param _value the amount to send
*/
function transfer(address _to, uint256 _value) public {
emit Log("transfer", msg.sender, _value);
_transfer(msg.sender, _to, _value);
}
/**
* Transfer tokens from other address
*
* Send `_value` tokens to `_to` on behalf of `_from`
*
* #param _from The address of the sender
* #param _to The address of the recipient
* #param _value the amount to send
*/
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
require(_value <= allowance[_from][msg.sender]); // Check allowance
allowance[_from][msg.sender] -= _value;
_transfer(_from, _to, _value);
return true;
}
/**
* Set allowance for other address
*
* Allows `_spender` to spend no more than `_value` tokens on your behalf
*
* #param _spender The address authorized to spend
* #param _value the max amount they can spend
*/
function approve(address _spender, uint256 _value) public
returns (bool success) {
allowance[msg.sender][_spender] = _value;
return true;
}
/**
* Set allowance for other address and notify
*
* Allows `_spender` to spend no more than `_value` tokens on your behalf, and then ping the contract about it
*
* #param _spender The address authorized to spend
* #param _value the max amount they can spend
* #param _extraData some extra information to send to the approved contract
*/
function approveAndCall(address _spender, uint256 _value, bytes _extraData)
public
returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
}
// /**
// * Destroy tokens
// *
// * Remove `_value` tokens from the system irreversibly
// *
// * #param _value the amount of money to burn
// */
// function burn(uint256 _value) public returns (bool success) {
// if(balanceOf[msg.sender] < _value){
// return;
// }
// balanceOf[msg.sender] -= _value; // Subtract from the sender
// if(msg.sender == owner){
// totalSupply -= _value; // Updates totalSupply
// }
// emit Burn(msg.sender, _value);
// return true;
// }
/**
* Destroy tokens
*
* Remove `_value` tokens from the system irreversibly
*
* #param _value the amount of money to burn
*/
function burn(uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value); // Check if the sender has enough
balanceOf[msg.sender] -= _value; // Subtract from the sender
totalSupply -= _value; // Updates totalSupply
emit Burn(msg.sender, _value);
return true;
}
/**
* Destroy tokens from other account
*
* Remove `_value` tokens from the system irreversibly on behalf of `_from`.
*
* #param _from the address of the sender
* #param _value the amount of money to burn
*/
function burnFrom(address _from, uint256 _value) public returns (bool success) {
require(balanceOf[_from] >= _value); // Check if the targeted balance is enough
require(_value <= allowance[_from][msg.sender]); // Check allowance
balanceOf[_from] -= _value; // Subtract from the targeted balance
allowance[_from][msg.sender] -= _value; // Subtract from the sender's allowance
totalSupply -= _value; // Update totalSupply
emit Burn(_from, _value);
return true;
}
function getTotalSupply() public constant returns (uint256 _totalSupply){
return totalSupply;
}
// function getOwner() public constant returns(address _address){
// return owner;
// }
// the following is test stub comment when release
// function toAsciiString(address x) internal pure returns (string) {
// bytes memory s = new bytes(40);
// for (uint i = 0; i < 20; i++) {
// byte b = byte(uint8(uint(x) / (2**(8*(19 - i)))));
// byte hi = byte(uint8(b) / 16);
// byte lo = byte(uint8(b) - 16 * uint8(hi));
// s[2*i] = char(hi);
// s[2*i+1] = char(lo);
// }
// return string(s);
// }
// function char(byte b) internal pure returns (byte c) {
// if (b < 10) return byte(uint8(b) + 0x30);
// else return byte(uint8(b) + 0x57);
// }
}
Eqzip crowdsale contract:
pragma solidity ^0.4.21;
interface token {
function transfer(address receiver, uint amount) external;
function getTotalSupply() external returns (uint256 _totalSupply);
// function getOwner() external returns(address _address);
}
contract EqzipCrowdsale {
string public constant whitePaperForEqzip = "The total supply of eqcoin is 100000 which corresponds to: \n\
1. 1% of Eqzip stock. \n\
2. 0.01% of Eqcoin stock. \n\
3. 10% of Lostk stock. \n\
4. Get the EQC corresponding to the price of eqcoin ico. \n\
5. If the Ether from one person's investment is greater than or equal to 333, \
hope life offers one cloned resurrection place (only 3 places, take the top 3). \n\
6. Hired Hope Media to provide Growth Hacker, product design, and business architecture design for Ethereum. \n\
7. Prior to joining eqzip work, under the same conditions to participate in the next round of financing eqzip. \n\
The decimals of Eqcoin is 18... \n\
owner: Xun Wang \n\
wechat: nju20006 \n\
email: 10509759#qq.com \n\
URL: www.eqzip.com www.eqzip.cn www.lostk.com www.lostk.cn github.com/eqzip/eqcoin github.com/eqzip/lostk \n\
";
// The owner's address
address public owner;
// This generates a public event on the blockchain that will notify clients
event Transfer(address indexed from, address indexed to, uint256 value);
// This notifies clients about the amount burnt
event Burn(string reason, uint256 value);
uint public fundingGoal;
uint public amountRaised;
uint public funderNumbers;
uint public deadline;
struct BalanceOfFounder{
uint256 _ether;
bool isSentToken;
}
// This creates an array with all balances of eqcoin, ether and if have sent token
mapping(address => BalanceOfFounder) public balanceOfEther;
token public tokenReward;
address public beneficiary;
bool burnedUnsaleToken = false;
event GoalReached(address recipient, uint totalAmountRaised);
// Milestone
string public milestone;
// Total supply
uint256 public totalSupply;
event Log(string log, address _address, uint256 value);
/**
* Constructor function
*
* Setup the owner
*/
function EqzipCrowdsale(
address ifSuccessfulSendTo,
uint fundingGoalInEthers,
uint durationInMinutes,
address addressOfTokenUsedAsReward
) public {
// For Eqzip crowdsale
beneficiary = ifSuccessfulSendTo;
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
tokenReward = token(addressOfTokenUsedAsReward);
totalSupply = tokenReward.getTotalSupply();
owner = msg.sender;
emit Log("cons", owner, 0);
// emit Log("cons", tokenReward.getOwner(), 1);
}
/**
* Fallback function
*
* The function without name is the default function that is called whenever anyone sends funds to a contract
*/
function () beforeDeadline public payable {
balanceOfEther[msg.sender]._ether += msg.value;
balanceOfEther[msg.sender].isSentToken = false;
amountRaised += msg.value;
beneficiary.transfer(msg.value);
emit GoalReached(msg.sender, msg.value);
}
modifier afterDeadline() { if (now > deadline) _; }
modifier beforeDeadline() { if (now <= deadline) _; }
function getReward() afterDeadline public {
emit Log("getReward", owner, 0);
// require(!balanceOfEther[msg.sender].isSentToken);
// save investment value
// uint256 amount = balanceOfEther[msg.sender]._ether;
emit Log("getReward after require", msg.sender, 1);
// because have sent the token to founder so set isSentToken to true to void get multiply reward
balanceOfEther[msg.sender].isSentToken = true;
// if amount raised less than founding goal then burn un sold token and reduce the total supply
// if((amountRaised < fundingGoal) && !burnedUnsaleToken){
// burnedUnsaleToken = true;
// // totalSupply = (totalSupply*amountRaised)/fundingGoal;
// // balanceOf[owner] = totalSupply;
// // emit Burn("Token not sold out all the sold value is", totalSupply);
// }
if(amountRaised < fundingGoal && !burnedUnsaleToken){
burnedUnsaleToken = true;
totalSupply = (totalSupply*amountRaised)/fundingGoal;
emit Burn("Token not sold out all the sold value is", totalSupply);
}
emit Log("getReward tokenReward.transfer", msg.sender, 2);
tokenReward.transfer(msg.sender, (balanceOfEther[msg.sender]._ether*totalSupply)/amountRaised);
emit Log("getReward after tokenReward.transfer", msg.sender, 3);
// _transfer(owner, msg.sender, (amount*totalSupply)/amountRaised);
}
function getBalanceOfEther(address _address) public payable returns(uint256) {
emit Log("getBalanceOfEther", _address, balanceOfEther[_address]._ether);
return balanceOfEther[_address]._ether;
}
function updateMilestone(string str) public {
emit Log("updateMilestone", msg.sender, 0);
milestone = strConcat(milestone, "\n", toAsciiString(msg.sender), "\n", str);
}
function strConcat(string _a, string _b, string _c, string _d, string _e) internal pure returns (string){
bytes memory _ba = bytes(_a);
bytes memory _bb = bytes(_b);
bytes memory _bc = bytes(_c);
bytes memory _bd = bytes(_d);
bytes memory _be = bytes(_e);
string memory abcde = new string(_ba.length + _bb.length + _bc.length + _bd.length + _be.length);
bytes memory babcde = bytes(abcde);
uint k = 0;
for (uint i = 0; i < _ba.length; i++) babcde[k++] = _ba[i];
for (i = 0; i < _bb.length; i++) babcde[k++] = _bb[i];
for (i = 0; i < _bc.length; i++) babcde[k++] = _bc[i];
for (i = 0; i < _bd.length; i++) babcde[k++] = _bd[i];
for (i = 0; i < _be.length; i++) babcde[k++] = _be[i];
return string(babcde);
}
function toAsciiString(address x) internal pure returns (string) {
bytes memory s = new bytes(40);
for (uint i = 0; i < 20; i++) {
byte b = byte(uint8(uint(x) / (2**(8*(19 - i)))));
byte hi = byte(uint8(b) / 16);
byte lo = byte(uint8(b) - 16 * uint8(hi));
s[2*i] = char(hi);
s[2*i+1] = char(lo);
}
return string(s);
}
function char(byte b) internal pure returns (byte c) {
if (b < 10) return byte(uint8(b) + 0x30);
else return byte(uint8(b) + 0x57);
}
}