Hi @jon_m,
Does this mean that if I pass owner instead of the msg.sender, I will destroy the owner not the subject I wanted to delete?
Destroyable.sol:
import "./Ownable.sol";
pragma solidity ^0.5.12;
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(owner);
}
}
Helloworld.sol
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity ^0.5.12;
contract HelloWorld is Ownable, Destroyable {}
Destroyable.sol contract:
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}
Remix seemed to give some cautionary flag for the above suggesting the address âownerâ was not a payable address and so I then converted it as Fillip had mentioned previously. This solved any warning remix was giving.
HelloWorld.sol contract:
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyable{
Hi @Jun_0113
No⌠the address you pass into selfdestruct() as the argument wonât be destroyed. The selfdestruct function destroys the contract (in this case HelloWorld, as thatâs the contract weâve deployed and from where we are calling the inherited selfdestruct function). The address argument is where the contractâs ETH balance is transferred upon destruction (so these funds arenât lost). Because this address is used to receive a payment, it needs to be a payable address.
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. When msg.sender
is used directly as a value (and not first assigned to a variable), it is treated as a payable address by default in Solidity, so thatâs whyâ selfdestruct(msg.sender)
âworks without having to add anything further or make any additional modifications. If you do the same withâowner
âthe compiler will give you an error, because it is defined as a non-payable address in contract Ownable:
address public owner;
You can still use owner
but you will need to also define it as a payable address by explicity adding the payable keyword:
address payable public owner;
If you make this modification to the owner state variable definition in Ownable, thenâ selfdestruct(owner);
âwill work.
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 contract Destroyable:
selfdestruct(address(uint160(owner)));
I hope that makes things clearer. But just let us know if you have any further questions.
My solution:
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function close() public onlyOwner {
selfdestruct(owner);
}
}
In Ownable contract I changed the owner variable to payable:
address payable public owner;
And I added inheritance from Destroyable to HelloWorld:
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;
contract HelloWrold is Ownable, Destroyable{
//the rest of the code
}
I think it works.
function destroyContract() public onlyOwner {
//We have already required that only the owner can change this code so is msg.sender isnât equal to owner it will throw an exception
selfdestruct(msg.sender);
}
My solution
pragma solidity 0.5.12;
import './Ownable.sol';
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(msg.sender);
}
}
I have a question @filip
Why I cant use owner instead of msg.sender ? It is definied in Ownable contract, so I thought that I can use, but it seams its not inherit from Ownable contract why ?
My Ownable contract here
pragma solidity 0.5.12;
contract Ownable{
address public owner;
modifier onlyOwner(){
require(msg.sender == owner);
_; //Continue execution
}
constructor() public{
owner = msg.sender;
}
}
Edit:
I found I need to cast it payble address
pragma solidity 0.5.12;
import './Ownable.sol';
contract Destroyable is Ownable {
function close() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}
Is there any other solution ? can the owner be as payble on Ownable contract ? so casting is not needed ?
I have owner as internal in Ownable contract, but still cant use it in Destroyable contract
You also can define your owner
address as payable at the begining of your Ownable
contract in order to avoir the conversion (address(uint160(owner)))
.
You can just use address payable public owner
, then in your close
function does not need the conversion.
Carlos Z
Destroyable.sol
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable {
function selfDestruct() public onlyOwner {
selfdestruct(address(uint160(owner)));
}
}
HelloWorld.sol
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;
contract HelloWorld is Ownable, Destroyable {
// STATE VARIABLES
uint private balance;
...
}
I created a new contract called âDestroyable.solâ. In it I created the following code:
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function shutdown() public onlyOwner {
selfdestruct(owner);
}
}
In the main file I added
import "./Destroyable.sol";
Also in the contract header I added the âDestroyableâ child contract.
contract HelloWorld is Ownable, Destroyable{
I also had to update the Ownable.sol file to make the owner address payable.
Destroyable Contract
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function close() public onlyOwner {
selfdestruct(owner);
}
}
To be able to send funds from the contract to the owner, the address needed to be payable
address payable public owner;
Next the steps for the HelloWorld Contract
import "./Ownable.sol";
import "./Destroyable.sol";
Deploy contract, create a person, then destroy this contract and send funds to owner.

After destroy ^ Funds are back to the owner >

