Hi @mickymax777,
That’s the correct modification to HelloWorld so that it inherits from the new separate contract, Destroyable.
Can we also see your code for Destroyable.sol? That’s the main part of this assignment.
Hi @mickymax777,
That’s the correct modification to HelloWorld so that it inherits from the new separate contract, Destroyable.
Can we also see your code for Destroyable.sol? That’s the main part of this assignment.
Nice solution @alegarap
What changes did you also have to make to HelloWorld in terms of inheritance?
Destroyable.sol
import"./Ownable.sol";
pragma solidity 0.5.12
contract Destroyable is Ownable{
function close() public onlyOwner{
selfdestruct(msg.sender);
}
}
I created a new contract (screenshot):
I added in the Hello World contract the DestroyContract contract
@ Filip
First I created the selfdestruct(owner); But solidity gave me this. I don’t understand because the owner variable is linked to an address?
Exactly right, @Ouzo69
Excellently presented solution, and well done for realising that, by using owner
instead of msg.sender
as the selfdestruct function’s argument, you needed to make owner
a payable address
I also noticed your very clever (and much more concise) alternative to the withdrawAll() function — impressive stuff
Hi @sajede.k,
When our derived contract HelloWorld (or in your case, contract map
) is deployed, there is only one contract that is deployed, not three separate ones. The fact that we have written 3 contracts related to each other via inheritance, is purely a way of organising our code so that it is more modular and easier to maintain and develop further. The single HelloWorld contract that is deployed includes all of the inherited functionality of Ownable and Destroyable, as if this had been written within HelloWorld itself. So when HelloWorld is deployed and selfdestruct() is invoked, even though selfdestruct is physically written in Destroyable, practically, it’s as if it is being called within HelloWorld, and that’s the key to how it knows which contract to destroy.
Remember that all functions, state variables, mappings, events, modifiers and constructors are inherited with the exception of functions, state variables and mappings marked with private or external visibility.
Hi @Nicksta,
Your DestroyContract inherits Owner, and so (providing you haven’t made any additional modifications to Owner) the state variable address public owner
will automatically be available within DestroyContract — you don’t need to repeat it.
Everything else is correct
To understand this error, you first need to understand that addresses can be stored in variables as either payable, or non-payable. Unless we specifically mark them as payable, then they are non-payable by default.
The address argument passed to the selfdestruct function must be payable, because it is used to transfer the contract balance to that address. It works with msg.sender
, because if used directly as a value (and not first assigned to a variable) then msg.sender
is treated as a payable address by default in Solidity. You get the error with owner
because this is defined as a non-payable address in contract Owner. To define an address as payable, you need to explicitly add the payable keyword:
address payable public owner;
If you make this modification to the owner state variable definition in Owner, then it will work calling selfdestruct with owner
, as follows:
selfdestruct(owner);
Another alternative is to leave the owner state variable definition as non-payable, and convert it to a payable address directly within the selfdestruct function call in DestroyContract:
selfdestruct(address(uint160(owner)));
By the way, that’s fine to post a screen shot to show an error message, but please don’t post screen shots of your submitted code, because it’s not possible to copy and paste it in order to execute and test it, if necessary. It also can’t be quoted. In future, please post your code formatted in the usual way
I hope that’s clarified things for you. Just let us know if you have any further questions.
import “./Ownable.sol”;
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function destroy() public onlyOwner {
address payable receiver = msg.sender;
selfdestruct(receiver);
}
}
quick response!! Thanks a lot!!
Here is my Destroyable contract:
import "./ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function destroyContract() public onlyOwner{
selfdestruct(address(uint160(owner)));
}
}
And here is the new header for my main contract:
import "./ownable.sol";
import "./destroyable.sol";
pragma solidity 0.5.12;
contract mappingPractice is Ownable, Destroyable{
I got a compiler error regarding my Owner address in the selfdestruct(owner) function, so I used address(uint160()) to convert it into a payable address and it seemed to work fine after that.
//Ownable.sol
pragma solidity 0.5.12;
contract Ownable{
address payable public owner;
constructor() public{
owner = msg.sender;
}
modifier onlyOwner(){
require(msg.sender == owner);
_; //Continue execution
}
}
//Destroyable.sol
import “./Ownable.sol”;
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function stopContract() public onlyOwner {
selfdestruct(owner);
}
}
//HelloWorld.sol
import “./Ownable.sol”;
import “./Destroyable.sol”;
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyable{
…
…
This is my code if I didn’t have a separate Ownable contract:
pragma solidity 0.5.12;
contract Destroyable {
address public owner;
constructor() public {
owner = msg.sender;
}
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
function close(address) public onlyOwner {
selfdestruct(msg.sender);
}
}
then add to the top of HelloWorld contract : import “./Destroyable.sol”;
Hello,
thanks a lot for taking time.
Hello @MrSeven , hope you are great.
Now a few comments on your code:
Meaning, your close
function ask for a argument (address
) that is never used in the function, this will trigger an error.
I advice to follow the video lesson closely, create your own Ownable contract has filip goes, if not, you might run into many issues later in the course without a way to compare with filip lessons.
If you have any more questions, please let us know so we can help you!
Carlos Z.
I get an error with this code.
pragma solidity 0.5.1;
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(owner);
}
}
Hello @oneworldcoder, hope you are good.
Your Destroyable
contract is Ownable
, but you are not importing the Ownable
contract into your code. Maybe you want to check the video lesson again, it is important to understand those kind of little details.
If you have any more questions, please let us know so we can help you!
Carlos Z.
Create the Destroyable.sol contract and called it from Hello_World.sol
import "./00_Ownable.sol";
import "./00_Destroyable.sol";
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyable{..}
The Destroyable.sol fil is:
import "./00_Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function close() public onlyOwner { // onlyOwner is custom modifier
selfdestruct(msg.sender);
}
}
I will check why I couldn’t only use owner variable directly, and only run by using msg.sender
selfdestruct(owner);
EDITED: I’ve got it from solution video. owner is not payable, so I need it to change it before.
Hey @oneworldcoder,
As well as the point that @thecil makes:
… you may find that you still get an error with owner
as the argument in the selfdestruct function call. If you do, it’s because owner
is defined as a non-payable address in contract Ownable:
address public owner;
Addresses can be stored in variables as either payable, or non-payable. Unless we specifically mark them as payable, then they are non-payable by default.
The address argument passed to the selfdestruct function must be payable, because it is used to transfer the contract balance to that address. It would work with msg.sender
, because if used directly as a value (and not first assigned to a variable), then msg.sender
is treated as a payable address by default in Solidity. To define an address as payable, you need to explicitly add the payable keyword:
address payable public owner;
I hope that helps you to understand another possible reason for the error you were getting.
Well done @josephg for finding the answer to your question
That’s right — owner
is defined as a non-payable address in contract Ownable:
address public owner;
Addresses can be stored in variables as either payable, or non-payable. Unless we specifically mark them as payable, then they are non-payable by default.
The address argument passed to the selfdestruct function must be payable, because it is used to transfer the contract balance to that address. It works with msg.sender
, because if used directly as a value (and not first assigned to a variable), then msg.sender
is treated as a payable address by default in Solidity. To define an address as payable, you need to explicitly add the payable keyword:
address payable public owner:
Also, take a look at this post — it explains how you can make an additional adjustment to HelloWorld in terms of the inheritance. I think you’ll find it interesting