Smart contract Ethereum - How to recreate same contract after used selfDestruct() - function

Is it possible to destroy (using selftDestruct function) and generate the same contract at the same time ?
We assume that the first contract is to have 1Eth and then withdraw all eth to another erc20 address, after the complete withdrawal, the first contract calls the selfdestruct function and then the same contract is redeployed, and that in a loop.
Maybe the simply way is to use a conditional function?

Not possible "at the same time", need to do it in separate transactions.
selfdestruct prevents later operations on the contract from being executed, and flags the contract for deletion.
selfdestruct stops the execution in its current scope, and flags the contract for deletion.
However, the EVM doesn't delete its bytecode until the end of processing of the transaction. So you won't be able to deploy new bytecode to the same address until the next tx. But you're still able to perform calls on the to-be-destructed contract.
pragma solidity ^0.8;
contract Destructable {
function destruct() external {
selfdestruct(payable(msg.sender));
}
}
contract Deployer {
function deployAndDestruct() external {
Destructable destructable = new Destructable{salt: keccak256("hello")}();
destructable.destruct();
// The second deployment (within the same transation) causes a revert
// because the bytecode on the desired address is still non-zero
Destructable destructable2 = new Destructable{salt: keccak256("hello")}();
}
}
pragma solidity 0.8.17;
contract Destructable {
uint public number = 1;
function destruct() external {
selfdestruct(payable(msg.sender));
number++; // not executed after selfdestruct
}
}
contract Caller {
Destructable destructable;
constructor(Destructable _destructable) {
destructable = _destructable;
}
function executeSequence() external {
destructable.destruct();
// successfully call after the selfestruct was initiated
uint returnedNumber = destructable.number();
require(returnedNumber == 1);
}
}

Related

Error message while executing solidity contract

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 {
}
}

Rinkeby Smart Contract

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.

What is the use of Uniswap Router Initialization in a Token Contract

I just started on building Tokens using ETH & BSC, this is one statement which I see in many Contracts.
Inside the Constructor method, the Uniswap router is iniliazed probably with the V2 version. What is the use of this?
constructor () public {
_rOwned[_msgSender()] = _rTotal;
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
// Create a uniswap pair for this new token
uniswapV2Pair = IUniswapV2Factory(_uniswapV2Router.factory())
.createPair(address(this), _uniswapV2Router.WETH());
// set the rest of the contract variables
uniswapV2Router = _uniswapV2Router;
Why is this initialization required? What is the functionality of this?
Appreciate if someone could help.
Thanks
IUniswapV2Router02 _uniswapV2Router = IUniswapV2Router02(0x10ED43C718714eb63d5aA57B78B54704E256024E);
This line initializes a pointer to the 0x10ED... address and expects the contract (deployed at the 0x10ED... address) to implement the IUniswapV2Router02 interface.
The interface is defined somewhere with the caller contract source code.
It allows you to execute and call functions defined by the interface instead of building low-level calls. It also allows you to use the returned datatypes instead of parsing the returned binary.
Example:
pragma solidity ^0.8.5;
interface IRemote {
function foo() external view returns (bool);
}
contract MyContract {
IRemote remote;
constructor() {
remote = IRemote(address(0x123));
}
function getFoo() external view returns (bool) {
bool returnedValue = remote.foo();
return returnedValue;
}
}

Execute solidity contract methods from specific account on Ethereum Remix JavaScript VM

I currently make a test contract on ethereum.remix.org.
But how can I specify the account in the test file from which a contract call should be sent?
contract test {
MyContract contract;
address creator = address(0);
address payable account2 = address(1);
address payable account3 = address(2);
address payable account4 = address(3);
function beforeAll () public {
contract = new MyContract();
}
function makeCallFromAccount2 () {
contract.function1(10);
}
}
How can I specify that contract.function1(10) is executed from account 2?
(This is important because the contract method uses the msg.sender value)
Apparently you can do this though there is little documentation on how to use:
https://github.com/ethereum/remix/tree/master/remix-tests#use-a-different-sender-msgsender

Questions on MinterRole contract in openzeppelin

I am using the openzeppelin for creating the ICO contract. I am concerned about the MinterRole here. After I develop Token contract, I added the sale contract as a minter using "addMinter" function.
Question
After the sale is over
I do not see a way to remove the contract address as a minter. I see that "renounceMinter" will remove only the person's who is calling this method.
I understand even If I remove (or) not remove the contract address as a minter at that point (i.e., after the sale is over) the Sale contract will b defined in such a way that it will not work at all. is it safe even if we leave the contract address in the minter list ?
Why openzeppelin has designed the "MinterRole" contract with the "renounceMinter" function that can remove only the person who is calling that contract but the function "addMinter" can do this for others also ?
Code
SampleCrowdsale
contract SampleCrowdsale is FinalizableCrowdsale, MintedCrowdsale
MintedCrowdsale
contract MintedCrowdsale is Crowdsale {
constructor() internal {}
function _deliverTokens(
address beneficiary,
uint256 tokenAmount
)
internal
{
// Potentially dangerous assumption about the type of the token.
require(
ERC20Mintable(address(token())).mint(beneficiary, tokenAmount));
}
}
ERC20Mintable
contract ERC20Mintable is ERC20, MinterRole
MinterRole
pragma solidity ^0.4.24;
import "../Roles.sol";
contract MinterRole {
using Roles for Roles.Role;
event MinterAdded(address indexed account);
event MinterRemoved(address indexed account);
Roles.Role private minters;
constructor() internal {
_addMinter(msg.sender);
}
modifier onlyMinter() {
require(isMinter(msg.sender));
_;
}
function isMinter(address account) public view returns (bool) {
return minters.has(account);
}
function addMinter(address account) public onlyMinter {
_addMinter(account);
}
function renounceMinter() public {
_removeMinter(msg.sender);
}
function _addMinter(address account) internal {
minters.add(account);
emit MinterAdded(account);
}
function _removeMinter(address account) internal {
minters.remove(account);
emit MinterRemoved(account);
}
}