Destroyable contract
HelloWorld contract
import â./Ownable.solâ;
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function selfImmolate() public onlyOwner {
selfdestruct(msg.sender);
}
}
import â./Ownable.solâ;
pragma solidity 0.7.3;
contract Destroyable is Ownable{
function close() public onlyOwner {
selfdestruct(owner);
}
}
in HellowWorld
import â./Ownable.solâ;
import â./Destroyable.solâ;
pragma solidity 0.7.3;
contract HelloWorld is Ownable, Destroyable{
in Ownable.sol I needed to change owner to payable:
address payable owner;
Hey all, really enjoyed this assignmentâŚ
Here is what i have conjured upâŚ
My Ownable Contract
pragma solidity 0.5.12;
contract Ownable{
address public owner;
modifier onlyOwner(){
require(msg.sender == owner);
_; //Continue execution
}
constructor() public{
owner = msg.sender;
}
}
Destroyable Contract
import "./Ownable.sol";
pragma solidity 0.5.12;
contract Destroyable is Ownable{
function kill() public onlyOwner {
selfdestruct(msg.sender);
}
}
And my Hello World
import "./Ownable.sol";
import "./Destroyable.sol";
pragma solidity 0.5.12;
contract HelloWorld is Ownable {
struct Person {
uint id;
string name;
uint age;
uint height;
bool senior;
}
event personCreated(string name, bool senior);
event personDeleted(string name, bool senior, address deletedBy);
uint public balance;
modifier costs(uint cost){
require(msg.value >= cost);
_;
}
mapping (address => Person) private people;
address[] private creators;
function createPerson(string memory name, uint age, uint height) public payable costs(1 ether){
require(age < 150, "Age needs to be below 150");
require(msg.value >= 1 ether);
balance += msg.value;
//This creates a person
Person memory newPerson;
newPerson.name = name;
newPerson.age = age;
newPerson.height = height;
if(age >= 65){
newPerson.senior = true;
}
else{
newPerson.senior = false;
}
insertPerson(newPerson);
creators.push(msg.sender);
assert(
keccak256(
abi.encodePacked(
people[msg.sender].name,
people[msg.sender].age,
people[msg.sender].height,
people[msg.sender].senior
)
)
==
keccak256(
abi.encodePacked(
newPerson.name,
newPerson.age,
newPerson.height,
newPerson.senior
)
)
);
emit personCreated(newPerson.name, newPerson.senior);
}
function insertPerson(Person memory newPerson) private {
address creator = msg.sender;
people[creator] = newPerson;
}
function getPerson() public view returns(string memory name, uint age, uint height, bool senior){
address creator = msg.sender;
return (people[creator].name, people[creator].age, people[creator].height, people[creator].senior);
}
function deletePerson(address creator) public onlyOwner {
string memory name = people[creator].name;
bool senior = people[creator].senior;
delete people[creator];
assert(people[creator].age == 0);
emit personDeleted(name, senior, owner);
}
function getCreator(uint index) public view onlyOwner returns(address){
return creators[index];
}
function withdrawAll() public onlyOwner returns(uint) {
uint toTransfer = balance;
balance = 0;
msg.sender.transfer(toTransfer);
return toTransfer;
}
}
Adding further to this brilliant task⌠I found when deploying my Hello World Contract that my âKILLâ Function was not showing on it.
When i dived deeper to figure out what was missing my âHello Worldâ contract has Ownable Inherited to it and not Destroyable. This ment that âKILLâ would not appear when deployed.
Other than that it feels good to actually now look at a problem and be able to work out what is wrong.
Thanks @thecil
By far the best course yet !!!
Rob.
Here is my code for Destroyable contract:
import â./Ownable.solâ;
pragma solidity 0.5.12;
contract Destroyable is Ownable{
modifier onlyOwner(){
require(msg.sender == owner);
_;
}
constructor() public{
owner = msg.sender;
}
function close() public onlyOwner { //onlyOwner is custom modifier
selfdestruct(0x5B38Da6a701c568545dCfcB03FcB875f56beddC4); // owner
is the owners address
}
}
Soooo happy I solved this all by myself!! Getting better at this!! Not completely sure I should have the actual address in the contract as opposed to a variable holding the owners address, but I kept getting the error for the address being not payable and could not seem to figure out how to convert it, at least this code compiled.
Youn have 2 options to fix the message of a payable addressâŚ
You also can define your owner
address as payable at the begining of your Ownable
contract in order to avoir the conversion (address(uint160(owner)))
.
You can just use address payable public owner
, then in your close
function does not need the conversion.
Carlos Z
// Destroyable.sol:
pragma solidity 0.5.12;
import â./Ownable.solâ;
contract Destroyable is Ownable{
/// destroy the contract by providing the owner address.
function killContract(address ownerAddress) public onlyOwner{
require(msg.sender == ownerAddress);
selfdestruct(msg.sender);
}
}