I want to send erc20 tokens to contract address which is able to trade the token.
However, I failed the test and error says
Error: VM Exception while processing transaction: revert
My function is this
TokenSale.sol
function startSale(address _tokenSaleContractAddress) public {
require(msg.sender == admin);
require(tokenContract.transfer(_tokenSaleContractAddress, 750000));
}
MyToken.sol
function transfer(address _to, uint256 _value) public returns (bool success) {
require(balanceOf[msg.sender] >= _value);
balanceOf[msg.sender] -= _value;
balanceOf[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
}
My test is this
it('facilitates start sale', function() {
return MyToken.deployed().then(function(instance) {
tokenInstance = instance;
return TokenSale.deployed()
}).then(function(instance) {
tokenSaleInstance = instance;
return tokenSaleInstance.startSale(tokenSaleInstance.address, {from: admin} )
}).then(function(receipt) {
return tokenInstance.balanceOf(tokenSaleInstance.address)
}).then(function(balance) {
assert.equal(balance.toNumber, 750000);
});
});
Could you give me any advise why I failed the test?
Admin has 1000000 tokens, and I want to send 750000 tokens to TokenSale contract.
To do this, the admin needs to call transfer on the token contract. I.e. your test code should have this in it:
tokenInstance.transfer(tokenSaleInstance.address, 750000, { from: admin });
After that, calling startSale should succeed, but there's no reason to call it because it's just transferring 750,000 tokens to itself.
Related
I have the following smart contract:
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./MyCoinSupply.sol";
contract MyCoinDEX
{
IERC20 public token;
event Bought(uint256 amount);
event Sold(uint256 amount);
constructor() public
{
token = new MyCoinSupply();
}
function getSenderAddress() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function getAddress() public view returns (address)
{
return address(this);
}
function getTokenAddress() public view returns (address)
{
return address(token);
}
function buy() payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
uint256 amountTobuy = msg.value;
uint256 dexBalance = token.balanceOf(address(this));
require(amountTobuy > 0, "You need to send some ether");
require(amountTobuy <= dexBalance, "Not enough tokens in the reserve");
token.transfer(msg.sender, amountTobuy);
emit Bought(amountTobuy);
}
function sell(uint256 amount) public // send tokens to get ether back
{
require(amount > 0, "You need to sell at least some tokens");
uint256 allowance = token.allowance(msg.sender, address(this));
require(allowance >= amount, "Check the token allowance");
token.transferFrom(msg.sender, address(this), amount);
// https://stackoverflow.com/questions/67341914/error-send-and-transfer-are-only-available-for-objects-of-type-address-payable
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
if I call the buy() method from truffle console, it executes without any exceptions:
truffle(development)> MyCoinDEX.buy({value: 1})
I verified that the account calling the buy() method receives the token. However, the balance of Ether in Ganache for the account calling the buy() method doesn't decrease. So essentially, the account is getting tokens for free.
What's going on here? How do I fix it?
I am not sure but it would be necessary to investigate about the balance of the contract account. The gas for token.transfer might be paid by the contract account balance, since the contract account is the transaction sender for token contract.
Or the balance decrement would be unnoticeable because it is too small.
I would be happy to know about the answer if you have found out.
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
I need to send ether from externally owned account to contract.
All code I found so far looks like this
contract Contract {
mapping (address => uint) balances;
event Transfer(address indexed _from, uint256 _value);
function deposit() public returns (uint) {
balances[msg.sender] += msg.value;
Transfer(msg.sender, msg.value);
return balances[msg.sender];
}
}
But I can not understand how does it work. I thought it should look like this: we should run some send function which will take current contract address, sender address and amount.
Can someone explain me the logic behind it?
I also found the solution which correspond to this logic
contract Contract {
function pay() payable {}
}
and than call it from console like that
var contract
Contract.deployed().then(function(instance) { contract = instance; })
contract.pay.sendTransaction({from: eoa_address,to: contract_address,value: web3.toWei(amount,"ether"), gas:1000000})
But in this case sendTransaction function called outside of contact.
Is there any way of calling it like from this perspective inside contract?
to send Ether to a contract :
we could create a payable function if we need to pay to execute this function
contract Contract {
function do_somthing() payable {
action1
action2
...
}
}
if we want to just send ethers to the contract without executing any function we define the fallback function as you presented in your question :
contract Contract {
function pay() payable {}
}
the example you have provided before :
contract Contract {
mapping (address => uint) balances;
event Transfer(address indexed _from, uint256 _value);
function deposit() public returns (uint) {
balances[msg.sender] += msg.value;
emit Transfer(msg.sender, msg.value);
return balances[msg.sender];
}
}
is recording the balances sent by the users to the contract (this function needs to be declared as payable for the recent compiler : function deposit() public payable returns)
function deposit() public payable returns (uint) {
balances[msg.sender] += msg.value;
emit Transfer(msg.sender, msg.value);
return balances[msg.sender];
}
I'm trying to set up a basic crowdsale at ethereum testnet and the solidity code I'm using is the basic examples found at
https://ethereum.org/crowdsale#the-code
with steps followed as described in that guide.
The issue first was that the ethereum wallet doesn't accept the code as is to compile due to the first line:
contract token { function transfer(address receiver, uint amount){ } }
Specifically, its function returns a warning of an unused local variable and won't compile. Is there a way around this other than defining empty variables inside the function?
The second issue is after it's deployed with the modification as mentioned above, it works. But when it sends tokens to the wallet that sent the ether, the amount is always locked at 0.00 tokens.
FULL CODE:
pragma solidity ^0.4.2;
contract token { function transfer(address receiver, uint amount){ receiver; amount; } }
contract Crowdsale {
address public beneficiary;
uint public fundingGoal; uint public amountRaised; uint public deadline; uint public price;
token public tokenReward;
mapping(address => uint256) public balanceOf;
bool fundingGoalReached = false;
event GoalReached(address beneficiary, uint amountRaised);
event FundTransfer(address backer, uint amount, bool isContribution);
bool crowdsaleClosed = false;
/* data structure to hold information about campaign contributors */
/* at initialization, setup the owner */
function Crowdsale(
address ifSuccessfulSendTo,
uint fundingGoalInEthers,
uint durationInMinutes,
uint etherCostOfEachToken,
token addressOfTokenUsedAsReward
) {
beneficiary = ifSuccessfulSendTo;
fundingGoal = fundingGoalInEthers * 1 ether;
deadline = now + durationInMinutes * 1 minutes;
price = etherCostOfEachToken * 1 ether;
tokenReward = token(addressOfTokenUsedAsReward);
}
/* The function without a name is the default function that is called whenever anyone sends funds to a contract */
function () payable {
if (crowdsaleClosed) throw;
uint amount = msg.value;
balanceOf[msg.sender] = amount;
amountRaised += amount;
tokenReward.transfer(msg.sender, amount / price);
FundTransfer(msg.sender, amount, true);
}
modifier afterDeadline() { if (now >= deadline) _; }
/* checks if the goal or time limit has been reached and ends the campaign */
function checkGoalReached() afterDeadline {
if (amountRaised >= fundingGoal){
fundingGoalReached = true;
GoalReached(beneficiary, amountRaised);
}
crowdsaleClosed = true;
}
function safeWithdrawal() afterDeadline {
if (!fundingGoalReached) {
uint amount = balanceOf[msg.sender];
balanceOf[msg.sender] = 0;
if (amount > 0) {
if (msg.sender.send(amount)) {
FundTransfer(msg.sender, amount, false);
} else {
balanceOf[msg.sender] = amount;
}
}
}
if (fundingGoalReached && beneficiary == msg.sender) {
if (beneficiary.send(amountRaised)) {
FundTransfer(beneficiary, amountRaised, false);
} else {
//If we fail to send the funds to beneficiary, unlock funders balance
fundingGoalReached = false;
}
}
}
}
EDIT: I forgot to mention the steps leading to this point aka Token creation / shareholder association work with the code as is provided in the guide.
I came across the same issue. I solved it by actually defining the transfer function as the example from ethereum.org provides an empty one.
I replaced this:
contract token { function transfer(address receiver, uint amount){ } }
By this:
contract token {
event Transfer(address indexed from, address indexed to, uint256 value);
function transfer(address _to, uint256 _value) {
if (_to == 0x0) throw;
Transfer(msg.sender, _to, _value);
}
}
For your second problem, do you actually have a confirmation that the token created were actually sent? How many ether did you send to the crowd-sale contract? It seems that you are using two decimals for your token and if you defined "Ether cost of each token" of 5 like in the example, you shouldn't send less than 0.05 ether to the crowd-sale contract.
Hope it helps!
New to solidity and geth for my traineeship, I started deploying contrcts using the solidity online IDE and the geth dev mode. My problem is I tried a few different ways to do it but nothing seems to really work.
Code:
contract Transaction {
address public owner;
mapping (address => uint) public balances;
function Transaction () {
owner = msg.sender;
}
function validateTransaction (address receiver, uint amount) constant returns (bool) {
if (balances[owner] < amount || owner == receiver || amount == 0)
return (false);
balances[owner] -= msg.value;
return (true);
}
function transact (address receiver, uint amount) {
if (!validateTransaction(receiver, amount))
return ;
balances[receiver] += msg.value;
}
function remove () {
if (msg.sender == owner)
selfdestruct(owner);
}
}
I also tried this contract of a solidity tutorial but it also don't work as I expected:
contract Coin {
// The keyword "public" makes those variables
// readable from outside.
address public minter;
mapping (address => uint) public balances;
// Events allow light clients to react on
// changes efficiently.
event Sent(address from, address to, uint amount);
// This is the constructor whose code is
// run only when the contract is created.
function Coin() {
minter = msg.sender;
}
function mint(address receiver, uint amount) {
if (msg.sender != minter) return;
balances[receiver] += amount;
}
function send(address receiver, uint amount) {
if (balances[msg.sender] < amount) return;
balances[msg.sender] -= amount;
balances[receiver] += amount;
Sent(msg.sender, receiver, amount);
}
}
I am just trying to make a smart contract that can make transactions between the sender and a receiver but the accounts balances don't move. Are that functions only abstract to learn how solidity works or can this really make the balances change ? Thanks for your answers :)
After have searched and work deeper on solidity I found that, indeed, this contract makes abstract transactions into HIS data. So the ether aren't truely sent and the balance variable is local to this contract.